/* ============================================================
   Motionary, demos H
   Collection Motion Systems, tokens et gouvernance
   ============================================================ */

.dsc .rw{display:flex;align-items:center;gap:8px}
.dsc .lb{font:600 9px/1 var(--mono);color:var(--ink-3);width:26px;text-align:right;font-style:normal}
.dsc .tk,.esc .tk,.dsl .tk,.ddu .tk{position:relative;display:block;height:8px;border-radius:4px;background:var(--s2);overflow:hidden}
.dsc .tk{width:80px}
.dsc .tk b,.dsl .tk b{position:absolute;inset:0;background:var(--lime);transform-origin:left;display:block}

/* ---------------- tokens et echelles ---------------- */
/* Ce qu un token achete est l INDIRECTION, et cela ne se voit qu en changeant
   la valeur. A 52 pour cent la valeur declaree passe de 150 a 400. Les trois
   premiers composants la referencent, leur balayage passe donc de 9 a 22
   points d un seul coup, ensemble, sans qu on les ait touches.
   Le quatrieme a son nombre ecrit en dur. Il garde ses 9 points pour
   toujours. C est le voisin qui RATE l effet, et c est la seule preuve
   possible, parce qu un token correct et un nombre en dur sont
   indiscernables tant que la valeur ne change pas.
   La valeur change a 52 et les balayages a 53, la cause precede l effet.
   La piste fait 64 et le mobile 10, la course vaut donc 54.
   La consigne nomme CINQ familles, duree, easing, delai, keyframe et
   ressort. La bande du bas en montre cinq, pas trois.
   Gele, les quatre composants seraient identiques et le token n aurait
   servi a rien. */
.mtk{display:flex;flex-direction:column;gap:6px;width:116px}
.mtk .tokrow{position:relative;display:flex;align-items:center;gap:6px;height:10px}
.mtk .nm{display:block;width:54px;font:700 6px/10px var(--mono);color:var(--lime);
  font-style:normal;letter-spacing:0;text-transform:none;flex:0 0 auto}
.mtk .val{position:relative;display:block;width:22px;height:10px}
.mtk .val i{position:absolute;left:0;top:0;display:block;width:22px;font:700 7px/10px var(--mono);
  color:var(--a2);font-style:normal;letter-spacing:0;text-transform:none;opacity:0}
.mtk .v1{animation:aMtkV1 4.6s steps(1,end) infinite}
.mtk .v2{animation:aMtkV2 4.6s steps(1,end) infinite}
.mtk .cmp{display:flex;align-items:center;gap:6px;height:8px}
.mtk .cmp em{display:block;width:10px;font:700 6px/8px var(--mono);font-style:normal;
  letter-spacing:0;text-transform:none;flex:0 0 auto}
.mtk .c1 em::before{content:"a";color:var(--lime)}
.mtk .c2 em::before{content:"b";color:var(--lime)}
.mtk .c3 em::before{content:"c";color:var(--lime)}
.mtk .raw em::before{content:"d";color:var(--a4)}
.mtk .tk{position:relative;display:block;width:64px;height:8px;border-radius:4px;
  background:var(--s2);flex:0 0 auto}
.mtk .tk b{position:absolute;left:0;top:0;display:block;width:10px;height:8px;border-radius:4px}
/* ils referencent le token, ils changent ensemble sans etre touches */
.mtk .f{background:var(--lime);animation:aMtkTok 4.6s cubic-bezier(.4,0,.2,1) infinite}
/* il a son nombre ecrit en dur, il ignore le changement */
.mtk .h{background:var(--a4);animation:aMtkHard 4.6s cubic-bezier(.4,0,.2,1) infinite}
.mtk .grp{display:flex;gap:3px;margin-top:2px}
.mtk .grp i{display:block;padding:2px 3px;border-radius:3px;background:var(--s2);
  font:600 6px/8px var(--mono);color:var(--ink-2);font-style:normal;letter-spacing:0;
  text-transform:none}
@keyframes aMtkV1{0%,51%{opacity:1}52%,100%{opacity:0}}
@keyframes aMtkV2{0%,51%{opacity:0}52%,94%{opacity:1}96%,100%{opacity:0}}
/* neuf points puis vingt deux, la course vaut 54 */
@keyframes aMtkTok{0%,5%{transform:translateX(0)}14%{transform:translateX(54px)}
  16%,53%{transform:translateX(0)}75%{transform:translateX(54px)}
  77%,100%{transform:translateX(0)}}
/* neuf points puis neuf points, il n a rien appris */
@keyframes aMtkHard{0%,5%{transform:translateX(0)}14%{transform:translateX(54px)}
  16%,53%{transform:translateX(0)}62%{transform:translateX(54px)}
  64%,100%{transform:translateX(0)}}

/* L echelle livree est 0 50 100 150 200 250 300 400 500 et 600. Elle
   COARSENE apres 300, et c est une vraie propriete qu il faut voir. Sur une
   course utile de 88 les barreaux tombent a 4 plus la milliseconde sur 600
   fois 88, soit 4 11 19 26 33 41 48 63 77 et 92. Les ecarts valent 7 8 7 7
   8 7 puis 15 14 15, la moitie de l echelle est deux fois plus large.
   En haut le curseur SNAPE. Il visite 150 300 500 et 100, donc les barreaux
   26 48 77 et 19, et son centre tombe exactement dessus chaque fois. Il est
   en steps, il ne se repose jamais entre deux barreaux, ce qui est
   litteralement ce que snapper veut dire.
   En bas le curseur est libre. Il visite 170 265 430 et 88, donc 29 43 67 et
   17. Aucune de ces quatre positions ne tombe sur un barreau, elles sont
   toutes entre deux. C est la valeur hors echelle que la revue doit refuser.
   Le curseur fait 8, sa translation vaut donc la position du barreau moins 4.
   Gele, les deux curseurs seraient a un endroit quelconque et on ne saurait
   pas lequel respecte l echelle. */
.dsc{display:flex;flex-direction:column;gap:8px;width:136px}
/* les barreaux, fixes, c est l echelle elle meme */
.dsc .lad{position:relative;display:block;width:96px;height:7px;margin-left:40px}
.dsc .lad i{position:absolute;top:0;display:block;width:1.5px;height:7px;background:var(--s4)}
.dsc .t1{left:3.25px}
.dsc .t2{left:10.25px}
.dsc .t3{left:18.25px}
.dsc .t4{left:25.25px}
.dsc .t5{left:32.25px}
.dsc .t6{left:40.25px}
.dsc .t7{left:47.25px}
.dsc .t8{left:62.25px}
.dsc .t9{left:76.25px}
.dsc .t10{left:91.25px}
.dsc .one{display:flex;align-items:center;gap:6px}
.dsc em{font:600 6px/8px var(--mono);font-style:normal;letter-spacing:0;text-transform:none;
  width:34px;flex:0 0 auto}
.dsc .ok em{color:var(--lime)}
.dsc .ko em{color:var(--a4)}
.dsc .tk{position:relative;display:block;width:96px;height:8px;border-radius:4px;
  background:var(--s2);flex:0 0 auto}
.dsc .kn{position:absolute;left:0;top:0;display:block;width:8px;height:8px;border-radius:4px}
/* en steps, il ne se repose jamais entre deux barreaux */
.dsc .ok .kn{background:var(--lime);animation:aDscSnap 4.4s steps(1,end) infinite}
/* libre, il se repose ou il veut, donc hors echelle */
.dsc .ko .kn{background:var(--a4);animation:aDscFree 4.4s cubic-bezier(.3,0,.2,1) infinite}
/* 150 300 500 100, soit les barreaux 26 48 77 19, moins 4 de demi curseur */
@keyframes aDscSnap{0%,8%{transform:translateX(22px)}30%{transform:translateX(44px)}
  54%{transform:translateX(73px)}78%,94%{transform:translateX(15px)}
  96%,100%{transform:translateX(22px)}}
/* 170 265 430 88, soit 29 43 67 17, aucun sur un barreau */
@keyframes aDscFree{0%,8%{transform:translateX(25px)}30%{transform:translateX(39px)}
  54%{transform:translateX(63px)}78%,94%{transform:translateX(13px)}
  96%,100%{transform:translateX(25px)}}

/* Les quatre courbes sont nommees par leur COMPORTEMENT et jamais par leurs
   nombres, ce qui est la deuxieme consigne. Aucune cubic-bezier n apparait a
   l ecran.
   La troisieme consigne est une CORRESPONDANCE, et c est ce que la scene
   demontre. Les quatre premieres rangees font chacune le travail pour lequel
   sa courbe est prevue, deceleration pour entrer, acceleration pour sortir,
   standard pour un deplacement, lineaire pour un rotatif et rien d autre.
   La cinquieme rangee entre avec l acceleration. Elle parcourt la MEME
   distance dans le MEME temps que la premiere, sur la meme keyframe, seule
   la courbe change. Elle arrive donc a pleine vitesse et s arrete net, alors
   que la premiere se pose. C est la seule facon de montrer qu une courbe
   n est pas un gout mais un role.
   Deux keyframes suffisent pour cinq rangees, une pour entrer et une pour
   sortir, et quatre fonctions de temps differentes. C est exactement ce
   qu une echelle fermee veut dire.
   La piste fait 60 et le mobile 10, la course vaut donc 50.
   Gele, les cinq rangees seraient au meme endroit et il ne resterait rien. */
