/* ==========================================================================
   piste-route.css — revêtements dessinés des bandes routières
   --------------------------------------------------------------------------
   Chaussée et piste de terre pour les bandes `.piste-route` du carnet de
   voyage, avec le mouvement du véhicule et les roues qui tournent.

   Chargé UNIQUEMENT par les articles concernés, après carnet.css :
     article-manic5.html · article-mount-washington.html · en/article-manic5.html

   Tout ce fichier est posé par assets/js/piste-route.js, qui enveloppe l'image
   du véhicule et injecte le sol. Rien ici ne s'applique à une bande qui n'a pas
   reçu de classe de revêtement — les articles qui utilisent .piste-route sans y
   toucher gardent la ligne pointillée et leurs voitures inchangées.

   C'est aussi pour ça que .sol-pose existe : le script ne l'ajoute qu'une fois
   le balisage réellement en place. Sans JavaScript, aucune de ces règles ne
   mord — la bande reste exactement ce qu'elle était.

   Les mesures de la roue viennent du PNG r1s-profil.png (998 × 390). Si l'image
   change, tout est à reprendre — méthode et relevés dans
   Z:/dev/piste-route-r1s/.
   ========================================================================== */

:root {
  --bitume:       #767a74;
  --bitume-fonce: #4f544e;
  --marquage:     #f2ece0;
  --terre:        #9c7d55;
  --terre-fonce:  #6b5233;
}

.piste-route .piste-sol,
.piste-route .route-sol { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; }
.piste-route .piste-sol { height: 24px; }
.piste-route .route-sol { height: 26px; }

.piste-route.sol-pose::after { display: none; }   /* l'ancienne ligne pointillée */

/* La caisse descend au niveau du sol. Sur le bitume elle passe en plus SOUS la
   ligne axiale : en vue de profil cette ligne court au milieu de la route,
   donc derrière le véhicule — si les roues tombent dessus, la voiture a l'air
   de rouler à cheval sur la ligne. */
.piste-route.revetement-terre.sol-pose  .vehicule { bottom: 8px; }
.piste-route.revetement-bitume.sol-pose .vehicule { bottom: 5px; }

/* ---------- les trois couches de mouvement ----------
   `transform` ne peut porter qu'une animation à la fois sur un même élément,
   donc empiler mouvement long, suspension et assiette impose de les répartir
   sur .terrain, .suspension et .chassis.

   Les durées sont sans multiple commun court, pour que le motif combiné ne se
   répète pas de façon perceptible, et les paliers des keyframes sont
   volontairement irréguliers — espacés régulièrement, ils redonneraient un
   rythme métronomique même avec de bonnes durées.

   Un seul jeu de keyframes sert aux DEUX sens de marche : le miroir
   scaleX(-1) est porté par .vehicule (au-dessus) et reste statique, donc ces
   rotations s'appliquent dans le repère local et produisent le même mouvement
   physique — museau qui plonge, arrière qui lève — des deux côtés. */
.piste-route .vehicule .terrain,
.piste-route .vehicule .suspension,
.piste-route .vehicule .chassis { display: block; }

/* la piste de terre CAHOTE */
.piste-route.revetement-terre .terrain    { animation: tt-houle 5.3s ease-in-out infinite; }
.piste-route.revetement-terre .suspension { animation: tt-suspension 2.7s ease-in-out infinite; }
.piste-route.revetement-terre .chassis    { animation: tt-tangage 3.9s ease-in-out infinite; }

@keyframes tt-houle {
  0% { transform: translateY(0); }   19% { transform: translateY(-2.4px); }
  37% { transform: translateY(.8px); } 58% { transform: translateY(-1.6px); }
  81% { transform: translateY(1.2px); } 100% { transform: translateY(0); }
}
@keyframes tt-suspension {
  0% { transform: translateY(0); }   11% { transform: translateY(-1.4px); }
  26% { transform: translateY(.6px); } 43% { transform: translateY(-2.8px); }
  54% { transform: translateY(1.1px); } 69% { transform: translateY(-1px); }
  87% { transform: translateY(-1.9px); } 100% { transform: translateY(0); }
}
@keyframes tt-tangage {
  0% { transform: rotate(0deg); }    14% { transform: rotate(-1.1deg); }
  29% { transform: rotate(.5deg); }  46% { transform: rotate(-1.7deg); }
  61% { transform: rotate(.9deg); }  78% { transform: rotate(-.6deg); }
  92% { transform: rotate(1.1deg); } 100% { transform: rotate(0deg); }
}

