/* Scène vivante (accueil et pages de rayon seulement) : brise, flamme de la lampe le soir, poussière dans la lumière du jour.
   Animations sur transform (rotate, scale, translate) et opacity seulement : le compositeur les joue, sans mise en page ni repeinte.
   Aucun filtre. Au repos, la scène est immobile ; seules la flamme (soir) et la poussière (jour) bougent en continu.
   Brise : shelf.js met la classe gust sur .room pendant une rafale (durée --gd). Chaque élément part avec un retard
   proportionnel à sa position x (--bx, de 0 à 1, donné par shelf.js) : la vague traverse la pièce de gauche à droite. */

.rib { transform-origin: 0 50%; }
.cord { transform-origin: 50% 0; }
.tsihy::before { transform-origin: 100% 50%; }
.tsihy::after { transform-origin: 0 50%; }

/* Signet en soie qui dépasse du livre (dos tourné : rotation positive = penché vers la droite à l'écran). */
.gust .rib { animation: rib var(--gd, 3s) ease-in-out calc(var(--bx, 0) * 1.2s) both; }
@keyframes rib {
  0%, 100% { rotate: 0deg; } 18% { rotate: 16deg; } 32% { rotate: 7deg; } 48% { rotate: 13deg; } 66% { rotate: 2deg; } 82% { rotate: -3deg; }
}
/* Ruban qui pend du livre du pupitre : son bout part vers la droite. */
.gust .cord { animation: cord var(--gd, 3s) ease-in-out calc(var(--bx, 0) * 1.2s) both; }
@keyframes cord {
  0%, 100% { rotate: 0deg; } 20% { rotate: -9deg; } 36% { rotate: -4deg; } 52% { rotate: -7deg; } 70% { rotate: 1.5deg; } 86% { rotate: -1deg; }
}
/* Frange du tsihy : les brins se soulèvent et frémissent. */
.gust .tsihy::before, .gust .tsihy::after { animation: fringe var(--gd, 3s) ease-in-out calc(var(--bx, 0) * 1.2s) both; }
@keyframes fringe {
  0%, 100% { transform: none; } 22% { transform: skewY(8deg) scaleX(1.12); } 40% { transform: skewY(3deg) scaleX(.96); } 58% { transform: skewY(6deg) scaleX(1.06); } 78% { transform: skewY(-2deg); }
}

/* Aiguille de la boussole : la rafale la fait osciller, puis elle revient au nord. Au survol ou au focus, elle se cale doucement. */
.gust .needle { animation: needle var(--gd, 3s) ease-in-out calc(var(--bx, 0) * 1.2s) both; }
@keyframes needle {
  0%, 100% { rotate: 0deg; } 16% { rotate: 9deg; } 32% { rotate: -6deg; } 48% { rotate: 4deg; } 64% { rotate: -2.5deg; } 80% { rotate: 1deg; }
}
.compass:hover .needle i, .compass:focus-visible .needle i { animation: settle 1.8s ease-out; }
@keyframes settle {
  0%, 100% { rotate: 0deg; } 18% { rotate: -7deg; } 38% { rotate: 4.5deg; } 58% { rotate: -2.5deg; } 78% { rotate: 1deg; }
}

/* Pendulette : heures et minutes en tours continus (43200 s, 3600 s), retard négatif --t (secondes depuis minuit à Antananarivo, shelf.js).
   Trotteuse : pas d'animation steps() (Chrome la joue sur le fil principal, environ 55 recalculs de style par seconde).
   shelf.js pose son angle une fois par seconde ; la transition courte (compositeur) donne le petit rebond du battement. */
.clock .hand { animation: turn 43200s linear var(--t, 0s) infinite; }
.clock .hand.m { animation-duration: 3600s; }
.clock .hand.s { animation: none; transition: transform .16s cubic-bezier(.3, 1.8, .5, 1); }
@keyframes turn { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* Soir : la flamme vacille (deux cycles de durées premières entre elles : jamais deux fois le même mouvement),
   la lueur et la lumière de la pièce suivent le premier cycle (flamme haute = plus de lumière). Jamais de clignotement : écarts faibles, courbes douces. */
html.dark .flame i { animation: flick 3.7s ease-in-out infinite, sway 6.1s ease-in-out infinite; }
@keyframes flick {
  0%, 100% { scale: 1 1; } 13% { scale: .96 1.06; } 27% { scale: 1.02 .95; } 41% { scale: .97 1.09; } 55% { scale: 1.03 .98; } 70% { scale: .95 1.04; } 84% { scale: 1.01 .93; }
}
@keyframes sway { 0%, 100% { rotate: 0deg; } 25% { rotate: 2.5deg; } 50% { rotate: -1.5deg; } 75% { rotate: 1.8deg; } }
html.dark .glow i { animation: glow 3.7s ease-in-out infinite; }
@keyframes glow {
  0%, 100% { opacity: .9; } 13% { opacity: 1; } 27% { opacity: .8; } 41% { opacity: 1; } 55% { opacity: .88; } 70% { opacity: .95; } 84% { opacity: .78; }
}
html.home.dark body::after { animation: room 3.7s ease-in-out infinite; }
@keyframes room {
  0%, 100% { opacity: .985; } 13% { opacity: .965; } 27% { opacity: 1; } 41% { opacity: .96; } 55% { opacity: .99; } 70% { opacity: .975; } 84% { opacity: 1; }
}
/* La rafale couche la flamme et baisse la lueur. */
html.dark .gust .flame { animation: lean var(--gd, 3s) ease-in-out calc(var(--bx, 0) * 1.2s) both; }
@keyframes lean { 0%, 100% { rotate: 0deg; } 20% { rotate: 12deg; } 38% { rotate: 5deg; } 56% { rotate: 9deg; } 78% { rotate: -2deg; } }
html.dark .gust .glow { animation: dim var(--gd, 3s) ease-in-out calc(var(--bx, 0) * 1.2s) both; }
@keyframes dim { 0%, 100% { opacity: 1; } 20% { opacity: .8; } 56% { opacity: .88; } }

/* Jour : quelques grains de poussière flottent lentement dans la lumière de la fenêtre (à gauche). Invisibles sur le mur clair, discrets devant les livres. */
/* will-change : couche du compositeur prête avant le départ (grains invisibles au début de chaque cycle). */
.motes { position: absolute; z-index: 4; inset: 0; pointer-events: none; }
.motes i { position: absolute; left: var(--x); top: var(--y); width: .5rem; height: .5rem; border-radius: 50%; opacity: 0;
  background: radial-gradient(closest-side, rgba(255, 252, 240, .95), rgba(255, 248, 230, 0));
  animation: mote var(--t) ease-in-out var(--d) infinite; will-change: translate, opacity; }
@keyframes mote {
  0% { translate: 0 0; opacity: 0; } 15% { opacity: .75; } 35% { translate: 2rem -1.6rem; } 55% { translate: 3.4rem -.6rem; opacity: .45; }
  80% { translate: 5rem -2.2rem; opacity: .7; } 100% { translate: 6.4rem -1rem; opacity: 0; }
}
html.dark .motes { display: none; }
@media not all and (min-width: 720px) { .motes { display: none; } }

/* Mouvement réduit : scène fixe, flamme fixe (allumée le soir), pas de poussière. */
@media (prefers-reduced-motion: reduce) {
  .motes, .hand.s { display: none; }
  .room *, .room *::before, .room *::after, html.home body::after { animation: none !important; }
}