.esc{display:flex;flex-direction:column;gap:8px;width:110px}
.esc .rw{display:flex;align-items:center;gap:6px;height:10px}
.esc em{font:600 6px/10px var(--mono);font-style:normal;letter-spacing:0;text-transform:none;
  width:44px;flex:0 0 auto}
.esc .r1 em,.esc .r2 em,.esc .r3 em,.esc .r4 em{color:var(--lime)}
.esc .ko em{color:var(--a4)}
.esc .tk{position:relative;display:block;width:60px;height:10px;border-radius:5px;
  background:var(--s2);flex:0 0 auto}
.esc .tk b{position:absolute;left:0;top:0;display:block;width:10px;height:10px;border-radius:5px;
  background:var(--lime)}
/* entrer, elle se pose */
.esc .r1 b{animation:aEscEnter 4.4s cubic-bezier(0,0,.2,1) infinite}
/* sortir, elle prend de la vitesse */
.esc .r2 b{animation:aEscMove 4.4s cubic-bezier(.4,0,1,1) infinite}
/* se deplacer, symetrique */
.esc .r3 b{animation:aEscMove 4.4s cubic-bezier(.4,0,.2,1) infinite}
/* un rotatif, et rien d autre, c est le seul emploi du lineaire */
.esc .r4 b{border-radius:3px;animation:aEscSpin 4.4s linear infinite}
/* entrer avec l acceleration, meme keyframe et meme duree que la premiere */
.esc .ko b{background:var(--a4);animation:aEscEnter 4.4s cubic-bezier(.4,0,1,1) infinite}
@keyframes aEscEnter{0%,19%{transform:translateX(50px)}60%,94%{transform:translateX(0)}
  96%,100%{transform:translateX(50px)}}
@keyframes aEscMove{0%,19%{transform:translateX(0)}60%,94%{transform:translateX(50px)}
  96%,100%{transform:translateX(0)}}
@keyframes aEscSpin{0%,19%{transform:translateX(0) rotate(0)}
  60%,94%{transform:translateX(50px) rotate(360deg)}
  96%,100%{transform:translateX(0) rotate(0)}}

/* Trois etages, et la consigne dit de rethemer en DEPLACANT le pointeur, pas
   en touchant les composants. La scene deplace donc le pointeur et rien
   d autre.
   En haut deux primitifs, 150 et 400. Au milieu deux fleches. Celle du
   token semantique se deplace de 150 vers 400 a 48 pour cent, une course de
   40, puisque les deux primitifs ont leurs centres a 16 et 56. Le pointeur
   fait 6, son bord gauche part donc de 13. Celle du
   composant qui court-circuite l etage reste sur 150 pour toujours.
   En bas, modal reference le token semantique, son balayage passe donc de 9
   a 22 points. Drawer est cable au primitif directement, il garde ses 9
   points. Le retheme a marche pour l un et pas pour l autre, sans qu aucun
   des deux n ait ete edite.
   C est la difference avec le token simple. Ici la VALEUR des primitifs ne
   change jamais, c est le POINTEUR qui bouge, et c est tout ce que le
   retheme fait.
   La piste fait 64 et le mobile 10, la course vaut donc 54.
   Gele, on ne verrait pas laquelle des deux fleches a bouge. */
.stz2{display:flex;flex-direction:column;align-items:flex-start;gap:5px;width:104px}
/* leur valeur ne change jamais, ce sont les primitifs */
.stz2 .prims{display:flex;gap:8px}
.stz2 .prims i{display:block;width:32px;padding:2px 0;border-radius:4px;background:var(--s2);
  font:700 7px/10px var(--mono);color:var(--ink-2);text-align:center;font-style:normal;
  letter-spacing:0;text-transform:none}
/* deux rangees de pointeurs, sans quoi les deux se superposeraient au pixel */
.stz2 .ptr{position:relative;display:block;width:72px;height:14px}
.stz2 .ptr i{position:absolute;left:13px;display:block;width:6px;height:6px}
/* le pointeur du token semantique, il se deplace de 40 */
.stz2 .mvp{top:0;background:var(--lime);clip-path:polygon(3px 0,6px 6px,0 6px);
  animation:aStkPtr 4.6s cubic-bezier(.2,1,.3,1) infinite}
/* le cablage direct du composant qui saute l etage, il ne bouge jamais */
.stz2 .fix{top:8px;box-sizing:border-box;border:1.5px solid var(--a4);border-radius:2px}
.stz2 .sem{display:block;padding:2px 5px;border-radius:4px;background:var(--lime);
  font:700 6px/8px var(--mono);color:var(--s0);font-style:normal;letter-spacing:0;
  text-transform:none}
.stz2 .one{display:flex;align-items:center;gap:6px;height:8px;margin-top:3px}
.stz2 em{font:600 6px/8px var(--mono);font-style:normal;letter-spacing:0;text-transform:none;
  width:34px;flex:0 0 auto}
.stz2 .ok em{color:var(--lime)}
.stz2 .ko em{color:var(--a4)}
.stz2 .tk{position:relative;display:block;width:64px;height:8px;border-radius:4px;
  background:var(--s2);flex:0 0 auto}
.stz2 .tk b{position:absolute;left:0;top:0;display:block;width:10px;height:8px;border-radius:4px}
/* il suit le token semantique, le retheme l atteint */
.stz2 .ok .tk b{background:var(--lime);animation:aStkSem 4.6s cubic-bezier(.4,0,.2,1) infinite}
/* il est cable au primitif, le retheme le manque */
.stz2 .ko .tk b{background:var(--a4);animation:aStkDirect 4.6s cubic-bezier(.4,0,.2,1) infinite}
/* 40 de course, les centres des deux primitifs sont a 16 et 56 */
@keyframes aStkPtr{0%,47%{transform:translateX(0)}54%,94%{transform:translateX(40px)}
  96%,100%{transform:translateX(0)}}
/* neuf points puis vingt deux */
@keyframes aStkSem{0%,5%{transform:translateX(0)}14%{transform:translateX(54px)}
  16%,50%{transform:translateX(0)}72%{transform:translateX(54px)}
  74%,100%{transform:translateX(0)}}
/* neuf points puis neuf points, le retheme ne l a pas touche */
@keyframes aStkDirect{0%,5%{transform:translateX(0)}14%{transform:translateX(54px)}
  16%,50%{transform:translateX(0)}59%{transform:translateX(54px)}
  61%,100%{transform:translateX(0)}}


/* Un token de transition est COMPOSITE, un nom qui se deplie en trois parts,
   et chaque part est un ALIAS et non une valeur recopiee. C est ce qui le
   separe du token semantique, qui empile des ETAGES alors que celui ci
   regroupe trois choses au meme niveau.
   Le nom porte son type a cote, transition, parce que c est le champ que le
   format W3C impose et que sans lui rien ne dit qu il y en a trois.
   A 20 le bloc se deplie sur trois rangees. La colonne de droite ne contient
   que des NOMS. Aucun nombre, aucune courbe ecrite en clair.
   La quatrieme rangee est en dehors du bloc et en pointille. Elle recopie une
   cubic-bezier au lieu de nommer une courbe. Elle est inerte du premier au
   dernier pour cent, parce qu une valeur recopiee ne suit plus rien, et c est
   exactement ce qu on perd en l ecrivant.
   Trois rangees de 10 avec deux ecarts de 4 font 38.
   Gele, on ne verrait pas qu un seul nom en contient trois. */
.ttk{display:flex;flex-direction:column;align-items:flex-start;gap:6px;width:112px}
.ttk .tok{display:flex;align-items:center;gap:5px;height:12px}
.ttk .tok em{display:block;font:700 7px/12px var(--mono);color:var(--lime);font-style:normal;
  letter-spacing:0;text-transform:none}
.ttk .ty{display:block;padding:2px 4px;border-radius:3px;background:var(--s2);
  font:600 6px/8px var(--mono);color:var(--ink-2);font-style:normal;letter-spacing:0;
  text-transform:none}
.ttk .parts{display:flex;flex-direction:column;gap:4px;height:0;overflow:hidden;
  animation:aTtkOpen 4.6s cubic-bezier(.3,0,.2,1) infinite}