/* la chaussée FLOTTE : amplitudes 3 à 5 fois plus faibles, plus une
   composante que le cahotement masquait — le tremblement de roulement,
   rapide et minuscule, qui fait « rouler » au lieu de « glisser » */
.piste-route.revetement-bitume .terrain    { animation: bi-roulement .23s linear infinite; }
.piste-route.revetement-bitume .suspension { animation: bi-flottement 3.1s ease-in-out infinite; }
.piste-route.revetement-bitume .chassis    { animation: bi-assiette 4.7s ease-in-out infinite; }

@keyframes bi-roulement {
  0% { transform: translateY(0); } 50% { transform: translateY(-.35px); } 100% { transform: translateY(0); }
}
@keyframes bi-flottement {
  0% { transform: translateY(0); }   23% { transform: translateY(-1.1px); }
  41% { transform: translateY(.3px); } 64% { transform: translateY(-.8px); }
  86% { transform: translateY(.5px); } 100% { transform: translateY(0); }
}
@keyframes bi-assiette {
  0% { transform: rotate(0deg); }    17% { transform: rotate(-.32deg); }
  38% { transform: rotate(.18deg); } 59% { transform: rotate(-.45deg); }
  81% { transform: rotate(.26deg); } 100% { transform: rotate(0deg); }
}

/* ---------- la poussière (terre) ----------
   La queue du véhicule est toujours dessinée à droite dans le repère LOCAL de
   l'image (elle regarde à gauche à la base), et ce repère ne bouge pas quand
   .vers-droite retourne la boîte en miroir : la poussière est retournée avec
   l'image. Donc `right` reste correct dans les deux sens ; un `left` ici la
   ferait sortir du museau. Même raison pour la dérive vers +x. */
.piste-route .poussiere {
  position: absolute; bottom: 4px; right: -4px; width: 14px; height: 8px;
  border-radius: 50%; opacity: 0; pointer-events: none;
  background: radial-gradient(circle, rgba(150,122,84,.6), rgba(150,122,84,0) 72%);
}
.piste-route.revetement-terre .poussiere { animation: poussiere 1.05s ease-out infinite; }
/* durées ET décalages distincts : trois bouffées de rythmes différents se
   recroisent sans jamais retomber ensemble, contrairement à un simple décalage
   sur une durée commune */
.piste-route .poussiere-1 { animation-duration: 1.05s; animation-delay: 0s; }
.piste-route .poussiere-2 { animation-duration: 1.37s; animation-delay: .38s; }
.piste-route .poussiere-3 { animation-duration: .89s;  animation-delay: .71s; }

@keyframes poussiere {
  0%   { opacity: 0;  transform: translate(0,0) scale(.4); }
  15%  { opacity: .5; }
  100% { opacity: 0;  transform: translate(26px, -10px) scale(1.35); }
}

/* ---------- l'ombre portée au sol (bitume) ----------
   Elle reste AU SOL : posée directement dans .vehicule, en dehors des couches
   qui flottent. Le -2,5 px n'est pas un ajustement à l'œil — le contact réel
   du pneu est à 381 px sur les 390 de l'image, pas au bas de la boîte du
   véhicule ; sans ce décalage l'ombre flotte au-dessus des roues. */
.piste-route .ombre {
  position: absolute; bottom: -2.5px; left: 8%; width: 84%; height: 7px;
  pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(40,32,22,.38), rgba(40,32,22,0) 70%);
}
.piste-route.revetement-bitume .ombre { animation: bi-ombre 3.1s ease-in-out infinite; }

/* en contre-phase du flottement : caisse haute → ombre large et pâle. C'est ce
   qui donne du poids au mouvement au lieu d'un simple glissement vertical. */
@keyframes bi-ombre {
  0%   { transform: scaleX(1);    opacity: .9; }
  23%  { transform: scaleX(1.06); opacity: .68; }
  41%  { transform: scaleX(.98);  opacity: .97; }
  64%  { transform: scaleX(1.04); opacity: .76; }
  86%  { transform: scaleX(.97);  opacity: 1; }
  100% { transform: scaleX(1);    opacity: .9; }
}

/* ---------- les roues qui tournent ----------
   Les jantes sont peintes dans le PNG, on ne peut donc pas les faire tourner
   directement. Chaque .roue est une COPIE ENTIÈRE de l'image, exactement
   superposée à l'originale, puis découpée sur la jante. Comme la rotation se
   fait autour du même centre, la découpe se superpose à elle-même : seul son
   contenu tourne.

   Toutes les valeurs viennent du PNG (998 × 390) — voir piste-route.js et
   Z:/dev/piste-route-r1s/ pour la méthode et les relevés. */
