/* ==========================================================================
   sortmaj — animations des pixels décoratifs (mosaïque et vague)
   Les retards et rythmes sont calculés en Python (jugement/affichage.py) et
   passés en variables CSS sur chaque case :
     tramée   : .qN durée d'allumage (N/20 du cycle), --p début (pas de 75 ms)
     vague    : .ec  case d'écume, --p durée (s), --t décalage (s)
   Rien ne bouge si l'utilisateur a demandé à réduire les animations.
   ========================================================================== */

/* --- Mosaïque : vague tramée (état sans animation) ----------------------- */
/* Grille plus fine (48 × 22). Cases éteintes = transparentes ; .on toujours
   allumée ; .s allumée sur l'image fixe montrée sans animation. */
.mosaic--tramee { gap: 2px; }
.mosaic--tramee > span { opacity: 0; border-radius: 1px; }
.mosaic--tramee > span.on, .mosaic--tramee > span.s { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {

  /* --- Mosaïque : vague tramée ------------------------------------------- */
  /* Chaque case s'allume en tout-ou-rien pendant sa fenêtre du cycle de 9 s :
     .qN = allumée N vingtièmes du cycle, --p = début de la fenêtre (pas de 75 ms). */
  .mosaic--tramee > span[style] {
    animation-duration: 9s;
    animation-timing-function: step-end;
    animation-iteration-count: infinite;
    animation-delay: calc(var(--p) * 75ms - 9s);
  }
  .mosaic--tramee > span.q1 { animation-name: trame-q1; }
  @keyframes trame-q1 { 0% { opacity: 1; } 5%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q2 { animation-name: trame-q2; }
  @keyframes trame-q2 { 0% { opacity: 1; } 10%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q3 { animation-name: trame-q3; }
  @keyframes trame-q3 { 0% { opacity: 1; } 15%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q4 { animation-name: trame-q4; }
  @keyframes trame-q4 { 0% { opacity: 1; } 20%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q5 { animation-name: trame-q5; }
  @keyframes trame-q5 { 0% { opacity: 1; } 25%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q6 { animation-name: trame-q6; }
  @keyframes trame-q6 { 0% { opacity: 1; } 30%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q7 { animation-name: trame-q7; }
  @keyframes trame-q7 { 0% { opacity: 1; } 35%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q8 { animation-name: trame-q8; }
  @keyframes trame-q8 { 0% { opacity: 1; } 40%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q9 { animation-name: trame-q9; }
  @keyframes trame-q9 { 0% { opacity: 1; } 45%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q10 { animation-name: trame-q10; }
  @keyframes trame-q10 { 0% { opacity: 1; } 50%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q11 { animation-name: trame-q11; }
  @keyframes trame-q11 { 0% { opacity: 1; } 55%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q12 { animation-name: trame-q12; }
  @keyframes trame-q12 { 0% { opacity: 1; } 60%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q13 { animation-name: trame-q13; }
  @keyframes trame-q13 { 0% { opacity: 1; } 65%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q14 { animation-name: trame-q14; }
  @keyframes trame-q14 { 0% { opacity: 1; } 70%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q15 { animation-name: trame-q15; }
  @keyframes trame-q15 { 0% { opacity: 1; } 75%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q16 { animation-name: trame-q16; }
  @keyframes trame-q16 { 0% { opacity: 1; } 80%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q17 { animation-name: trame-q17; }
  @keyframes trame-q17 { 0% { opacity: 1; } 85%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q18 { animation-name: trame-q18; }
  @keyframes trame-q18 { 0% { opacity: 1; } 90%, 100% { opacity: 0; } }
  .mosaic--tramee > span.q19 { animation-name: trame-q19; }
  @keyframes trame-q19 { 0% { opacity: 1; } 95%, 100% { opacity: 0; } }

  /* --- Vague : écume ------------------------------------------------------- */
  /* Une partie des cases claires passe franchement à la couleur foncée de sa
     famille (bleu pâle → « Très bien », rose clair → « À rejeter »), puis revient.
     Calque ::after en opacité : peu coûteux à animer. */
  .pixel-wave--ecume > span.ec { position: relative; }
  .pixel-wave--ecume > span.ec::after {
    content: ""; position: absolute; inset: 0; opacity: 0;
    animation: vague-ecume calc(var(--p) * 1s) ease-in-out infinite;
    animation-delay: calc(var(--t) * -1s);
  }
  .pixel-wave--ecume > span.wa.ec::after { background: var(--mj-tres-bien); }
  .pixel-wave--ecume > span.wi.ec::after { background: var(--mj-a-rejeter); }
  @keyframes vague-ecume {
    0%, 30%, 100% { opacity: 0; }
    45%, 62% { opacity: 1; }
  }
}

@media (prefers-reduced-motion: no-preference) {

  /* --- Page 404 : pixels du fond qui scintillent ---------------------------- */
  .champ-pixels > span {
    opacity: 0;
    animation: champ-scintille calc(var(--p) * 1s) ease-in-out infinite;
    animation-delay: calc(var(--t) * -1s);
  }
  @keyframes champ-scintille {
    0%, 100% { opacity: 0; transform: scale(.4); }
    45%, 60% { opacity: 1; transform: scale(1); }
  }
}