.ttk .pt{display:flex;align-items:center;gap:4px;height:10px;flex:0 0 auto}
.ttk .pt em{display:block;width:34px;font:600 6px/10px var(--mono);color:var(--ink-2);
  font-style:normal;letter-spacing:0;text-transform:none;flex:0 0 auto}
.ttk .ar{display:block;width:8px;height:6px;background:var(--s4);
  clip-path:polygon(0 0,8px 3px,0 6px);flex:0 0 auto}
/* la colonne de droite ne contient que des noms */
.ttk .v{display:block;font:700 6px/10px var(--mono);color:var(--a2);letter-spacing:0;
  text-transform:none;white-space:nowrap}
/* une valeur recopiee ne suit plus rien, elle est donc inerte */
.ttk .ko{opacity:.75}
.ttk .ko em,.ttk .ko .v{color:var(--a4)}
.ttk .ko .ar{background:var(--a4)}
/* trois rangees de 10 et deux ecarts de 4 font 38 */
@keyframes aTtkOpen{0%,19%{height:0}30%,94%{height:38px}96%,100%{height:0}}

/* La consigne plafonne a 240 millisecondes, et la seule facon de montrer
   POURQUOI est de repeter l action. Les cinq traits du bas sont les appuis,
   a 8 18 28 38 et 48, soit un toutes les 10 points, ce qui vaut 440
   millisecondes.
   Le curseur doit franchir six positions de 16, donc 80 en tout.
   En haut, 240 millisecondes valent 5,5 points, la vitesse est donc de 16
   sur 5,5, soit 2,9 par point. L utilisateur en demande 1,6. L interface est
   plus rapide que la main, elle arrive a chaque position AVANT l appui
   suivant, et elle a fini a 53,5.
   En bas, 700 millisecondes valent 15,9 points, la vitesse tombe a 1 par
   point. C est moins que les 1,6 demandes, l interface ne rattrape jamais.
   Elle avance de 10 par appui la ou il en faudrait 16, et elle n arrive au
   bout qu a 88, soit 40 points apres le dernier appui, ce qui fait 1,76
   seconde de mouvement sans personne devant.
   700 millisecondes est la bande du motion expressif. La faute n est donc pas
   d avoir choisi une mauvaise duree, c est d avoir applique la bonne duree au
   mauvais endroit.
   Les appuis sont fixes, ils ne bougent pas, c est la cadence de la main.
   Gele, les deux rangees seraient au meme endroit et le plafond n aurait
   aucune justification. */
.pmo{display:flex;flex-direction:column;gap:7px;width:136px}
.pmo .one{display:flex;align-items:center;gap:6px}
.pmo em{font:600 6px/8px var(--mono);font-style:normal;letter-spacing:0;text-transform:none;
  width:30px;flex:0 0 auto}
.pmo .ok em{color:var(--lime)}
.pmo .ko em{color:var(--a4)}
.pmo .tk{position:relative;display:block;width:100px;height:8px;border-radius:4px;
  background:var(--s2);flex:0 0 auto}
.pmo .kn{position:absolute;left:0;top:0;display:block;width:8px;height:8px;border-radius:4px}
/* 2,9 par point, plus rapide que la main */
.pmo .ok .kn{background:var(--lime);animation:aPmoOk 4.4s cubic-bezier(.3,0,.2,1) infinite}
/* 1 par point, elle ne rattrape jamais */
.pmo .ko .kn{background:var(--a4);animation:aPmoKo 4.4s linear infinite}
/* la cadence de la main, fixe */
.pmo .tl{position:relative;display:block;width:100px;height:6px;margin-left:36px}
.pmo .tl i{position:absolute;top:0;display:block;width:1.5px;height:6px;background:var(--ink-3)}
.pmo .k1{left:8px}
.pmo .k2{left:18px}
.pmo .k3{left:28px}
.pmo .k4{left:38px}
.pmo .k5{left:48px}
/* six positions de 16, moins 4 de demi curseur, donc 4 20 36 52 68 et 84 */
@keyframes aPmoOk{0%,8%{transform:translateX(4px)}13.5%,18%{transform:translateX(20px)}
  23.5%,28%{transform:translateX(36px)}33.5%,38%{transform:translateX(52px)}
  43.5%,48%{transform:translateX(68px)}53.5%,94%{transform:translateX(84px)}
  96%,100%{transform:translateX(4px)}}
/* elle avance de 10 par appui la ou il en faudrait 16 */
@keyframes aPmoKo{0%,8%{transform:translateX(4px)}18%{transform:translateX(14px)}
  28%{transform:translateX(24px)}38%{transform:translateX(34px)}
  48%{transform:translateX(44px)}88%,94%{transform:translateX(84px)}
  96%,100%{transform:translateX(4px)}}

/* La bande expressive va de 240 a 700 millisecondes et la consigne demande
   une courbe prononcee ou un depassement. La scene montre les deux bouts de
   la bande et ce qui se passe en dessous.
   La cible est marquee a 80, c est la ou le bord gauche du mobile doit se
   poser. En haut, 500 millisecondes valent 11,4 points. Le mobile depasse
   jusqu a 88, soit 8 au-dela, un depassement de 10 pour cent, puis il
   revient se poser sur la cible.
   En bas, 120 millisecondes valent 2,7 points. Le mobile arrive sans
   depasser et sans qu on ait eu le temps de le suivre. Le trajet est le
   MEME, la cible est la meme, seule la duree change. Un moment qui n arrive
   qu une fois par session et que personne ne voit est un moment perdu.
   Le mobile fait 12, il va donc de 0 a 80 et son bord droit atteint 92 au
   repos et 100 au sommet du depassement, ce qui tient exactement dans la
   piste de 100.
   La cible est fixe, c est la valeur declaree.
   Gele, on ne saurait pas laquelle des deux arrive et laquelle passe. */
.xmo{display:flex;flex-direction:column;gap:8px;width:136px}
.xmo .one{display:flex;align-items:center;gap:6px}
.xmo em{font:600 6px/8px var(--mono);font-style:normal;letter-spacing:0;text-transform:none;
  width:30px;flex:0 0 auto}
.xmo .ok em{color:var(--lime)}
.xmo .ko em{color:var(--a4)}
.xmo .tk{position:relative;display:block;width:100px;height:10px;border-radius:5px;
  background:var(--s2);flex:0 0 auto}
.xmo .kn{position:absolute;left:0;top:0;display:block;width:12px;height:10px;border-radius:5px}
/* 11,4 points, et 8 de depassement, soit 10 pour cent */
.xmo .ok .kn{background:var(--lime);animation:aXmoOk 4.4s cubic-bezier(.3,0,.2,1) infinite}
/* 2,7 points, aucun depassement, et personne ne l a vu */
.xmo .ko .kn{background:var(--a4);animation:aXmoKo 4.4s cubic-bezier(.3,0,.4,1) infinite}
/* la cible, fixe, c est la valeur declaree */
.xmo .tg{position:absolute;left:80px;top:-3px;display:block;width:1.5px;height:16px;
  background:var(--s5)}
.xmo .note{display:block;font:600 6px/8px var(--mono);color:var(--ink-3);font-style:normal;
  letter-spacing:0;text-transform:none;width:auto}
@keyframes aXmoOk{0%,19%{transform:translateX(0)}27%{transform:translateX(88px)}
  33%,94%{transform:translateX(80px)}96%,100%{transform:translateX(0)}}
@keyframes aXmoKo{0%,19%{transform:translateX(0)}21.7%,94%{transform:translateX(80px)}
  96%,100%{transform:translateX(0)}}

/* Un seul multiplicateur, et TROIS reglages nommes. La scene en montre trois,
   pas un.
   Les trois pistes ont des durees de base differentes, 6, 10 et 16 points,
   parce que le multiplicateur porte sur la valeur PROPRE de chaque token et
   non sur une valeur unique. C est tout ce qui le separe d une simple duree
   globale.
   A x1, de 4 a 30, elles finissent a 10, 14 et 20. A x3, de 34 a 84, elles
   finissent a 52, 64 et 82, soit exactement trois fois leur duree. A x0,
   a 87, elles atteignent le bout en un demi point, soit 22 millisecondes,
   ce qui est le reglage de reduced motion.
   Les trois se declenchent au MEME instant dans chaque phase, ce qui rend le
   rapport des trois durees lisible d un coup d oeil.
   La piste fait 96 et le mobile 10, la course vaut donc 86.
   Gele, on ne verrait ni le rapport de trois ni le zero. */
.dsl{display:flex;flex-direction:column;gap:7px;width:96px}
.dsl .sc{position:relative;display:block;height:12px}
.dsl .sc em{position:absolute;left:0;top:0;font:800 10px/12px var(--mono);font-style:normal;
  letter-spacing:0;text-transform:none;opacity:0}