.piste-route .vehicule .chassis {
  position: relative;
  transform-origin: 50% 88%;   /* la caisse pivote autour de l'essieu */
  --roue-av-x: 19.09%;   /* 190,5 px : le CACHE-MOYEU, pas le centre du pneu */
  --roue-ar-x: 80.26%;   /* 801 px   */
  --roue-y:    76.03%;   /* 296,5 px */
  /* la jante seule (~58 px), pas le pneu (~99 px) : le haut du pneu passe
     derrière l'aile, et une découpe qui déborderait repeindrait du pneu
     par-dessus la carrosserie. Le % de clip-path se réfère à
     sqrt((l²+h²)/2), soit 0,759 × la largeur, d'où 7,66 %. */
  --roue-r:     7.66%;
}

/* sélecteur aussi spécifique que la règle générale des images du véhicule,
   sinon son drop-shadow s'appliquerait une seconde fois sur chaque copie */
.piste-route .vehicule img.calque {
  position: absolute; inset: 0; width: 100%; height: auto; display: block;
  filter: none;
}

/* le jaune devient transparent sur la jante tournante, sinon on verrait
   l'étrier faire le tour de la roue. Le seuil doit être BAS : dans le disque,
   11 059 px ont un écart rouge−bleu de 0 à 9 (les gris neutres) alors que
   l'étrier s'étale de 10 à 190 ; son contour brun ombré, ~440 px, laisserait
   sinon un fantôme tourner. */
.piste-route .vehicule img.roue { filter: url(#f-sans-jaune); }

/* fond sombre glissé SOUS la jante : il masque l'étrier de l'image de base
   — sans lui, le trou du filtre viendrait s'aligner dessus une fois par tour
   et le ferait clignoter — et sert de fond aux creux devenus transparents */
.piste-route .fond-roue {
  position: absolute; top: var(--roue-y); width: 11.6%; aspect-ratio: 1;
  transform: translate(-50%, -50%); border-radius: 50%; background: #14171a;
}
.piste-route .fond-av { left: var(--roue-av-x); }
.piste-route .fond-ar { left: var(--roue-ar-x); }

/* l'étrier de frein : solidaire du porte-moyeu, il ne tourne pas, et les
   rayons passent DEVANT lui — d'où le détourage des creux de la jante */
.piste-route .frein {
  position: absolute; top: var(--roue-y); width: 14.03%; aspect-ratio: 1;
  transform: translate(-50%, -50%); overflow: visible;
  display: none;   /* révélé seulement si le détourage a pu être posé */
}
.piste-route .frein-av { left: var(--roue-av-x); }
.piste-route .frein-ar { left: var(--roue-ar-x); }
.piste-route .etrier-arc { fill: #d99e50; }

.piste-route .roue-av {
  clip-path: circle(var(--roue-r) at var(--roue-av-x) var(--roue-y));
  transform-origin: var(--roue-av-x) var(--roue-y);
}
.piste-route .roue-ar {
  clip-path: circle(var(--roue-r) at var(--roue-ar-x) var(--roue-y));
  transform-origin: var(--roue-ar-x) var(--roue-y);
}

/* Sans le détourage, la jante garde sa découpe circulaire et l'étrier reste
   caché : pas d'étrier plutôt qu'un étrier posé devant les rayons. */
.piste-route.rayons-detoures .frein { display: block; }
.piste-route.rayons-detoures .roue-av { clip-path: url(#c-rayons-av); }
.piste-route.rayons-detoures .roue-ar { clip-path: url(#c-rayons-ar); }

/* Un seul sens de rotation pour les deux directions, même raison que le
   reste : dans le repère local la voiture regarde à gauche, donc avancer
   c'est tourner en sens antihoraire — le miroir de .vehicule le rend horaire
   quand elle roule vers la droite. La durée est liée à celle du trajet :
   ~24 tours par traversée, soit le roulement sans glissement à cette échelle. */
.piste-route .roue { animation: tourne-roue calc(55.78125s / 24) linear infinite; }
@keyframes tourne-roue { to { transform: rotate(-360deg); } }

@media (prefers-reduced-motion: reduce) {
  .piste-route .terrain, .piste-route .suspension, .piste-route .chassis,
  .piste-route .ombre, .piste-route .roue { animation: none; }
  .piste-route .poussiere { display: none; }
}

