/* ============================================================
   FogenCraft — MOUVEMENT (0.92.0)
   Tout ce qui bouge. Posé par vivant.js sous `html.vivant`, éteint sous
   `html.calme` (préférence du système OU commutateur « Mouvement »).
   Les animations avancent par pas (`steps`) : un pixel ne glisse pas,
   il saute.

   Puis les régimes particuliers : contraste élevé, impression.
   ============================================================ */

/* ---------------------------------------------------- l'arrêt */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important;
    animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}
/* Par le commutateur (WCAG 2.2.2) : plus aucune animation ni transition,
   curseurs et voyants compris. */
html.calme *, html.calme *::before, html.calme *::after {
  animation: none !important; transition-duration: 0s !important;
}
html.calme { scroll-behavior: auto; }

/* ---------------------------------------------------- l'allumage */

/* Jamais depuis zéro ni avec un filtre plein écran : le navigateur ne
   comptait pas le contenu à opacité 0 comme peint, et quatre
   rasterisations de tout le document coûtaient plus que l'effet. */
html.vivant:not(.calme):not(.rallume) body { animation: fg-allumer .4s steps(4, jump-start); }
@keyframes fg-allumer { from { opacity: .3; } }

/* ---------------------------------------------------- apparition */

html.vivant:not(.calme) [data-reveal] {
  opacity: 0; transform: translateY(12px);
  transition: opacity var(--duree-lente) var(--courbe), transform var(--duree-lente) var(--pas-anim);
  transition-delay: calc(var(--i, 0) * 70ms);
}
html.vivant:not(.calme) [data-reveal].visible { opacity: 1; transform: none; }
html.vivant:not(.calme):not(.rallume) .heros-contenu > * { animation: fg-monter .6s var(--pas-anim) both; }
html.vivant:not(.calme):not(.rallume) .heros-contenu > :nth-child(2) { animation-delay: .12s; }
html.vivant:not(.calme):not(.rallume) .heros-contenu > :nth-child(3) { animation-delay: .22s; }
html.vivant:not(.calme):not(.rallume) .heros-contenu > :nth-child(4) { animation-delay: .32s; }
@keyframes fg-monter { from { opacity: 0; transform: translateY(16px); } }
html.vivant:not(.calme) .heros img.fond { will-change: transform; }

/* La machine à écrire du héros. */
html.vivant:not(.calme) .amorce p { opacity: 0; }
html.vivant:not(.calme) .amorce p.en-cours, html.vivant:not(.calme) .amorce p.tapee { opacity: 1; }
.amorce p.en-cours::after { content: "▮"; margin-left: 2px; animation: fg-curseur .6s steps(1) infinite; }
@keyframes fg-curseur { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
.terminal .invite::after { animation: fg-curseur 1.1s steps(1) infinite; }
/* Le curseur d'un titre de plaque ne clignote que sur la plaque qu'on
   regarde : dix-neuf curseurs infinis sur une page d'administration, c'était
   dix-neuf minuteries de repeinture. */
.panneau:hover > :is(h2, h3)::after, .panneau:focus-within > :is(h2, h3)::after { animation: fg-curseur 1.1s steps(1) infinite; }

/* Les écrans scintillent et une ligne descend. */
.terminal { animation: fg-scintillement 7s steps(1) infinite; }
@keyframes fg-scintillement { 0%, 96%, 100% { opacity: 1; } 97% { opacity: .94; } 98.5% { opacity: .98; } }
/* (La ligne qui descendait animait `background-position` : une repeinture
   continue de tout l'écran vert. Retirée ; le balayage statique reste.) */
.voyant { animation: fg-pulser 2.2s ease-in-out infinite; }
.pastille.ok::before, .pastille.attente::before { animation: fg-pulser 2.4s ease-in-out infinite; }
@keyframes fg-pulser { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* ---------------------------------------------------- les chiffres, les lignes */

.saute { animation: fg-saute .35s var(--pas-anim); }
@keyframes fg-saute { 30% { transform: scale(1.08); color: var(--jaune-survol); } }
html.vivant:not(.calme) .tableau tbody tr.ligne-neuve { animation: fg-ligne var(--duree) var(--pas-anim) both;
                                                         animation-delay: calc(var(--i, 0) * 45ms); }
@keyframes fg-ligne { from { opacity: 0; transform: translateX(-8px); } }
html.vivant:not(.calme) .message:not([hidden]) { animation: fg-glisser var(--duree) var(--pas-anim); }
@keyframes fg-glisser { from { opacity: 0; transform: translateY(-6px); } }
@media (prefers-reduced-motion: no-preference) {
  .bandeau-action { animation: paraitre .18s var(--pas-anim); }
  @keyframes paraitre { from { transform: translateY(-100%); } }
}
.verdict.frappe { overflow: hidden; animation: fg-frappe .35s steps(24, end); }
@keyframes fg-frappe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

/* ---------------------------------------------------- les gestes */

.onde { position: absolute; pointer-events: none; z-index: 2;
        background: radial-gradient(circle, rgba(255,255,255,.35) 0%, transparent 65%);
        transform: scale(0); animation: fg-onde .55s var(--pas-anim) forwards; }
@keyframes fg-onde { to { transform: scale(1); opacity: 0; } }

.bouton.travaille::after {
  content: ""; position: absolute; inset: 0; z-index: 2;
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,.28) 50%, transparent 100%);
  background-size: 40% 100%; background-repeat: no-repeat;
  animation: fg-balayage .9s steps(12, end) infinite;
}
@keyframes fg-balayage { from { background-position: -40% 0; } to { background-position: 140% 0; } }

.tuile.article.incline, .camp-tuile.incline, .pilier.incline {
  transform: perspective(700px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateY(-3px);
  transform-style: preserve-3d; transition: transform .08s linear;
}
.tuile.article:hover .vignette { transform: translateZ(18px) scale(1.06); }
.tuile.article .vignette { transition: transform var(--duree) var(--pas-anim); }

/* ---------------------------------------------------- contraste élevé */

@media (forced-colors: active) {
  body::before, body::after, #poussiere { display: none; }
  .bouton::before, .panneau::before, .tuile::before, .forum-onglet::before, .forum-ligne::before,
  .forum-message::before, .carte-jeu::before, .voie::before, .objet::before, .sous-menu::before,
  .terminal::before { border: 2px solid CanvasText; background: Canvas; }
  .champ.ok :is(input, select, textarea) { border-style: double; border-width: 3px; }
  .champ.ko :is(input, select, textarea) { border-style: dashed; border-width: 2px; }
  .forum-onglet[aria-current="true"], .onglets button[aria-selected="true"] {
    outline: 2px solid Highlight; outline-offset: -4px; text-decoration: underline; }
  .mouvement[aria-pressed="false"] { border-style: dashed; }
  .stat .jauge i, .jauge-longue i, td.avec-barre::after { forced-color-adjust: none; background: Highlight; }
  .voyant, .pastille::before { forced-color-adjust: none; border: 1px solid CanvasText; }
  .bouton-primaire { border: 2px solid ButtonText; }
  .burger span, .burger span::before, .burger span::after { forced-color-adjust: none; background: ButtonText; }
}

/* ---------------------------------------------------- impression */

@media print {
  .nav, .pied, .mouvement, #poussiere, body::before, body::after, .actions, .saut { display: none !important; }
  body { background: #fff; color: #000; }
  .panneau::before, .tuile::before { background: #fff; border-color: #000; }
}