.dsl .s1{color:var(--lime);animation:aDslS1 4.4s steps(1,end) infinite}
.dsl .s2{color:var(--a2);animation:aDslS2 4.4s steps(1,end) infinite}
.dsl .s3{color:var(--a4);animation:aDslS3 4.4s steps(1,end) infinite}
.dsl .tk{position:relative;display:block;width:96px;height:8px;border-radius:4px;
  background:var(--s2)}
.dsl .tk b{position:absolute;left:0;top:0;display:block;width:10px;height:8px;border-radius:4px;
  background:var(--lime)}
/* base 6 points, donc 18 a x3 */
.dsl .l1 b{animation:aDslL1 4.4s cubic-bezier(.4,0,.2,1) infinite}
/* base 10 points, donc 30 a x3 */
.dsl .l2 b{animation:aDslL2 4.4s cubic-bezier(.4,0,.2,1) infinite}
/* base 16 points, donc 48 a x3 */
.dsl .l3 b{animation:aDslL3 4.4s cubic-bezier(.4,0,.2,1) infinite}
@keyframes aDslS1{0%,3%{opacity:0}4%,30%{opacity:1}31%,100%{opacity:0}}
@keyframes aDslS2{0%,33%{opacity:0}34%,84%{opacity:1}85%,100%{opacity:0}}
@keyframes aDslS3{0%,86%{opacity:0}87%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aDslL1{0%,3%{transform:translateX(0)}10%,33%{transform:translateX(86px)}
  34%{transform:translateX(0)}52%,86%{transform:translateX(86px)}
  87%{transform:translateX(0)}87.5%,94%{transform:translateX(86px)}
  96%,100%{transform:translateX(0)}}
@keyframes aDslL2{0%,3%{transform:translateX(0)}14%,33%{transform:translateX(86px)}
  34%{transform:translateX(0)}64%,86%{transform:translateX(86px)}
  87%{transform:translateX(0)}87.5%,94%{transform:translateX(86px)}
  96%,100%{transform:translateX(0)}}
@keyframes aDslL3{0%,3%{transform:translateX(0)}20%,33%{transform:translateX(86px)}
  34%{transform:translateX(0)}82%,86%{transform:translateX(86px)}
  87%{transform:translateX(0)}87.5%,94%{transform:translateX(86px)}
  96%,100%{transform:translateX(0)}}

/* La regle sert a garder une VITESSE a peu pres constante, et cela ne se
   prouve qu en divisant la distance par la duree.
   Les trois distances sont 24, 60 et 96. En haut les durees suivent la
   consigne, 100, 300 et 400 millisecondes, soit 2,3, 6,8 et 9,1 points. Les
   vitesses valent donc 10,4, 8,8 et 10,5 par point, presque egales. La
   consigne est legerement sous lineaire, la grande distance va un peu plus
   vite, et c est voulu, l oeil accepte cela.
   En bas les trois utilisent 300 millisecondes. Les vitesses tombent a 3,5,
   8,8 et 14,1. La plus longue va QUATRE FOIS plus vite que la plus courte.
   Les six partent au meme instant, a 20. En haut elles arrivent a 22,3, 26,8
   et 29,1, donc en escalier. En bas elles arrivent toutes les trois a 26,8,
   ensemble. La rangee fautive a l air PLUS ordonnee que la bonne, et c est
   exactement le piege, une duree unique se lit comme de la rigueur.
   Gele, on ne verrait aucune vitesse, seulement trois positions. */
/* 114 moins 4 de padding moins 2 de bordure laissent les 108 de la piste */
.ddu{display:flex;flex-direction:column;gap:10px;width:114px}
.ddu .grp{display:flex;flex-direction:column;gap:5px;padding-left:4px}
.ddu .ok{border-left:2px solid var(--lime)}
.ddu .ko{border-left:2px solid var(--a4)}
.ddu .tk{position:relative;display:block;width:108px;height:8px;border-radius:4px;
  background:var(--s2)}
.ddu .tk b{position:absolute;left:0;top:0;display:block;width:10px;height:8px;border-radius:4px}
.ddu .ok .tk b{background:var(--lime)}
.ddu .ko .tk b{background:var(--a4)}
/* 24 en 2,3 points, 10,4 par point */
.ddu .ok .d1 b{animation:aDduA1 4.4s cubic-bezier(.4,0,.2,1) infinite}
/* 60 en 6,8 points, 8,8 par point */
.ddu .ok .d2 b{animation:aDduA2 4.4s cubic-bezier(.4,0,.2,1) infinite}
/* 96 en 9,1 points, 10,5 par point */
.ddu .ok .d3 b{animation:aDduA3 4.4s cubic-bezier(.4,0,.2,1) infinite}
/* les trois en 6,8 points, donc 3,5 puis 8,8 puis 14,1 par point */
.ddu .ko .d1 b{animation:aDduB1 4.4s cubic-bezier(.4,0,.2,1) infinite}
.ddu .ko .d2 b{animation:aDduB2 4.4s cubic-bezier(.4,0,.2,1) infinite}
.ddu .ko .d3 b{animation:aDduB3 4.4s cubic-bezier(.4,0,.2,1) infinite}
@keyframes aDduA1{0%,19%{transform:translateX(0)}22.3%,94%{transform:translateX(24px)}
  96%,100%{transform:translateX(0)}}
@keyframes aDduA2{0%,19%{transform:translateX(0)}26.8%,94%{transform:translateX(60px)}
  96%,100%{transform:translateX(0)}}
@keyframes aDduA3{0%,19%{transform:translateX(0)}29.1%,94%{transform:translateX(96px)}
  96%,100%{transform:translateX(0)}}
@keyframes aDduB1{0%,19%{transform:translateX(0)}26.8%,94%{transform:translateX(24px)}
  96%,100%{transform:translateX(0)}}
@keyframes aDduB2{0%,19%{transform:translateX(0)}26.8%,94%{transform:translateX(60px)}
  96%,100%{transform:translateX(0)}}
@keyframes aDduB3{0%,19%{transform:translateX(0)}26.8%,94%{transform:translateX(96px)}
  96%,100%{transform:translateX(0)}}

/* Une personnalite n est pas une courbe, c est un RAPPORT tenu a plusieurs
   echelles. C est la seule chose qui la distingue d une echelle de courbes,
   qui elle ne parle que de l ensemble autorise.
   Les trois rangees parcourent la MEME distance, 70. Les deux premieres
   depassent de 7, soit exactement 10 pour cent, l une en 12 points et
   l autre en 28. Le rapport est identique alors que les durees sont dans un
   rapport de plus du double. C est cela qu on reconnait, et c est mesurable.
   La troisieme depasse de 21, soit 30 pour cent, dans la meme duree que la
   premiere. Rien d autre ne change, ni la distance ni le temps. Elle se lit
   donc comme un AUTRE produit, et c est le seul defaut qui compte ici.
   La cible est marquee a 70. Le mobile fait 10, son bord droit atteint donc
   80 au repos, 87 au sommet des deux premieres et 101 au sommet de la
   troisieme, ce qui tient dans la piste de 104.
   Gele, les trois seraient sur la cible et il ne resterait aucune
   personnalite. */
.mpe{display:flex;flex-direction:column;gap:8px;width:150px}
.mpe .one{display:flex;align-items:center;gap:6px}
.mpe em{font:600 6px/8px var(--mono);font-style:normal;letter-spacing:0;text-transform:none;
  width:38px;flex:0 0 auto}
.mpe .a em,.mpe .b em{color:var(--lime)}
.mpe .c em{color:var(--a4)}
.mpe .tk{position:relative;display:block;width:104px;height:8px;border-radius:4px;
  background:var(--s2);flex:0 0 auto}
.mpe .kn{position:absolute;left:0;top:0;display:block;width:10px;height:8px;border-radius:4px}
.mpe .a .kn,.mpe .b .kn{background:var(--lime)}
.mpe .c .kn{background:var(--a4)}
/* 10 pour cent de depassement en 12 points */
.mpe .a .kn{animation:aMpeA 4.6s cubic-bezier(.3,0,.2,1) infinite}
/* le meme 10 pour cent en 28 points, c est la signature */
.mpe .b .kn{animation:aMpeB 4.6s cubic-bezier(.3,0,.2,1) infinite}
/* 30 pour cent dans la duree de la premiere, une autre voix */
.mpe .c .kn{animation:aMpeC 4.6s cubic-bezier(.3,0,.2,1) infinite}
/* la cible, fixe */
.mpe .tg{position:absolute;left:70px;top:-3px;display:block;width:1.5px;height:14px;
  background:var(--s5)}
@keyframes aMpeA{0%,19%{transform:translateX(0)}25%{transform:translateX(77px)}
  31%,94%{transform:translateX(70px)}96%,100%{transform:translateX(0)}}
@keyframes aMpeB{0%,19%{transform:translateX(0)}33%{transform:translateX(77px)}
  47%,94%{transform:translateX(70px)}96%,100%{transform:translateX(0)}}
@keyframes aMpeC{0%,19%{transform:translateX(0)}25%{transform:translateX(91px)}
  31%,94%{transform:translateX(70px)}96%,100%{transform:translateX(0)}}

/* ---------------- gouvernance et passation ---------------- */

/* L audit vient AVANT les tokens, et la scene le montre par l ordre. Les neuf
   relevés apparaissent de 6 a 40, les regroupements a 48, et les tokens
   seulement a 66. Un token qui apparaitrait avant son regroupement dirait
   l inverse de la consigne.
   Les neuf durees observees sont 90 110 130 180 200 220 300 320 et 480
   millisecondes. Les 500 millisecondes sont portees sur 92 d une piste de
   100, ce qui laisse la place a la derniere pastille. Les relevés tombent
   donc a 17 20 24 33 37 40 55 59 et 88.
   Elles se regroupent en QUATRE, autour de 100, 200, 300 et 500. Neuf valeurs
   deviennent quatre tokens, et c est tout ce que l audit produit. Le dernier
   groupe n a qu un membre, un cas isole reste un cas isole, on ne le force
   pas dans un voisin.
   Les crochets couvrent 17 a 24, 33 a 40, 55 a 59 et 88 seul, soit des
   largeurs de 7, 7, 4 et 2. Les quatre tokens sont a 18, 37, 55 et 92, et
   comme leur pastille fait 6, leur bord gauche tombe a 15, 34, 52 et 89.
   Gele, on aurait un nuage de traits et quatre pastilles sans savoir
   lesquelles viennent des quels. */
.mau{display:flex;flex-direction:column;gap:7px;width:104px}
.mau .obs,.mau .cls,.mau .toks{position:relative;display:block;width:100px;height:8px}
.mau .obs i{position:absolute;top:0;display:block;width:1.5px;height:8px;background:var(--ink-3);
  opacity:0}
.mau .o1{left:17px;animation:aMauO1 4.6s steps(1,end) infinite}
.mau .o2{left:20px;animation:aMauO2 4.6s steps(1,end) infinite}
.mau .o3{left:24px;animation:aMauO3 4.6s steps(1,end) infinite}
.mau .o4{left:33px;animation:aMauO4 4.6s steps(1,end) infinite}
.mau .o5{left:37px;animation:aMauO5 4.6s steps(1,end) infinite}
.mau .o6{left:40px;animation:aMauO6 4.6s steps(1,end) infinite}
.mau .o7{left:55px;animation:aMauO7 4.6s steps(1,end) infinite}
.mau .o8{left:59px;animation:aMauO8 4.6s steps(1,end) infinite}
.mau .o9{left:88px;animation:aMauO9 4.6s steps(1,end) infinite}
/* les regroupements, apres les relevés */
.mau .cls i{position:absolute;top:2px;display:block;height:4px;border-radius:2px;
  background:var(--a2);opacity:0;animation:aMauCl 4.6s ease infinite}
.mau .g1{left:17px;width:7px}
.mau .g2{left:33px;width:7px}
.mau .g3{left:55px;width:4px}
.mau .g4{left:88px;width:2px}
/* les tokens, apres les regroupements */
.mau .toks i{position:absolute;top:0;display:block;width:6px;height:8px;border-radius:3px;
  background:var(--lime);opacity:0;animation:aMauTk 4.6s cubic-bezier(.2,1.4,.3,1) infinite}
.mau .t1{left:15px}
.mau .t2{left:34px}
.mau .t3{left:52px}
.mau .t4{left:89px}
@keyframes aMauO1{0%,5%{opacity:0}6%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aMauO2{0%,9%{opacity:0}10%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aMauO3{0%,13%{opacity:0}14%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aMauO4{0%,17%{opacity:0}18%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aMauO5{0%,21%{opacity:0}22%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aMauO6{0%,25%{opacity:0}26%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aMauO7{0%,29%{opacity:0}30%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aMauO8{0%,33%{opacity:0}34%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aMauO9{0%,39%{opacity:0}40%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aMauCl{0%,47%{opacity:0}52%,94%{opacity:1}96%,100%{opacity:0}}
@keyframes aMauTk{0%,65%{opacity:0;transform:scale(.4)}72%,94%{opacity:1;transform:scale(1)}
  96%,100%{opacity:0;transform:scale(.4)}}

/* La consigne demande un exemple a FAIRE et un a NE PAS FAIRE par principe.
   Chaque rangee porte donc deux marques, une lime et une a4, et il y en a
   deux par principe, jamais une.
   Le document sert a TRANCHER, et c est ce que la rangee du bas montre. Deux
   propositions arrivent a 30. A 52 le deuxieme principe s allume. A 58 la
   proposition de gauche est retenue et celle de droite tombe. Le principe
   s allume AVANT que la decision ne se prenne, sinon ce serait une
   justification apres coup et non un arbitrage.
   Trois principes, ce qui est le minimum de la consigne, et la hauteur est
   bornee, trois rangees de 10 avec deux ecarts de 5 font 40. Un document qui
   depasse la page ne tranche plus rien, personne ne le relit.
   Gele, on aurait trois lignes de texte et deux propositions, sans savoir
   laquelle a gagne ni pourquoi. */
.mpr{display:flex;flex-direction:column;gap:5px;width:92px}
.mpr .pr{display:flex;align-items:center;gap:4px;height:10px}
.mpr .pr b{display:block;width:8px;font:800 8px/10px var(--mono);color:var(--ink-2);
  text-align:center;letter-spacing:0;text-transform:none;flex:0 0 auto}
.mpr .tx{display:block;width:52px;height:6px;border-radius:3px;background:var(--s3);flex:0 0 auto}
/* deux marques par principe, un a faire et un a ne pas faire */
.mpr .do{display:block;width:8px;height:8px;border-radius:4px;background:var(--lime);
  flex:0 0 auto}
.mpr .dont{display:block;width:8px;height:8px;border-radius:2px;background:var(--a4);
  flex:0 0 auto}
/* il s allume avant la decision, sinon ce serait une justification */
.mpr .p2 b{animation:aMprLit 4.6s steps(1,end) infinite}
.mpr .p2 .tx{animation:aMprTx 4.6s steps(1,end) infinite}
.mpr .dis{display:flex;gap:6px;margin-top:5px}
.mpr .dis i{display:block;width:40px;height:14px;border-radius:5px;background:var(--s2)}
.mpr .pa{animation:aMprKeep 4.6s cubic-bezier(.2,1,.3,1) infinite}
.mpr .pb{animation:aMprDrop 4.6s cubic-bezier(.3,0,.2,1) infinite}
@keyframes aMprLit{0%,51%{color:var(--ink-2)}52%,94%{color:var(--lime)}
  96%,100%{color:var(--ink-2)}}
@keyframes aMprTx{0%,51%{background:var(--s3)}52%,94%{background:var(--s5)}
  96%,100%{background:var(--s3)}}
@keyframes aMprKeep{0%,29%{opacity:0;background:var(--s2)}
  36%,57%{opacity:1;background:var(--s2)}58%,94%{opacity:1;background:var(--lime)}
  96%,100%{opacity:0;background:var(--s2)}}
@keyframes aMprDrop{0%,29%{opacity:0;transform:translateY(0)}
  36%,57%{opacity:1;transform:translateY(0)}
  66%,94%{opacity:0;transform:translateY(6px)}
  96%,100%{opacity:0;transform:translateY(0)}}

/* Un lint ne previent pas, il ARRETE. C est ce qui le separe de la liste des
   interdits, qui est une case a cocher tenue par un humain.
   Trois lignes avancent vers la barriere, placee a 60. La premiere est
   conforme, elle passe et sort du champ a 84. La deuxieme ecrit 300ms en dur,
   elle bute a 32 et son bord droit s arrete a 58, juste avant la barriere.
   La troisieme declare un keyframe hors du paquet de tokens, elle n atteint
   meme pas la barriere, elle reste bloquee a 4 DERRIERE la deuxieme.
   C est la seule chose qui compte. Une regle de build ne laisse pas passer le
   reste de la file, tout le monde attend la correction. Un avertissement
   aurait laissé les trois lignes sortir.
   Le message arrive a 40, apres le refus, parce qu on nomme la faute une fois
   qu elle est constatee.
   Les lignes font 26, la piste 110, et la barriere est a 60.
   Gele, les trois lignes seraient a des endroits differents sans qu on sache
   laquelle a ete refusee. */
.tln{position:relative;display:flex;flex-direction:column;gap:4px;width:110px}
.tln .rw{display:block;width:110px;height:8px}
.tln .ln{display:block;width:26px;height:8px;border-radius:4px;background:var(--s3)}
/* conforme, elle passe et sort du champ */
.tln .r1 .ln{background:var(--lime);animation:aTlnPass 5s cubic-bezier(.4,0,.6,1) infinite}
/* 300ms en dur, elle bute juste avant la barriere */
.tln .r2 .ln{background:var(--a4);animation:aTlnStop 5s cubic-bezier(.4,0,.6,1) infinite}
/* un keyframe hors paquet, elle reste bloquee derriere la precedente */
.tln .r3 .ln{background:var(--a4);animation:aTlnQueue 5s cubic-bezier(.4,0,.6,1) infinite}
/* la barriere, fixe, elle ne s ouvre pas */
.tln .gate{position:absolute;left:60px;top:0;display:block;width:2px;height:32px;
  background:var(--s5)}
.tln .msg{display:block;font:700 6px/8px var(--mono);color:var(--a4);font-style:normal;
  letter-spacing:0;text-transform:none;opacity:0;animation:aTlnMsg 5s steps(1,end) infinite}
@keyframes aTlnPass{0%,13%{transform:translateX(0)}24%,94%{transform:translateX(84px)}
  96%,100%{transform:translateX(0)}}
/* elle s arrete a 32, son bord droit est donc a 58 */
@keyframes aTlnStop{0%,17%{transform:translateX(0)}34%,94%{transform:translateX(32px)}
  96%,100%{transform:translateX(0)}}
/* bloquee derriere, elle n avance que de 4 */
@keyframes aTlnQueue{0%,21%{transform:translateX(0)}38%,94%{transform:translateX(4px)}
  96%,100%{transform:translateX(0)}}
@keyframes aTlnMsg{0%,39%{opacity:0}40%,94%{opacity:1}96%,100%{opacity:0}}

/* La consigne nomme SIX cas interdits, la liste en montre donc six et pas
   quatre. Decoration, motion comme seul retour, version maison d un pattern
   standard, mouvement plein ecran, parallaxe et scrolljacking.
   La liste est INERTE du premier au dernier pour cent, parce qu une liste
   publiee ne bouge pas. C est un document, comme les tokens a cote desquels
   elle est publiee.
   Ce qui bouge est la revue. Une proposition arrive a 24. A 46 la case du
   quatrieme cas se coche, la correspondance est trouvee. A 56 la proposition
   est barree.
   L ordre compte. La case se coche AVANT que la proposition ne tombe, sinon
   on refuserait d abord et on chercherait la justification ensuite.
   C est un geste humain, pas une regle de build. Rien n empeche d ecrire le
   code, quelqu un doit le regarder.
   Six rangees de 7 avec cinq ecarts de 4 font 62.
   Gele, on aurait une liste et une proposition sans savoir laquelle des six
   lignes l a arretee. */
.dna{display:flex;flex-direction:column;gap:9px;width:76px}
/* une liste publiee ne bouge pas */
.dna .ls{display:flex;flex-direction:column;gap:4px}
.dna .rw{display:flex;align-items:center;gap:4px;height:7px}
.dna .cb{display:block;width:7px;height:7px;border-radius:2px;box-sizing:border-box;
  border:1.5px solid var(--s4);flex:0 0 auto}
.dna .tx{display:block;width:60px;height:5px;border-radius:3px;background:var(--s3)}
/* la case du quatrieme cas, la seule qui se coche */
.dna .r4 .cb{animation:aDnaCb 4.6s steps(1,end) infinite}
.dna .prop{display:block;height:10px}
.dna .prop b{display:block;width:52px;height:10px;border-radius:4px;background:var(--a2);
  opacity:0;animation:aDnaProp 4.6s cubic-bezier(.3,0,.2,1) infinite}
@keyframes aDnaCb{0%,45%{border-color:var(--s4);background:none}
  46%,94%{border-color:var(--a4);background:var(--a4)}
  96%,100%{border-color:var(--s4);background:none}}
/* elle arrive a 24, elle tombe a 56, apres la case */
@keyframes aDnaProp{0%,23%{opacity:0;transform:scaleX(1)}
  30%,55%{opacity:1;transform:scaleX(1)}
  64%,94%{opacity:.3;transform:scaleX(.2)}
  96%,100%{opacity:0;transform:scaleX(1)}}

/* Le budget est un RAPPORT, 10 sur 16,7, et il ne se lit qu en le dessinant.
   La barre fait 100 pour 16,7 millisecondes, soit 5,99 par milliseconde. Le
   repere du budget est donc a 10 fois 5,99, soit 60. Ce qui est a droite du
   repere appartient au navigateur, pas a nous.
   En haut on n anime que transform et opacity, le compositeur s en charge, la
   frame coute 8 millisecondes, soit 48. Il reste 12 pour le navigateur.
   En bas on anime width, ce qui force une mise en page a chaque frame. La
   frame coute 14, soit 84. On empiete de 24 pixels, c est-a-dire de 4
   millisecondes, sur le temps du navigateur.
   Les deux trains de six montrent la consequence. En haut les six frames
   sortent. En bas la quatrieme manque, parce que le budget du navigateur a
   fini par etre epuise. Une frame perdue ne se voit pas dans une barre, elle
   se voit dans un trou.
   Les deux barres et le repere sont INERTES. Ce sont une mesure et une
   limite declaree, pas un mouvement. Ce qui bouge est la consequence, les
   deux trains de frames, et c est bien la que la faute se voit.
   Gele, les deux barres seraient a des longueurs differentes sans qu on sache
   ou est la limite ni ce qu on perd a la depasser. */
.abg{display:flex;flex-direction:column;gap:10px;width:136px}
.abg .one{display:grid;grid-template-columns:30px 100px;gap:4px 6px;align-items:center}
.abg em{font:600 6px/8px var(--mono);font-style:normal;letter-spacing:0;text-transform:none;
  grid-column:1;grid-row:1}
.abg .ok em{color:var(--lime)}
.abg .ko em{color:var(--a4)}
.abg .fr{position:relative;display:block;width:100px;height:8px;border-radius:4px;
  background:var(--s2);grid-column:2;grid-row:1}
.abg .us{display:block;height:8px;border-radius:4px}
/* 8 millisecondes, soit 48 */
.abg .ok .us{background:var(--lime);width:48px}
/* 14 millisecondes, soit 84, dont 24 voles au navigateur */
.abg .ko .us{background:var(--a4);width:84px}
/* le repere du budget, a 10 millisecondes, soit 60 */
.abg .mk{position:absolute;left:60px;top:-3px;display:block;width:1.5px;height:14px;
  background:var(--s5)}
.abg .tr{position:relative;display:flex;gap:4px;grid-column:2;grid-row:2}
.abg .tr i{display:block;width:14px;height:5px;border-radius:2px;background:var(--s3);
  flex:0 0 auto}
.abg .ok .tr i{animation:aAbgOk 4.4s steps(1,end) infinite}
.abg .ko .tr i{animation:aAbgKo 4.4s steps(1,end) infinite}
/* la quatrieme frame manque, le trou est la vraie consequence */
.abg .ko .tr .f4{animation:aAbgDrop 4.4s steps(1,end) infinite}
@keyframes aAbgOk{0%,11%{background:var(--s3)}12%,94%{background:var(--lime)}
  96%,100%{background:var(--s3)}}
@keyframes aAbgKo{0%,11%{background:var(--s3)}12%,94%{background:var(--a4)}
  96%,100%{background:var(--s3)}}
@keyframes aAbgDrop{0%,11%{background:var(--s3);opacity:1}
  12%,94%{background:var(--s3);opacity:.15}96%,100%{background:var(--s3);opacity:1}}

/* Ce budget ne compte pas des millisecondes dans une frame, il compte des
   CHOSES sur un ecran. C est la seule difference avec le budget d image, et
   elle est complete, ni la meme unite ni la meme ressource. L un protege le
   compositeur, l autre protege l attention.
   Six candidats se presentent. Trois entrent dans les trois emplacements, a
   14, 26 et 38. Les trois autres sont COUPES a 52, ils disparaissent. La
   consigne dit de couper ce qui depasse, pas de le reduire.
   La barre du bas est la seconde contrainte, le temps total ajoute. Elle fait
   100 pour 600 millisecondes, soit 0,167 par milliseconde, et le repere des
   500 est donc a 83. Les trois durees retenues valent 180, 150 et 120, soit
   450, donc 75. On est sous les deux limites a la fois, et il faut les deux.
   Trois emplacements pleins avec 600 millisecondes de total seraient conformes
   au compte et hors budget de temps.
   Gele, on verrait trois choses allumees sans savoir combien ont ete
   refusees. */
.mbg{display:flex;flex-direction:column;gap:9px;width:100px}
.mbg .cands{display:flex;gap:4px;height:10px}
.mbg .cands i{display:block;width:14px;height:10px;border-radius:3px;background:var(--s2);
  flex:0 0 auto}
/* les trois retenus */
.mbg .c1{animation:aMbgIn1 4.6s steps(1,end) infinite}
.mbg .c2{animation:aMbgIn2 4.6s steps(1,end) infinite}
.mbg .c3{animation:aMbgIn3 4.6s steps(1,end) infinite}
/* les trois coupes, la consigne dit couper et non reduire */
.mbg .c4,.mbg .c5,.mbg .c6{animation:aMbgCut 4.6s cubic-bezier(.3,0,.2,1) infinite}
.mbg .slots{display:flex;gap:4px;height:12px}
.mbg .slots i{display:block;width:30px;height:12px;border-radius:4px;box-sizing:border-box;
  border:1.5px dashed var(--line-2);flex:0 0 auto}
/* on anime la couleur et le fond, pas border-style, qui n est pas animable */
.mbg .slots i:nth-child(1){animation:aMbgSl1 4.6s steps(1,end) infinite}
.mbg .slots i:nth-child(2){animation:aMbgSl2 4.6s steps(1,end) infinite}
.mbg .slots i:nth-child(3){animation:aMbgSl3 4.6s steps(1,end) infinite}
.mbg .sum{position:relative;display:block;width:100px;height:6px;border-radius:3px;
  background:var(--s2)}
/* 450 millisecondes sur 600, soit 75 */
.mbg .sum b{display:block;width:0;height:6px;border-radius:3px;background:var(--a2);
  animation:aMbgSum 4.6s cubic-bezier(.4,0,.2,1) infinite}
/* le repere des 500, a 83, fixe */
.mbg .mk{position:absolute;left:83px;top:-3px;display:block;width:1.5px;height:12px;
  background:var(--s5)}
@keyframes aMbgIn1{0%,13%{background:var(--s2)}14%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}
@keyframes aMbgIn2{0%,25%{background:var(--s2)}26%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}
@keyframes aMbgIn3{0%,37%{background:var(--s2)}38%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}
@keyframes aMbgCut{0%,51%{opacity:1;transform:scale(1)}60%,94%{opacity:0;transform:scale(.4)}
  96%,100%{opacity:1;transform:scale(1)}}
@keyframes aMbgSl1{0%,13%{border-color:var(--line-2);background:none}
  14%,94%{border-color:var(--lime);background:var(--s1)}
  96%,100%{border-color:var(--line-2);background:none}}
@keyframes aMbgSl2{0%,25%{border-color:var(--line-2);background:none}
  26%,94%{border-color:var(--lime);background:var(--s1)}
  96%,100%{border-color:var(--line-2);background:none}}
@keyframes aMbgSl3{0%,37%{border-color:var(--line-2);background:none}
  38%,94%{border-color:var(--lime);background:var(--s1)}
  96%,100%{border-color:var(--line-2);background:none}}
@keyframes aMbgSum{0%,13%{width:0}44%,94%{width:75px}96%,100%{width:0}}

/* La consigne demande d echelonner la duree ET la distance selon le rang, et
   de faire partir le plus important en PREMIER. Trois choses a la fois, la
   scene les montre donc toutes les trois.
   En haut, le primaire part a 18, parcourt 72 en 20 points. Le secondaire part
   a 22, parcourt 36 en 13. Le fond part a 26, parcourt 12 en 8. Les distances
   sont dans un rapport de 6 a 3 a 1 et les durees de 20 a 13 a 8. Le premier
   parti est aussi le plus loin et le plus long, les trois criteres pointent
   dans le meme sens, ce qui est la seule facon de construire un rang lisible.
   En bas les trois partent a 18, parcourent 40 en 13 points. Rien ne
   distingue le principal de l accessoire. L oeil ne sait pas ou aller, et
   c est exactement ce que la troisieme consigne interdit.
   La piste fait 84 et le mobile 8, la course maximale vaut donc 76, les 72 du
   primaire tiennent.
   Gele, les six lignes seraient a leur arrivee et les deux groupes se
   ressembleraient. */
/* 90 moins 4 de padding moins 2 de bordure laissent les 84 de la piste */
.mhi{display:flex;flex-direction:column;gap:9px;width:90px}
.mhi .grp{display:flex;flex-direction:column;gap:4px;padding-left:4px}
.mhi .ok{border-left:2px solid var(--lime)}
.mhi .ko{border-left:2px solid var(--a4)}
.mhi .lane{display:block;width:84px;height:8px}
.mhi .lane b{display:block;width:8px;height:8px;border-radius:4px}
.mhi .ok .lane b{background:var(--lime)}
.mhi .ko .lane b{background:var(--a4)}
/* premier parti, le plus loin, le plus long */
.mhi .ok .h1 b{animation:aMhiP 4.6s cubic-bezier(.3,0,.2,1) infinite}
.mhi .ok .h2 b{animation:aMhiS 4.6s cubic-bezier(.3,0,.2,1) infinite}
.mhi .ok .h3 b{animation:aMhiB 4.6s cubic-bezier(.3,0,.2,1) infinite}
/* les trois identiques, aucun rang */
.mhi .ko .lane b{animation:aMhiFlat 4.6s cubic-bezier(.3,0,.2,1) infinite}
@keyframes aMhiP{0%,17%{transform:translateX(0)}38%,94%{transform:translateX(72px)}
  96%,100%{transform:translateX(0)}}
@keyframes aMhiS{0%,21%{transform:translateX(0)}35%,94%{transform:translateX(36px)}
  96%,100%{transform:translateX(0)}}
@keyframes aMhiB{0%,25%{transform:translateX(0)}34%,94%{transform:translateX(12px)}
  96%,100%{transform:translateX(0)}}
@keyframes aMhiFlat{0%,17%{transform:translateX(0)}31%,94%{transform:translateX(40px)}
  96%,100%{transform:translateX(0)}}

/* La consigne nomme HUIT champs, declencheur, proprietes, duree en
   millisecondes, token d easing, delai, decalage, etat final et comportement
   en cas d interruption. La fiche en montre huit, et ils se remplissent un
   par un, de 8 a 64, tous les 8 points.
   La puce du bas est le lien de prototype. Elle est presente du premier au
   dernier pour cent et elle ne remplit AUCUN des huit champs. C est la
   troisieme consigne, un lien de prototype n est pas une spec, et la seule
   facon de le montrer est de le laisser la, inerte, pendant que la fiche se
   remplit sans lui.
   On peut compter. Huit lignes se remplissent, le lien en aurait rempli zero.
   Huit rangees de 5 avec sept ecarts de 3 font 61.
   Gele, on aurait une fiche remplie et un lien, sans savoir lequel des deux a
   fait le travail. */
.msp{display:flex;flex-direction:column;align-items:flex-start;gap:8px;width:70px}
.msp .sheet{display:flex;flex-direction:column;gap:3px}
.msp .fd{display:flex;align-items:center;gap:4px;height:5px}
.msp .fd i{display:block;width:16px;height:5px;border-radius:2px;background:var(--s4);
  flex:0 0 auto}
.msp .fd b{display:block;width:40px;height:5px;border-radius:2px;background:var(--s2)}
.msp .f1 b{animation:aMspF1 4.6s steps(1,end) infinite}
.msp .f2 b{animation:aMspF2 4.6s steps(1,end) infinite}
.msp .f3 b{animation:aMspF3 4.6s steps(1,end) infinite}
.msp .f4 b{animation:aMspF4 4.6s steps(1,end) infinite}
.msp .f5 b{animation:aMspF5 4.6s steps(1,end) infinite}
.msp .f6 b{animation:aMspF6 4.6s steps(1,end) infinite}
.msp .f7 b{animation:aMspF7 4.6s steps(1,end) infinite}
.msp .f8 b{animation:aMspF8 4.6s steps(1,end) infinite}
/* il est la du debut a la fin et il ne remplit aucun champ */
.msp .link{display:block;padding:2px 5px;border-radius:4px;box-sizing:border-box;
  border:1px dashed var(--a4);font:700 6px/8px var(--mono);color:var(--a4);font-style:normal;
  letter-spacing:0;text-transform:none}
@keyframes aMspF1{0%,7%{background:var(--s2)}8%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}
@keyframes aMspF2{0%,15%{background:var(--s2)}16%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}
@keyframes aMspF3{0%,23%{background:var(--s2)}24%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}
@keyframes aMspF4{0%,31%{background:var(--s2)}32%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}
@keyframes aMspF5{0%,39%{background:var(--s2)}40%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}
@keyframes aMspF6{0%,47%{background:var(--s2)}48%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}
@keyframes aMspF7{0%,55%{background:var(--s2)}56%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}
@keyframes aMspF8{0%,63%{background:var(--s2)}64%,94%{background:var(--lime)}
  96%,100%{background:var(--s2)}}

/* La classification a deux sorties et elles sont differentes, ce n est pas un
   interrupteur unique. La scene montre les deux.
   De 8 a 24 le reglage est normal, les deux entrent en glissant sur 60.
   A 48 le reduced motion s allume. De 56 a 72, le decoratif ne fait PLUS
   RIEN, il est simplement la. L essentiel, lui, continue de signaler, mais en
   fondu sur place, sans aucun deplacement.
   C est le coeur de la definition. Apres la reduction, l essentiel porte
   encore son information, on sait qu un element est arrive. Le decoratif n a
   rien a porter, on ne perd donc rien a le retirer entierement.
   La difference entre les deux n est pas une intensite, c est une PRESENCE.
   Reduire le decoratif a un petit mouvement serait la faute, la consigne dit
   de le supprimer.
   La piste fait 76 et le mobile 12, la course de 60 tient donc.
   Gele, on ne verrait pas laquelle des deux survit ni sous quelle forme. */
.emo{display:flex;flex-direction:column;gap:8px;width:118px}
.emo .one{display:flex;align-items:center;gap:6px}
.emo em{font:600 6px/8px var(--mono);font-style:normal;letter-spacing:0;text-transform:none;
  width:34px;flex:0 0 auto}
.emo .deco em{color:var(--a4)}
.emo .ess em{color:var(--lime)}
.emo .st{position:relative;display:block;width:76px;height:10px;border-radius:5px;
  background:var(--s2);flex:0 0 auto}
.emo .st b{position:absolute;left:0;top:0;display:block;width:12px;height:10px;
  border-radius:5px}
/* apres la reduction il ne fait plus rien, il n avait rien a porter */
.emo .deco b{background:var(--a4);animation:aEmoDeco 4.4s cubic-bezier(.3,0,.2,1) infinite}
/* apres la reduction il signale encore, en fondu et sans deplacement */
.emo .ess b{background:var(--lime);animation:aEmoEss 4.4s cubic-bezier(.3,0,.2,1) infinite}
.emo .sw{display:block;align-self:flex-start;padding:2px 5px;border-radius:4px;
  background:var(--s2);font:700 6px/8px var(--mono);color:var(--a2);font-style:normal;
  letter-spacing:0;text-transform:none;opacity:.25;
  animation:aEmoSw 4.4s steps(1,end) infinite}
/* il glisse avant, il ne fait plus rien apres */
@keyframes aEmoDeco{0%,7%{transform:translateX(0);opacity:1}
  24%,40%{transform:translateX(60px);opacity:1}
  47%,94%{transform:translateX(0);opacity:0}
  96%,100%{transform:translateX(0);opacity:1}}
/* il glisse avant, il fond sur place apres */
@keyframes aEmoEss{0%,7%{transform:translateX(0);opacity:1}
  24%,40%{transform:translateX(60px);opacity:1}
  47%,55%{transform:translateX(60px);opacity:0}
  62%,94%{transform:translateX(60px);opacity:1}
  96%,100%{transform:translateX(0);opacity:1}}
@keyframes aEmoSw{0%,47%{opacity:.25}48%,94%{opacity:1}96%,100%{opacity:.25}}

/* La consigne trace une FRONTIERE, Lottie pour l illustratif, du code pour
   tout ce qui reflete un etat d interface. La scene met les deux cotes et la
   faute.
   La premiere rangee est une illustration, un trace qui se dessine. C est le
   bon emploi, un dessin de caractere que du code ne saurait pas produire.
   La deuxieme rangee est un interrupteur pilote par du code. Son bouton est a
   droite et le temoin est allume. Les deux disent la meme chose.
   La troisieme rangee est le meme interrupteur livre en Lottie. Son bouton
   joue sa boucle et revient a droite, mais le temoin reste ETEINT. Le fichier
   ne connait pas l etat, il joue ses images. Deux elements de la meme rangee
   se contredisent, et c est cela qu on achete en livrant un etat d interface
   en Lottie.
   Le trace utilise pathLength 1, ce qui rend le dessin independant de la
   longueur reelle du chemin.
   Gele, la troisieme rangee aurait l air correcte, la faute est dans le
   desaccord entre deux choses qui bougent. */
.lho{display:flex;flex-direction:column;gap:8px;width:120px}
.lho .one{display:flex;align-items:center;gap:6px}
.lho em{font:600 6px/8px var(--mono);font-style:normal;letter-spacing:0;text-transform:none;
  width:30px;flex:0 0 auto}
.lho .ill em,.lho .code em{color:var(--lime)}
.lho .ko em{color:var(--a4)}
.lho .stg{display:block;width:72px;height:22px;flex:0 0 auto}
.lho svg{display:block;width:72px;height:22px}
/* pathLength 1, le dessin ne depend pas de la longueur reelle */
.lho path{fill:none;stroke:var(--lime);stroke-width:2.5;stroke-linecap:round;
  stroke-dasharray:1;animation:aLhoDraw 5s cubic-bezier(.4,0,.2,1) infinite}
.lho .tg{position:relative;display:block;width:34px;height:16px;border-radius:8px;
  background:var(--s2);flex:0 0 auto}
.lho .kn{position:absolute;left:2px;top:2px;display:block;width:12px;height:12px;
  border-radius:7px;background:var(--ink-3)}
/* pilote par le code, il suit l etat */
.lho .code .kn{animation:aLhoKn 5s cubic-bezier(.2,1,.3,1) infinite}
/* livre en Lottie, il joue ses images sans connaitre l etat */
.lho .ko .kn{animation:aLhoKn 5s cubic-bezier(.2,1,.3,1) infinite}
.lho .stt{display:block;width:8px;height:8px;border-radius:4px;background:var(--s3);
  flex:0 0 auto}
/* le temoin suit l etat reel */
.lho .code .stt{animation:aLhoStt 5s steps(1,end) infinite}
/* dans la rangee fautive le temoin n a AUCUNE animation, il reste eteint
   pendant que le bouton joue ses images, et les deux se contredisent */
@keyframes aLhoDraw{0%,7%{stroke-dashoffset:1}62%,94%{stroke-dashoffset:0}
  96%,100%{stroke-dashoffset:1}}
@keyframes aLhoKn{0%,23%{transform:translateX(0)}38%,94%{transform:translateX(18px)}
  96%,100%{transform:translateX(0)}}
@keyframes aLhoStt{0%,37%{background:var(--s3)}38%,94%{background:var(--lime)}
  96%,100%{background:var(--s3)}}

/* Smart Animate interpole entre deux calques qui portent le MEME NOM. Rien
   d autre ne compte, ni leur forme, ni leur position, ni la duree choisie.
   Les deux rangees ont exactement le meme montage et la meme keyframe. La
   seule difference est la pastille de nom du second cadre, identique en haut
   et differente en bas.
   En haut le carre traverse les 48 qui separent les deux cadres. En bas il
   passe en une image, parce que rien ne s est apparie et qu il ne reste qu une
   coupe franche. La meme keyframe donne donc deux resultats, et ce n est pas
   la courbe qui change, c est le nom.
   C est la seule facon de montrer une regle d appariement. Une scene qui
   montrerait un beau tween ne dirait rien de ce qui le rend possible.
   Les cadres font 40 avec 8 d ecart, le mobile 12, il va donc de 4 a 52, soit
   48 de course.
   Gele, les deux rangees seraient identiques, puisque leur etat final est le
   meme. C est le cas le plus net du glossaire, ici le mouvement EST toute
   l information. */
.sma{display:flex;flex-direction:column;gap:9px;width:128px}
.sma .one{display:flex;align-items:center;gap:6px}
.sma em{font:600 6px/8px var(--mono);font-style:normal;letter-spacing:0;text-transform:none;
  width:34px;flex:0 0 auto}
.sma .ok em{color:var(--lime)}
.sma .ko em{color:var(--a4)}
.sma .strip{position:relative;display:flex;gap:8px;flex:0 0 auto}
.sma .fr{position:relative;display:block;width:40px;height:20px;border-radius:5px;
  box-sizing:border-box;border:1px solid var(--line-2)}
/* la pastille de nom, seule difference entre les deux rangees */
.sma .nm{position:absolute;right:3px;top:3px;display:block;width:6px;height:6px;
  border-radius:2px;background:var(--lime)}
.sma .nm.b{background:var(--a4);border-radius:4px}
.sma .mv{position:absolute;left:4px;top:4px;display:block;width:12px;height:12px;
  border-radius:3px;background:var(--s4)}
/* meme keyframe, meme duree, seule la fonction de temps change */
.sma .ok .mv{animation:aSmaMv 4.6s cubic-bezier(.3,0,.2,1) infinite}
/* rien ne s est apparie, il ne reste qu une coupe franche */
.sma .ko .mv{animation:aSmaMv 4.6s steps(1,end) infinite}
/* 48 de course, la distance entre les deux cadres */
@keyframes aSmaMv{0%,19%{transform:translateX(0)}45%,94%{transform:translateX(48px)}
  96%,100%{transform:translateX(0)}}
