/* =========================================================
   PAVAGE ANIMÉ — scène « verre fumé »
   Dalles de verre violet translucide, posées sur une lueur
   qui dérive lentement en dessous. Les dalles remontent du noir.
   ========================================================= */
:root {
  --pavage-duree: 0.9s;      /* montée d'une dalle */
  --pavage-hauteur: 26px;    /* profondeur d'où remonte chaque dalle */
  --pavage-lueur-1: #7c3aed; /* couleurs de la lueur sous le verre */
  --pavage-lueur-2: #c026d3;
  --pavage-lueur-3: #4f46e5;
}

/* Le bloc #layer garde son id (utilisé par dayDiff() dans 2310.js)
   mais n'affiche plus l'ancienne image de fond */
#layer.pavage-hote {
  height: auto;
  background-image: none !important;
}
#layer.pavage-hote #zonetxt { display: none !important; }

.pavage {
  position: relative;
  width: 100%;
  aspect-ratio: 768 / 205;
  background: #050208;
  container-type: inline-size;   /* textes proportionnels à la taille du pavage */
  overflow: hidden;
  isolation: isolate;
}
.pavage-fond,
.dalle,
.pavage-lueur { position: absolute; display: block; }
.pavage-fond { inset: 0; width: 100%; height: 100%; }   /* joints noirs */
.dalle img,
img.dalle { width: 100%; height: auto; }

/* Lueur sous le verre : trois taches de lumière floues qui dérivent */
.pavage-lueur {
  inset: -25%;
  background:
    radial-gradient(28% 45% at 30% 45%, var(--pavage-lueur-1), transparent 70%),
    radial-gradient(25% 40% at 68% 60%, var(--pavage-lueur-2), transparent 70%),
    radial-gradient(22% 35% at 52% 25%, var(--pavage-lueur-3), transparent 70%);
  filter: blur(20px);
  opacity: 0.75;
  animation: pavage-derive 18s ease-in-out infinite alternate;
}
@keyframes pavage-derive {
  0%   { transform: translate(-6%, 2%) rotate(0deg); }
  50%  { transform: translate(5%, -3%) rotate(4deg); }
  100% { transform: translate(-2%, 4%) rotate(-3deg); }
}

/* Les images sont rectangulaires : leurs coins transparents ne doivent pas
   capter la souris. Seule la zone .zone (forme exacte de la dalle) est cliquable. */
.pavage-fond, img.dalle, .dalle-lien { pointer-events: none; }
.dalle-lien .zone {
  position: absolute;
  inset: 0;
  pointer-events: auto;
}

/* ---------- Avant l'animation : tout est dans le noir ---------- */
.pavage.attente .pavage-lueur,
.pavage.attente .dalle { opacity: 0; }

/* ---------- Animation d'arrivée ---------- */
.pavage.monte .pavage-lueur {
  animation:
    pavage-allume 1.6s ease-out both,
    pavage-derive 18s ease-in-out infinite alternate;
}
.pavage.monte .dalle {
  animation: pavage-monte var(--pavage-duree) cubic-bezier(.2, .7, .3, 1) var(--d, 0s) both;
}
@keyframes pavage-allume {
  from { opacity: 0; }
  to   { opacity: 0.75; }
}
/* La dalle remonte des profondeurs, dépasse à peine, puis se pose */
@keyframes pavage-monte {
  0%   { opacity: 0; transform: translateY(var(--pavage-hauteur)) scale(0.96); }
  60%  { opacity: 1; }
  80%  { transform: translateY(-2px) scale(1.005); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

/* ---------- Dalles-liens ---------- */
.dalle-lien {
  --c: #7c3aed;              /* même violet au survol pour toutes les dalles */
  transition: translate 0.25s ease, filter 0.25s ease;
}

/* Lumière intérieure de la couleur du site, à la forme exacte de la dalle */
.dalle-lien .lumiere {
  position: absolute;
  inset: 0;
  background: radial-gradient(75% 95% at 50% 50%, var(--c), transparent 85%);
  mix-blend-mode: screen;
  opacity: 0;
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  transition: opacity 0.3s ease;
}

/* Nom du site dans la dalle : invisible à l'écran mais lu par les lecteurs d'écran.
   Au survol, il s'affiche dans la légende sous le pavage (voir pavage.js). */
.dalle-lien .nom {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Petite licorne gravée en creux dans la dalle 2h38, avec le même traitement que le kanji de la dalle 23h10 :
   creux sombre, ombre d'1 px au-dessus, reflet violet clair d'1 px en dessous, couchée dans la perspective de la dalle */
.dalle-lien .licorne {
  position: absolute;
  width: 6.4cqw;
  translate: -50% -50%;
  overflow: visible;
  pointer-events: none;
  fill: rgba(255, 255, 255, 0.5);   /* blanc semi-transparent, comme le kanji */
  /* axe horizontal le long du bord haut de la dalle (-3°), axe vertical penché comme ses bords latéraux */
  transform: matrix(0.998, -0.055, 0.5, 0.6, 0, 0);
  /* reflet blanc-violet sur le bord bas, ombre sur le bord haut, comme le kanji
     (décalages un peu plus forts : la perspective les écrase, et la silhouette a peu de bords) */
  filter: drop-shadow(0 -1.6px 0 rgba(0, 0, 0, 0.55)) drop-shadow(0 1.8px 0 rgba(221, 214, 254, 0.6));
}

/* Symbole infini-cœur gravé dans la dalle 0h05, même traitement que la licorne et le kanji :
   blanc semi-transparent, léger relief, couché dans la perspective de la dalle.
   Trait calligraphique : le dessin est fait de courts segments d'épaisseur variable (plein / délié),
   tracés en blanc opaque ; la transparence est appliquée à l'ensemble (sans surépaisseur aux raccords). */
.dalle-lien .infini {
  position: absolute;
  width: 10cqw;
  translate: -50% -50%;
  overflow: visible;
  pointer-events: none;
  fill: none;
  stroke: #fff;
  stroke-linecap: round;
  opacity: 0.55;
  /* axe horizontal le long du bord haut de la dalle (-2°), axe vertical penché comme ses bords latéraux */
  transform: matrix(0.999, -0.03, 0.25, 0.7, 0, 0);
  filter: drop-shadow(0 -1.2px 0 rgba(0, 0, 0, 0.55)) drop-shadow(0 1.4px 0 rgba(221, 214, 254, 0.6));
}

/* Kanji gravé en creux dans la dalle : plus sombre que le verre,
   ombre sur le bord haut et reflet clair sur le bord bas */
.dalle-lien .kanji {
  position: absolute;
  translate: -50% -50%;
  white-space: nowrap;
  font: 400 5.2cqw/1 "Yu Mincho", "Hiragino Mincho ProN", "Noto Serif CJK JP", "MS Mincho", serif;
  color: rgba(255, 255, 255, 0.5);   /* blanc semi-transparent */
  /* orienté comme la dalle : axe horizontal le long du bord haut (-4°),
     axe vertical penché comme les bords latéraux, légèrement écrasé par la perspective */
  rotate: none;
  transform: matrix(0.997, -0.072, 0.37, 0.6, 0, 0);
  text-shadow:
    0 -1px 0 rgba(0, 0, 0, 0.55),
    0 1px 0 rgba(196, 181, 253, 0.45);
}

.dalle-lien:not(.en-cours):hover,
.dalle-lien:not(.en-cours):focus-visible {   /* la dalle dont l'ambiance est lancée (en-cours) redevient comme les autres */
  translate: 0 -4px;
  filter: drop-shadow(0 6px 6px rgba(0, 0, 0, 0.9)) drop-shadow(0 0 8px rgba(124, 58, 237, 0.55));
  z-index: 2;
}
.dalle-lien:not(.en-cours):hover .lumiere,
.dalle-lien:not(.en-cours):focus-visible .lumiere { opacity: 0.45; }

.dalle-lien:focus-visible { outline: none; }

/* Pendant une ambiance, la dalle survolée réagit toujours (elle se soulève et s'éclaire)
   mais reste derrière l'animation au lieu de passer devant */
.pavage[class*="-active"] .dalle-lien:not(.en-cours):hover,
.pavage[class*="-active"] .dalle-lien:not(.en-cours):focus-visible { z-index: 0; }

/* « Nous 3 » (ambiance 0h05) : les trois dalles à icône (kanji, licorne, infini-cœur) s'illuminent
   tant que le mot est lisible (classe « surbrillance » posée par pavage.js), puis reviennent doucement */
.dalle-lien[data-site="23h10"], .dalle-lien[data-site="2h38"], .dalle-lien[data-site="0h05"] {
  transition: translate 0.25s ease, filter 1.2s ease;
}
.dalle-lien .kanji, .dalle-lien .licorne, .dalle-lien .infini { transition: color 1.2s ease, fill 1.2s ease, opacity 1.2s ease; }
.pavage.surbrillance .dalle-lien[data-site="23h10"],
.pavage.surbrillance .dalle-lien[data-site="2h38"],
.pavage.surbrillance .dalle-lien[data-site="0h05"] {
  --c: #ffffff;
  filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.7)) drop-shadow(0 0 16px rgba(255, 255, 255, 0.45));
  transition: translate 0.25s ease, filter 0.6s ease;
}
.pavage.surbrillance .dalle-lien[data-site="23h10"] .lumiere,
.pavage.surbrillance .dalle-lien[data-site="2h38"] .lumiere,
.pavage.surbrillance .dalle-lien[data-site="0h05"] .lumiere {
  opacity: 0.7;
  transition: opacity 0.6s ease;
}
.dalle-lien[data-site="23h10"] .lumiere,
.dalle-lien[data-site="2h38"] .lumiere,
.dalle-lien[data-site="0h05"] .lumiere { transition: opacity 1.2s ease; }   /* retour en douceur */
.pavage.surbrillance .dalle-lien .kanji   { color: rgba(255, 255, 255, 0.95); transition-duration: 0.6s; }
.pavage.surbrillance .dalle-lien .licorne { fill: rgba(255, 255, 255, 0.95); transition-duration: 0.6s; }
.pavage.surbrillance .dalle-lien .infini  { opacity: 0.95; transition-duration: 0.6s; }

/* ---------- Bouton rond de fermeture de l'ambiance (en haut à droite, visible pendant une ambiance) ----------
   Fond transparent : un fin cercle et une croix blancs, entourés d'un léger halo de lumière.
   Au survol, le halo s'intensifie, un voile lumineux à peine visible apparaît et la croix pivote d'un quart de tour. */
.fermer-ambiance {
  position: absolute;
  z-index: 5;                     /* au-dessus des ambiances et des dalles */
  top: 4%;
  right: 1.3%;
  width: max(18px, 2.2cqw);
  aspect-ratio: 1;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.18), transparent 70%) center / 0 0 no-repeat;
  box-shadow: 0 0 6px rgba(221, 214, 254, 0.55), inset 0 0 4px rgba(221, 214, 254, 0.35);
  filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.55));   /* lisible aussi sur un fond clair */
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  scale: 0.6;
  transition: opacity 0.25s ease, scale 0.25s ease, box-shadow 0.3s ease, background-size 0.3s ease, visibility 0s linear 0.25s;
}
.fermer-ambiance.visible {
  opacity: 1;
  visibility: visible;
  scale: 1;
  transition: opacity 0.3s ease, scale 0.35s cubic-bezier(.3, 1.5, .5, 1), box-shadow 0.3s ease, background-size 0.3s ease, visibility 0s;
}
.fermer-ambiance::before,
.fermer-ambiance::after {         /* la croix blanche, fine et aux bouts arrondis */
  content: "";
  position: absolute;
  left: 24%;
  top: 50%;
  width: 52%;
  height: 1.2px;
  margin-top: -0.6px;
  border-radius: 1px;
  background: #fff;
  box-shadow: 0 0 3px rgba(255, 255, 255, 0.8);
  rotate: 45deg;
  transition: rotate 0.35s cubic-bezier(.3, 1.4, .5, 1);
}
.fermer-ambiance::after { rotate: -45deg; }
.fermer-ambiance:hover {
  scale: 1.1;
  background-size: 100% 100%;
  box-shadow: 0 0 10px rgba(221, 214, 254, 0.9), 0 0 2px #fff, inset 0 0 6px rgba(221, 214, 254, 0.5);
}
.fermer-ambiance:hover::before { rotate: 135deg; }
.fermer-ambiance:hover::after  { rotate: 45deg; }
.fermer-ambiance:active { scale: 0.92; }
.fermer-ambiance:focus-visible { outline: 1px solid #c4b5fd; outline-offset: 3px; }

/* ---------- Légende sous le pavage : nom du lien survolé, aligné à gauche ---------- */
.pavage-legende {
  min-height: 1.6em;              /* place réservée : la page ne bouge pas */
  padding: 6px 0 0 15px;          /* décalé de 15 px vers la droite */
  text-align: left;
  font: 600 12px/1.6 system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  letter-spacing: 0.12em;
  color: #fff;
  text-shadow: 0 0 6px #a78bfa, 0 0 14px #a78bfa;
  opacity: 0;
  transition: opacity 0.3s ease;
}
.pavage-legende.visible { opacity: 1; }

/* ---------- Mouvement réduit : pavage affiché directement, lueur fixe ---------- */
@media (prefers-reduced-motion: reduce) {
  .pavage.attente .pavage-lueur,
  .pavage.attente .dalle { opacity: 1; }
  .pavage-lueur,
  .pavage.monte .pavage-lueur,
  .pavage.monte .dalle { animation: none; }
  .pavage-lueur { opacity: 0.75; }
  .dalle-lien,
  .pavage-legende { transition: none; }
}

/* =========================================================
   AMBIANCE 0h05 — au survol du lien 0h05 :
   à gauche l'amour (rouge, cœurs), à droite les épreuves (noir, éclairs)
   ========================================================= */
.amb {
  position: absolute;
  inset: 0;
  z-index: 1;                    /* au-dessus des dalles, sous la dalle survolée */
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.6s ease, visibility 0s linear 0.6s;
}
.pavage.ambiance-0h05-active .amb-0h05 {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.6s ease, visibility 0s;
}
.amb > div { position: absolute; inset: 0; }
.eclairs { position: absolute; inset: 0; }

/* ----- Gauche : l'amour ----- */
.amour-teinte {                  /* le verre violet vire au rouge */
  background: linear-gradient(90deg, #e11d48 0%, #e11d48 58%, transparent 72%);   /* l'amour : 70 % à gauche */
  mix-blend-mode: color;
}
.amour-lueur > div {             /* lueur rouge-rose chaleureuse */
  background:
    radial-gradient(45% 85% at 28% 60%, rgba(251, 113, 133, 0.55), transparent 70%),
    radial-gradient(30% 60% at 55% 30%, rgba(225, 29, 72, 0.35), transparent 70%);
}
.amour-lueur { mix-blend-mode: screen; }
.amour-lueur > div { animation: amour-battement 1.6s ease-in-out infinite; }
@keyframes amour-battement {     /* pulsation lente, comme un cœur */
  0%, 100% { opacity: 0.8; }
  15%      { opacity: 1; }
  30%      { opacity: 0.85; }
  45%      { opacity: 1; }
}
.coeur {
  position: absolute;
  bottom: -10%;
  width: var(--t);
  fill: #fb7185;
  filter: drop-shadow(0 0 4px #f43f5e) drop-shadow(0 0 10px rgba(244, 63, 94, 0.6));
  opacity: 0;
  animation: coeur-monte var(--du) ease-in var(--dl) infinite;
}
.coeur svg { display: block; width: 100%; height: auto; }
@keyframes coeur-monte {
  0%   { opacity: 0;   transform: translate(0, 0) scale(0.6); }
  15%  { opacity: 0.9; }
  70%  { opacity: 0.7; }
  100% { opacity: 0;   transform: translate(var(--dx), calc(var(--t) * -9)) scale(1.05); }
}

/* ----- Droite : les épreuves de la vie ----- */
.epreuves-gris {                 /* les couleurs s'éteignent */
  background: linear-gradient(270deg, #808080 0%, #808080 22%, transparent 34%);   /* les épreuves : 30 % à droite */
  mix-blend-mode: saturation;
}
.epreuves-ombre {                /* obscurité qui gagne depuis la droite */
  background: linear-gradient(270deg, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.65) 22%, transparent 34%);
}
.epreuves-flash > div {          /* lueur bleutée de l'éclair sur le sol */
  background: radial-gradient(22% 90% at 85% 40%, rgba(199, 210, 254, 0.35), transparent 70%);
  opacity: 0;
  animation: eclair-crepite 2.3s linear infinite;
}
.eclairs { width: 100%; height: 100%; overflow: visible; }
.eclair polyline {
  fill: none;
  stroke: #eef2ff;
  stroke-width: 1.6;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.eclair .branche { stroke-width: 0.9; opacity: 0.8; }
.eclair {
  filter: drop-shadow(0 0 2px #a5b4fc) drop-shadow(0 0 6px #818cf8);
  opacity: 0;
  transform-box: fill-box;        /* déplacement / miroir appliqués par pavage.js à chaque flash */
  transform-origin: center;
}
.e1 { animation: eclair-crepite 2.3s linear infinite; }
.e2 { animation: eclair-crepite 3.1s linear 0.9s infinite; }
.e3 { animation: eclair-crepite 1.9s linear 1.6s infinite; }
/* éclair : éclats irréguliers, puis disparition complète jusqu'au suivant */
@keyframes eclair-crepite {
  0%, 100% { opacity: 0; }
  3%       { opacity: 1; }
  6%       { opacity: 0.3; }
  9%       { opacity: 0.95; }
  13%      { opacity: 0.5; }
  16%      { opacity: 1; }
  22%      { opacity: 0; }
}

/* Mouvement réduit : ambiance fixe, sans cœurs qui montent ni éclairs qui clignotent */
@media (prefers-reduced-motion: reduce) {
  .amb, .pavage.ambiance-0h05-active .amb-0h05 { transition: none; }
  .amour-lueur > div, .epreuves-flash > div, .coeur, .eclair { animation: none; }
  .coeurs-guerison { display: none; }
  .coeur { opacity: 0.7; bottom: auto; top: 50%; }
  .eclair { opacity: 0.6; }
}

/* Cycle de 35 s pendant le survol :
   0-9 s     : équilibre (rouge 70 % / noir 30 %)
   9-11 s    : le rouge envahit tout le pavage
   11-32 s   : rouge plein ; un cœur fêlé apparaît à droite (12 s), l'or comble ses fêlures
               (12,6-20,8 s), les fêlures disparaissent (21 s), il s'illumine (22,4 s) et bat 10 fois
   32-34 s   : le noir revient sur ses 30 %
   On anime « filter: opacity() » pour ne pas gêner le fondu d'entrée des calques (propriété opacity). */
.amour-teinte-totale {           /* rouge sur toute la largeur */
  background: #e11d48;
  mix-blend-mode: color;
  filter: opacity(0);
}
.pavage.ambiance-0h05-active .amour-teinte-totale {
  animation: amour-envahit 35s ease-in-out infinite;
}
.pavage.ambiance-0h05-active .epreuves-gris,
.pavage.ambiance-0h05-active .epreuves-ombre,
.pavage.ambiance-0h05-active .epreuves-flash,
.pavage.ambiance-0h05-active .epreuves-eclairs {
  animation: epreuves-reculent 35s ease-in-out infinite;
}
@keyframes amour-envahit {
  0%, 25.71%       { filter: opacity(0); }
  31.43%, 91.43% { filter: opacity(1); }
  97.14%, 100%    { filter: opacity(0); }
}
@keyframes epreuves-reculent {
  0%, 25.71%       { filter: opacity(1); }
  31.43%, 91.43% { filter: opacity(0); }
  97.14%, 100%    { filter: opacity(1); }
}

/* Le cœur fêlé, ressoudé à l'or (kintsugi) : fêlures fines qui vont jusqu'au bord,
   comblées d'or une à une, puis effacées une fois le cœur ressoudé ; il s'illumine et bat 10 fois */
.coeurs-guerison svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.coeur-fendu {
  fill: #ef1a3a;                 /* rouge vif */
  opacity: 0;
  transform-box: fill-box;
  transform-origin: 50% 55%;
}
.coeur-ombre { fill: #000; opacity: 0.35; }   /* ombre portée au sol */
.coeur-violet { opacity: 0; }                  /* juste après l'éclatement, le cœur prend le violet des dalles */
.pavage.ambiance-0h05-active .coeur-violet { animation: coeur-violet 35s ease-in-out infinite; }
@keyframes coeur-violet {
  0%, 60.14% { opacity: 0; }
  62.00%, 100% { opacity: 1; }
}
.feles polyline, .feles-or polyline {
  fill: none;
  stroke-linejoin: miter;
  stroke-linecap: round;
}
.feles polyline { stroke: #2a020c; stroke-width: 0.3; }            /* fêlures très fines et nettes */
.feles-or { filter: drop-shadow(0 0 0.4px #fde68a) drop-shadow(0 0 0.9px #f59e0b); }
.feles-or polyline {
  stroke: #f5c542;               /* or */
  stroke-width: 0.28;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;          /* l'or se dépose le long de la fêlure */
}
.pavage.ambiance-0h05-active .coeur-fendu {
  animation: coeur-guerit 35s ease-in-out infinite, coeur-bat 35s linear infinite;
}
.pavage.ambiance-0h05-active .feles,
.pavage.ambiance-0h05-active .feles-or { animation: feles-disparaissent 35s ease-in-out infinite; }
.pavage.ambiance-0h05-active .or-v1 { animation: or-1 35s ease-in-out infinite; }
.pavage.ambiance-0h05-active .or-v2 { animation: or-2 35s ease-in-out infinite; }
.pavage.ambiance-0h05-active .or-v3 { animation: or-3 35s ease-in-out infinite; }
.pavage.ambiance-0h05-active .or-v4 { animation: or-4 35s ease-in-out infinite; }
.pavage.ambiance-0h05-active .or-v5 { animation: or-5 35s ease-in-out infinite; }
@keyframes coeur-guerit {
  0%, 26.57%        { opacity: 0; filter: none; }
  28.29%            { opacity: 1; filter: drop-shadow(0 0 1px #4c0519); }                              /* intact */
  29.14%           { opacity: 1; filter: brightness(1.9) drop-shadow(0 0 4px #fff) drop-shadow(0 0 10px #c7d2fe); } /* 1er impact */
  30.00%           { opacity: 1; filter: drop-shadow(0 0 1px #4c0519); }
  31.14%           { opacity: 1; filter: brightness(1.9) drop-shadow(0 0 4px #fff) drop-shadow(0 0 10px #c7d2fe); } /* 2e impact : brisé */
  32.00%           { opacity: 1; filter: drop-shadow(0 0 1px #4c0519); }                              /* fêlé */
  59.43%           { opacity: 1; filter: drop-shadow(0 0 1px #4c0519); }
  60.14%          { opacity: 1; filter: drop-shadow(0 0 3px #fde68a) drop-shadow(0 0 9px #f59e0b); } /* éclatement */
  62.29%           { opacity: 1; filter: drop-shadow(0 0 1px #2e1065); }                              /* ressoudé, violet */
  64.00%           { opacity: 1; filter: drop-shadow(0 0 3px #ede9fe) drop-shadow(0 0 8px #8b5cf6); } /* s'illumine */
  67.43%, 92.00% { opacity: 1; filter: drop-shadow(0 0 2px #c4b5fd) drop-shadow(0 0 6px #7c3aed); }
  94.86%, 100%     { opacity: 1; filter: drop-shadow(0 0 2px #c4b5fd) drop-shadow(0 0 6px #7c3aed); }   /* reste visible entre les boucles */
}
@keyframes coeur-bat {          /* secousse aux deux impacts, puis 10 battements « boum-boum » */
  0%, 29.09% { transform: scale(1); }
  29.20% { transform: scale(0.93) rotate(-3deg); }
  29.60% { transform: scale(1.02) rotate(2deg); }
  30.00% { transform: scale(1); }
  31.09% { transform: scale(1); }
  31.20% { transform: scale(0.92) rotate(3deg); }
  31.60% { transform: scale(1.02) rotate(-2deg); }
  32.00%, 63.97% { transform: scale(1); }
  64.00% { transform: scale(1); }
  64.43% { transform: scale(1.13); }
  65.03% { transform: scale(1); }
  65.46% { transform: scale(1.07); }
  66.23% { transform: scale(1); }
  66.86% { transform: scale(1); }
  67.29% { transform: scale(1.13); }
  67.89% { transform: scale(1); }
  68.31% { transform: scale(1.07); }
  69.09% { transform: scale(1); }
  69.71% { transform: scale(1); }
  70.14% { transform: scale(1.13); }
  70.74% { transform: scale(1); }
  71.17% { transform: scale(1.07); }
  71.94% { transform: scale(1); }
  72.57% { transform: scale(1); }
  73.00% { transform: scale(1.13); }
  73.60% { transform: scale(1); }
  74.03% { transform: scale(1.07); }
  74.80% { transform: scale(1); }
  75.43% { transform: scale(1); }
  75.86% { transform: scale(1.13); }
  76.46% { transform: scale(1); }
  76.89% { transform: scale(1.07); }
  77.66% { transform: scale(1); }
  78.29% { transform: scale(1); }
  78.71% { transform: scale(1.13); }
  79.31% { transform: scale(1); }
  79.74% { transform: scale(1.07); }
  80.51% { transform: scale(1); }
  81.14% { transform: scale(1); }
  81.57% { transform: scale(1.13); }
  82.17% { transform: scale(1); }
  82.60% { transform: scale(1.07); }
  83.37% { transform: scale(1); }
  84.00% { transform: scale(1); }
  84.43% { transform: scale(1.13); }
  85.03% { transform: scale(1); }
  85.46% { transform: scale(1.07); }
  86.23% { transform: scale(1); }
  86.86% { transform: scale(1); }
  87.29% { transform: scale(1.13); }
  87.89% { transform: scale(1); }
  88.31% { transform: scale(1.07); }
  89.09% { transform: scale(1); }
  89.71% { transform: scale(1); }
  90.14% { transform: scale(1.13); }
  90.74% { transform: scale(1); }
  91.17% { transform: scale(1.07); }
  91.94% { transform: scale(1); }
  100% { transform: scale(1); }
}
/* Les fêlures apparaissent au moment où les éclairs frappent le cœur */
.feles .fa, .feles .fb { opacity: 0; }
.pavage.ambiance-0h05-active .feles .fa { animation: feles-1er-impact 35s linear infinite; }
.pavage.ambiance-0h05-active .feles .fb { animation: feles-2e-impact 35s linear infinite; }
@keyframes feles-1er-impact { 0%, 29.11% { opacity: 0; } 29.20%, 100% { opacity: 1; } }
@keyframes feles-2e-impact  { 0%, 31.11% { opacity: 0; } 31.20%, 100% { opacity: 1; } }

/* Les deux derniers éclairs, qui frappent le cœur pendant que le noir se retire */
.foudre polyline {
  fill: none;
  stroke: #f8fafc;
  stroke-width: 2;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.foudre .branche { stroke-width: 1; }
.foudre { opacity: 0; filter: drop-shadow(0 0 2px #c7d2fe) drop-shadow(0 0 7px #818cf8); }
.impact { fill: #fff; opacity: 0; filter: blur(3px); transform-box: fill-box; transform-origin: center; }
.pavage.ambiance-0h05-active .foudre-1, .pavage.ambiance-0h05-active .impact-1 { animation: foudre-1 35s linear infinite; }
.pavage.ambiance-0h05-active .foudre-2, .pavage.ambiance-0h05-active .impact-2 { animation: foudre-2 35s linear infinite; }
@keyframes foudre-1 {
  0%, 28.91% { opacity: 0; }
  29.09% { opacity: 1; }
  29.31% { opacity: 0.35; }
  29.49% { opacity: 1; }
  30.00%, 100% { opacity: 0; }
}
@keyframes foudre-2 {
  0%, 30.91% { opacity: 0; }
  31.09% { opacity: 1; }
  31.31% { opacity: 0.35; }
  31.49% { opacity: 1; }
  32.14%, 100% { opacity: 0; }
}

/* À partir de la 2e boucle : le cœur violet entier remplace le cœur brisé.
   Les deux cœurs tournent en permanence sur le même rythme de 35 s ;
   on rend seulement visible celui de la boucle en cours (visibility ne redémarre pas les animations).
   Les deux éclairs rebondissent sur le cœur entier (bouclier violet + foudre renvoyée),
   puis, 2 s après, il s'illumine et bat 10 fois. */
.groupe-entier, .bouclier, .rebond { visibility: hidden; }
.pavage[data-boucle="2"] .groupe-brise,
.pavage[data-boucle="3"] .groupe-brise,
.pavage[data-boucle="4"] .groupe-brise,
.pavage[data-boucle="5"] .groupe-brise { visibility: hidden; }
.pavage[data-boucle="2"] .groupe-entier,
.pavage[data-boucle="3"] .groupe-entier,
.pavage[data-boucle="4"] .groupe-entier,
.pavage[data-boucle="5"] .groupe-entier,
.pavage[data-boucle="2"] .bouclier,
.pavage[data-boucle="3"] .bouclier,
.pavage[data-boucle="4"] .bouclier,
.pavage[data-boucle="5"] .bouclier,
.pavage[data-boucle="2"] .rebond,
.pavage[data-boucle="3"] .rebond,
.pavage[data-boucle="4"] .rebond,
.pavage[data-boucle="5"] .rebond { visibility: visible; }
.coeur-entier {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: 50% 55%;
}
.pavage.ambiance-0h05-active .coeur-entier {
  animation: coeur-intact 35s ease-in-out infinite, coeur-bat-intact 35s linear infinite;
}
@keyframes coeur-intact {
  0%, 26.57%       { opacity: 1; filter: drop-shadow(0 0 2px #c4b5fd) drop-shadow(0 0 6px #7c3aed); }   /* déjà là depuis la boucle précédente */
  28.29%           { opacity: 1; filter: drop-shadow(0 0 1px #2e1065); }
  29.14%          { opacity: 1; filter: brightness(1.6) drop-shadow(0 0 4px #fff) drop-shadow(0 0 10px #a78bfa); }
  30.00%          { opacity: 1; filter: drop-shadow(0 0 1px #2e1065); }
  31.14%          { opacity: 1; filter: brightness(1.6) drop-shadow(0 0 4px #fff) drop-shadow(0 0 10px #a78bfa); }
  32.00%          { opacity: 1; filter: drop-shadow(0 0 1px #2e1065); }      /* complet et intact */
  36.00%          { opacity: 1; filter: drop-shadow(0 0 1px #2e1065); }
  37.71%          { opacity: 1; filter: drop-shadow(0 0 3px #ede9fe) drop-shadow(0 0 8px #8b5cf6); }   /* 2 s après : s'illumine */
  41.14%, 92.00% { opacity: 1; filter: drop-shadow(0 0 2px #c4b5fd) drop-shadow(0 0 6px #7c3aed); }
  94.86%, 100%     { opacity: 1; filter: drop-shadow(0 0 2px #c4b5fd) drop-shadow(0 0 6px #7c3aed); }   /* reste visible entre les boucles */
}
@keyframes coeur-bat-intact {    /* léger recul aux impacts, puis 10 battements dès 13,2 s */
  0%, 29.09% { transform: scale(1); }
  29.20% { transform: scale(0.97); }
  29.60% { transform: scale(1.01); }
  30.00%, 31.09% { transform: scale(1); }
  31.20% { transform: scale(0.97); }
  31.60% { transform: scale(1.01); }
  32.00%, 37.69% { transform: scale(1); }
  37.71% { transform: scale(1); }
  38.14% { transform: scale(1.13); }
  38.74% { transform: scale(1); }
  39.17% { transform: scale(1.07); }
  39.94% { transform: scale(1); }
  40.57% { transform: scale(1); }
  41.00% { transform: scale(1.13); }
  41.60% { transform: scale(1); }
  42.03% { transform: scale(1.07); }
  42.80% { transform: scale(1); }
  43.43% { transform: scale(1); }
  43.86% { transform: scale(1.13); }
  44.46% { transform: scale(1); }
  44.89% { transform: scale(1.07); }
  45.66% { transform: scale(1); }
  46.29% { transform: scale(1); }
  46.71% { transform: scale(1.13); }
  47.31% { transform: scale(1); }
  47.74% { transform: scale(1.07); }
  48.51% { transform: scale(1); }
  49.14% { transform: scale(1); }
  49.57% { transform: scale(1.13); }
  50.17% { transform: scale(1); }
  50.60% { transform: scale(1.07); }
  51.37% { transform: scale(1); }
  52.00% { transform: scale(1); }
  52.43% { transform: scale(1.13); }
  53.03% { transform: scale(1); }
  53.46% { transform: scale(1.07); }
  54.23% { transform: scale(1); }
  54.86% { transform: scale(1); }
  55.29% { transform: scale(1.13); }
  55.89% { transform: scale(1); }
  56.31% { transform: scale(1.07); }
  57.09% { transform: scale(1); }
  57.71% { transform: scale(1); }
  58.14% { transform: scale(1.13); }
  58.74% { transform: scale(1); }
  59.17% { transform: scale(1.07); }
  59.94% { transform: scale(1); }
  60.57% { transform: scale(1); }
  61.00% { transform: scale(1.13); }
  61.60% { transform: scale(1); }
  62.03% { transform: scale(1.07); }
  62.80% { transform: scale(1); }
  63.43% { transform: scale(1); }
  63.86% { transform: scale(1.13); }
  64.46% { transform: scale(1); }
  64.89% { transform: scale(1.07); }
  65.66% { transform: scale(1); }
  100% { transform: scale(1); }
}
.bouclier {
  fill: rgba(167, 139, 250, 0.18);
  stroke: #ede9fe;
  stroke-width: 2.5;
  opacity: 0;
  filter: drop-shadow(0 0 5px #a78bfa) drop-shadow(0 0 14px #7c3aed);
  transform-box: fill-box;
  transform-origin: center;
}
.rebond { opacity: 0; filter: drop-shadow(0 0 2px #c7d2fe) drop-shadow(0 0 6px #818cf8); }
.rebond polyline { fill: none; stroke: #f8fafc; stroke-width: 2.2; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.rebond .branche { stroke-width: 1.6; }
.pavage.ambiance-0h05-active .bouclier-1,
.pavage.ambiance-0h05-active .rebond-1 { animation: rebond-1 35s ease-out infinite; }
.pavage.ambiance-0h05-active .bouclier-2,
.pavage.ambiance-0h05-active .rebond-2 { animation: rebond-2 35s ease-out infinite; }
@keyframes rebond-1 {
  0%, 29.06% { opacity: 0; transform: scale(0.85); }
  29.17% { opacity: 1; transform: scale(1); }
  30.14%, 100% { opacity: 0; transform: scale(1.15); }
}
@keyframes rebond-2 {
  0%, 31.06% { opacity: 0; transform: scale(0.85); }
  31.17% { opacity: 1; transform: scale(1); }
  32.14%, 100% { opacity: 0; transform: scale(1.15); }
}

/* Horloge des boucles : son animation démarre à 32 s (retour du noir) puis se répète toutes
   les 35 s ; pavage.js compte ces passages, ce qui reste calé sur les animations */
.tic-boucle { position: absolute; width: 1px; height: 1px; }
.pavage.ambiance-0h05-active .tic-boucle { animation: tic-boucle 35s linear 32s infinite; }
@keyframes tic-boucle { from { opacity: 0; } to { opacity: 0.01; } }

/* l'or comble les fêlures par vagues, la principale d'abord (12,6 s à 20,8 s) */
@keyframes or-1 { 0%, 36.00% { stroke-dashoffset: 1; } 43.43%, 100% { stroke-dashoffset: 0; } }
@keyframes or-2 { 0%, 39.71% { stroke-dashoffset: 1; } 47.43%, 100% { stroke-dashoffset: 0; } }
@keyframes or-3 { 0%, 43.71% { stroke-dashoffset: 1; } 51.43%, 100% { stroke-dashoffset: 0; } }
@keyframes or-4 { 0%, 47.71% { stroke-dashoffset: 1; } 55.43%, 100% { stroke-dashoffset: 0; } }
@keyframes or-5 { 0%, 51.71% { stroke-dashoffset: 1; } 59.43%, 100% { stroke-dashoffset: 0; } }
/* une fois toutes les fêlures comblées (20,8 s), la carapace d'or éclate (21 s)
   et laisse apparaître le cœur entier */
.feles, .feles-or { transform-box: view-box; transform-origin: 12px 11.5px; }
@keyframes feles-disparaissent {
  0%, 59.43%   { opacity: 1; transform: scale(1);    filter: none; }
  60.00%       { opacity: 1; transform: scale(1.03); filter: brightness(1.8); }
  61.00%      { opacity: 0; transform: scale(1.22); filter: brightness(2.2) blur(0.3px); }
  100%            { opacity: 0; transform: scale(1.22); }
}
.onde-or {
  fill: none;
  stroke: #fde68a;
  stroke-width: 0.5;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}
.eclat-or {
  fill: #f5c542;
  opacity: 0;
  filter: drop-shadow(0 0 0.5px #fde68a);
}
.pavage.ambiance-0h05-active .onde-or  { animation: onde-or 35s ease-out infinite; }
.pavage.ambiance-0h05-active .eclat-or { animation: eclat-or 35s ease-out infinite; }
@keyframes onde-or {             /* onde de choc dorée */
  0%, 59.86%  { opacity: 0; transform: scale(0.4); }
  60.14%      { opacity: 1; transform: scale(0.8); }
  62.00%       { opacity: 0; transform: scale(3.6); }
  100%            { opacity: 0; transform: scale(3.6); }
}
@keyframes eclat-or {            /* éclats d'or projetés vers l'extérieur */
  0%, 59.86%  { opacity: 0; translate: 0 0; rotate: 0deg; scale: 0.5; }
  60.14%      { opacity: 1; translate: 0 0; rotate: 0deg; scale: 1; }
  63.14%       { opacity: 0; translate: var(--tx) var(--ty); rotate: var(--r); scale: 0.4; }
  100%            { opacity: 0; translate: var(--tx) var(--ty); scale: 0.4; }
}


/* Progression des boucles (data-boucle donné par pavage.js au retour du noir) :
   boucle 1 : noir 100 %, 3 éclairs ; boucle 2 : noir 80 %, 1 éclair et un peu de pluie ;
   boucle 3 : noir 60 %, plus d'éclair, pluie légère ;
   ensuite (« fin ») : le noir ne revient plus, rouge à 100 %, le cœur violet bat sans fin. */
.pavage.ambiance-0h05-active .amb-0h05.epreuves-ombre,
.pavage.ambiance-0h05-active .amb-0h05.epreuves-gris,
.pavage.ambiance-0h05-active .amb-0h05.epreuves-flash { opacity: var(--noir, 1); }
.pavage[data-boucle="2"] { --noir: 0.8; }
.pavage[data-boucle="3"] { --noir: 0.6; }
.pavage[data-boucle="2"] .e2, .pavage[data-boucle="2"] .e3,              /* boucle 2 : 1 éclair */
.pavage[data-boucle="3"] .eclair,                                        /* boucle 3 : aucun */
.pavage[data-boucle="3"] .epreuves-flash > div { display: none; }
/* boucle 3 : les deux éclairs qui frappent le cœur ne viennent plus */
.pavage[data-boucle="3"] .foudre, .pavage[data-boucle="3"] .impact,
.pavage[data-boucle="3"] .bouclier, .pavage[data-boucle="3"] .rebond { visibility: hidden; }

/* Pluie dans la partie droite (boucles 2 et 3), qui suit l'apparition du noir */
.pavage.ambiance-0h05-active:not([data-boucle="2"]):not([data-boucle="3"]) .amb-0h05.epreuves-pluie { visibility: hidden; }
.pavage.ambiance-0h05-active .amb-0h05.epreuves-pluie { opacity: 0.7; animation: epreuves-reculent 35s ease-in-out infinite; }
.pavage[data-boucle="3"] .goutte:not(.legere) { display: none; }    /* pluie plus légère */
.goutte {
  position: absolute;
  top: -12%;
  width: 1px;
  height: var(--h);
  background: linear-gradient(to bottom, transparent, rgba(199, 210, 254, 0.75));
  rotate: 12deg;
  animation: goutte var(--du) linear var(--dl) infinite;
}
@keyframes goutte {
  from { translate: 0 0; }
  to   { translate: -2.5cqw 33cqw; }   /* toute la hauteur du pavage (205/768 de sa largeur) */
}

/* Cœur violet calme (boucle 3) : intact, sans éclair ni recul ; s'illumine à 13,2 s puis bat 10 fois */
.groupe-calme, .groupe-fin { visibility: hidden; }
.pavage[data-boucle="3"] .groupe-entier,
.pavage[data-boucle="3"] .groupe-brise { visibility: hidden; }
.pavage[data-boucle="3"] .groupe-calme { visibility: visible; }
.coeur-calme, .coeur-fin { transform-box: fill-box; transform-origin: 50% 55%; }
.coeur-calme { opacity: 0; }
.pavage.ambiance-0h05-active .coeur-calme { animation: coeur-calme 35s ease-in-out infinite, coeur-bat-calme 35s linear infinite; }
@keyframes coeur-calme {
  0%, 26.57%       { opacity: 1; filter: drop-shadow(0 0 2px #c4b5fd) drop-shadow(0 0 6px #7c3aed); }   /* déjà là depuis la boucle précédente */
  28.29%, 36.00% { opacity: 1; filter: drop-shadow(0 0 1px #2e1065); }
  37.71%          { opacity: 1; filter: drop-shadow(0 0 3px #ede9fe) drop-shadow(0 0 8px #8b5cf6); }
  41.14%, 92.00% { opacity: 1; filter: drop-shadow(0 0 2px #c4b5fd) drop-shadow(0 0 6px #7c3aed); }
  94.86%, 100%     { opacity: 1; filter: drop-shadow(0 0 2px #c4b5fd) drop-shadow(0 0 6px #7c3aed); }   /* reste visible entre les boucles */
}
@keyframes coeur-bat-calme {
  0%, 37.69% { transform: scale(1); }
  37.71% { transform: scale(1); }
  38.14% { transform: scale(1.13); }
  38.74% { transform: scale(1); }
  39.17% { transform: scale(1.07); }
  39.94% { transform: scale(1); }
  40.57% { transform: scale(1); }
  41.00% { transform: scale(1.13); }
  41.60% { transform: scale(1); }
  42.03% { transform: scale(1.07); }
  42.80% { transform: scale(1); }
  43.43% { transform: scale(1); }
  43.86% { transform: scale(1.13); }
  44.46% { transform: scale(1); }
  44.89% { transform: scale(1.07); }
  45.66% { transform: scale(1); }
  46.29% { transform: scale(1); }
  46.71% { transform: scale(1.13); }
  47.31% { transform: scale(1); }
  47.74% { transform: scale(1.07); }
  48.51% { transform: scale(1); }
  49.14% { transform: scale(1); }
  49.57% { transform: scale(1.13); }
  50.17% { transform: scale(1); }
  50.60% { transform: scale(1.07); }
  51.37% { transform: scale(1); }
  52.00% { transform: scale(1); }
  52.43% { transform: scale(1.13); }
  53.03% { transform: scale(1); }
  53.46% { transform: scale(1.07); }
  54.23% { transform: scale(1); }
  54.86% { transform: scale(1); }
  55.29% { transform: scale(1.13); }
  55.89% { transform: scale(1); }
  56.31% { transform: scale(1.07); }
  57.09% { transform: scale(1); }
  57.71% { transform: scale(1); }
  58.14% { transform: scale(1.13); }
  58.74% { transform: scale(1); }
  59.17% { transform: scale(1.07); }
  59.94% { transform: scale(1); }
  60.57% { transform: scale(1); }
  61.00% { transform: scale(1.13); }
  61.60% { transform: scale(1); }
  62.03% { transform: scale(1.07); }
  62.80% { transform: scale(1); }
  63.43% { transform: scale(1); }
  63.86% { transform: scale(1.13); }
  64.46% { transform: scale(1); }
  64.89% { transform: scale(1.07); }
  65.66% { transform: scale(1); }
  100% { transform: scale(1); }
}

/* Fin : le noir ne revient plus, le rouge reste à 100 %, le cœur violet bat sans fin */
.pavage.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.amour-teinte-totale { animation: none; filter: opacity(1); }
.pavage.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.epreuves-ombre,
.pavage.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.epreuves-gris,
.pavage.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.epreuves-flash,
.pavage.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.epreuves-eclairs,
.pavage.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.epreuves-pluie,
.pavage[data-boucle="fin"] .foudre,
.pavage[data-boucle="fin"] .impact,
.pavage[data-boucle="fin"] .bouclier,
.pavage[data-boucle="fin"] .rebond,
.pavage[data-boucle="fin"] .groupe-brise,
.pavage[data-boucle="fin"] .groupe-entier,
.pavage[data-boucle="fin"] .groupe-calme { visibility: hidden; }
.pavage[data-boucle="fin"] .groupe-fin { visibility: visible; }
.coeur-fin { filter: drop-shadow(0 0 2px #c4b5fd) drop-shadow(0 0 6px #7c3aed); }
.pavage.ambiance-0h05-active .coeur-fin { animation: coeur-bat-fin 1s linear infinite; }
@keyframes coeur-bat-fin {       /* « boum-boum » toutes les secondes, sans fin */
  0%   { transform: scale(1); }
  15%  { transform: scale(1.13); }
  36%  { transform: scale(1); }
  51%  { transform: scale(1.07); }
  78%, 100% { transform: scale(1); }
}

/* Mots d'amour qui apparaissent puis disparaissent sur les dalles de la partie rouge.
   pavage.js choisit à chaque fois une dalle libre au hasard et lui applique
   la matrice calculée sur sa forme, pour suivre sa perspective. */
.mot {
  position: absolute;
  translate: -50% -50%;
  white-space: nowrap;
  font: 400 1.9cqw/1 "Segoe Script", "Snell Roundhand", "Brush Script MT", "Lucida Handwriting", cursive;
  color: #ffe4e6;
  text-shadow: 0 0 4px #fb7185, 0 0 10px #f43f5e, 0 0 18px rgba(244, 63, 94, 0.6);
  opacity: 0;
  animation: mot-apparait 4.4s ease-in-out forwards;
}
@keyframes mot-apparait {        /* fondu d'apparition, quelques secondes, puis disparition */
  0%   { opacity: 0; filter: blur(3px); scale: 0.92; }
  25%  { opacity: 1; filter: blur(0);   scale: 1; }
  70%  { opacity: 1; filter: blur(0);   scale: 1; }
  100% { opacity: 0; filter: blur(3px); scale: 1.04; }
}
@media (prefers-reduced-motion: reduce) {
  .mot { animation: none; opacity: 0.85; }
}

/* =========================================================
   AMBIANCE 2h38 — au survol du lien 2h38 :
   une famille soudée, deux parents et leur fille, tout en douceur
   ========================================================= */
.pavage.ambiance-2h38-active .amb-2h38 {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.9s ease, visibility 0s;
}
/* Arrêt : toute l'ambiance s'efface d'un bloc, figée dans son état du moment (voir pavage.js, data-sortie-figee) */
.pavage.ambiance-2h38-active.sortie-2h38 .amb-2h38 {
  opacity: 0;
  transition: opacity 0.6s ease, visibility 0s;
}

/* Le verre prend une teinte bleu ciel légère */
.douceur-teinte {
  background: radial-gradient(75% 110% at 50% 50%, #bae6fd 0%, #93c5fd 55%, #a5b4fc 100%);
  mix-blend-mode: color;
}
/* Lumière bleu clair qui respire lentement */
.douceur-lueur { mix-blend-mode: screen; }
.douceur-lueur > div {
  background:
    radial-gradient(40% 75% at 50% 50%, rgba(224, 242, 254, 0.55), transparent 70%),
    radial-gradient(70% 100% at 50% 50%, rgba(186, 230, 253, 0.3), transparent 75%);
  animation: douceur-respire 5s ease-in-out infinite;
}
@keyframes douceur-respire {
  0%, 100% { opacity: 0.75; }
  50%      { opacity: 1; }
}

/* Petites lumières blanches flottantes */
.poussiere {
  position: absolute;
  width: var(--s);
  height: var(--s);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 6px 2px rgba(255, 255, 255, 0.6);
  opacity: 0;
  animation: poussiere-flotte var(--du) ease-in-out var(--dl) infinite;
}
@keyframes poussiere-flotte {
  0%   { opacity: 0;   transform: translate(0, 0); }
  25%  { opacity: 0.9; }
  75%  { opacity: 0.6; }
  100% { opacity: 0;   transform: translate(var(--dx), -40px); }
}

/* Étoiles filantes qui traversent le ciel de temps en temps :
   chacune passe en moins d'une seconde, puis disparaît jusqu'à son prochain passage */
.filante {
  position: absolute;
  width: 13cqw;
  height: 2px;
  border-radius: 1px;
  background: linear-gradient(90deg, #fff 0%, rgba(255, 255, 255, 0.6) 25%, transparent 100%);
  transform-origin: 0 50%;
  opacity: 0;
  animation: filante var(--p) ease-out var(--dl) infinite;
}
.filante::before {               /* tête lumineuse */
  content: "";
  position: absolute;
  left: -2px;
  top: 50%;
  width: 4px;
  height: 4px;
  margin-top: -2px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 6px 2px #fff, 0 0 14px 4px rgba(186, 230, 253, 0.8);
}
@keyframes filante {             /* traversée rapide vers le bas à gauche */
  0%   { opacity: 0; transform: rotate(var(--a)) translateX(0); }
  1%   { opacity: 1; }
  7%   { opacity: 0.9; }
  10%  { opacity: 0; transform: rotate(var(--a)) translateX(-34cqw); }
  100% { opacity: 0; transform: rotate(var(--a)) translateX(-34cqw); }
}

/* La famille : trois cubes de lettres L, A, M, posés le long de l'arc-en-ciel.
   Chaque cube (et le halo) est placé par ses coordonnées dans le dessin 768×205 (--x, --y),
   converties en unités du pavage (1 unité = 100cqw / 768). */
.famille .famille-groupe {      /* (sélecteur précis : prime sur « .amb > div ») */
  position: absolute;
  inset: 0;
  perspective: 600px;
}
.famille-groupe > * {
  position: absolute;
  left: calc(var(--x) * 100cqw / 768);
  top: calc(var(--y) * 100cqw / 768);
}
.famille-halo {                  /* halo blanc commun qui les réunit, allongé le long de l'arc */
  width: 34cqw;
  height: 13cqw;
  margin: -6.5cqw 0 0 -17cqw;
  rotate: 45deg;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.12) 60%, transparent);
  animation: douceur-respire 5s ease-in-out infinite;
}
.bloc {                          /* cube en 3D : face avant + dessus + côté droit */
  --s: 4.8cqw;
  position: absolute;
  width: var(--s);
  height: var(--s);
  margin: calc(var(--s) / -2) 0 0 calc(var(--s) / -2);   /* centré sur son point de l'arc */
  transform-style: preserve-3d;
  transform: rotateX(-16deg) rotateY(-24deg);
  animation: famille-berce 6s ease-in-out infinite;
}
.bloc .face {
  position: absolute;
  inset: 0;
  border-radius: calc(var(--s) * 0.104);
  border: 1px solid rgba(255, 255, 255, 0.5);
}
.bloc .avant, .bloc .arriere {   /* la lettre est sur les deux faces : visible même quand le cube tourne */
  display: grid;
  place-items: center;
  transform: translateZ(calc(var(--s) / 2));
  background: linear-gradient(145deg, var(--clair), var(--base));
  font: 800 calc(var(--s) * 0.6875)/1 "Arial Rounded MT Bold", "Nunito", system-ui, -apple-system, "Segoe UI", sans-serif;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  box-shadow: 0 0 calc(var(--s) * 0.33) calc(var(--s) * 0.05) var(--glow);   /* lueur (un filtre aplatirait le cube) */
}
.bloc .haut { transform: rotateX(90deg) translateZ(calc(var(--s) / 2)); background: var(--clair); }
.bloc .cote { transform: rotateY(90deg) translateZ(calc(var(--s) / 2)); background: var(--fonce); }
.bloc .arriere { transform: rotateY(180deg) translateZ(calc(var(--s) / 2)); }
.bloc .gauche  { transform: rotateY(-90deg) translateZ(calc(var(--s) / 2)); background: var(--fonce); }
.bloc-l { --base: #ec4899; --clair: #f9a8d4; --fonce: #be185d; --glow: rgba(249, 168, 212, 0.8); }                         /* rose */
.bloc-a { --base: #8b5cf6; --clair: #c4b5fd; --fonce: #6d28d9; --glow: rgba(196, 181, 253, 0.8); animation-delay: -0.4s; } /* violet */
.bloc-m { --base: #f472b6; --clair: #fbcfe8; --fonce: #db2777; --glow: rgba(251, 207, 232, 0.85); animation-delay: -0.8s; } /* rose (enfant) */
@keyframes famille-berce {       /* bercement lent, presque à l'unisson */
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -4px; }
}


/* Arc-en-ciel féérique en perspective : il arrive de hors champ, en haut à gauche,
   et redescend se poser sur les cubes de lettres, comme le trésor à son pied */
.arc-en-ciel svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.arc-en-ciel { mix-blend-mode: screen; }
.arc-halo {                      /* halo lumineux qui respire autour de l'arc */
  filter: blur(9px);
  opacity: 0.7;
  animation: arc-respire 4s ease-in-out infinite;
}
.arc-bandes { filter: blur(0.8px); }
.arc-bandes { fill-opacity: 0.62; }   /* dessin partagé avec le halo (élément <use>) */
@keyframes arc-respire {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 0.95; }
}
.etincelle {                     /* étoiles qui scintillent le long de l'arc */
  fill: #fff;
  filter: drop-shadow(0 0 2px #fff);
  opacity: 0;
  animation: etincelle var(--du) ease-in-out var(--dl) infinite;
}
@keyframes etincelle {
  0%, 100% { opacity: 0;   transform: scale(0.3) rotate(0deg); }
  50%      { opacity: 1;   transform: scale(1)   rotate(45deg); }
}

/* Quatre nuages bien dessinés qui passent lentement sur le haut du pavage */
.nuages svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.nuage {
  filter: drop-shadow(0 3px 3px rgba(30, 58, 138, 0.35));
  opacity: 0.95;
  animation: nuage-passe 36s ease-in-out infinite alternate;
}
.n2, .n4 { animation-duration: 44s; animation-direction: alternate-reverse; }
.n3 { animation-delay: -14s; }
@keyframes nuage-passe {
  from { transform: translateX(-40px); }
  to   { transform: translateX(40px); }
}


/* Ouverture de l'ambiance 2h38, en étapes (au clic) :
   0 s     : seules les dalles passent au bleu (teinte + lumière)
   1,2 s   : les lueurs flottantes se dévoilent du bas de l'image vers le haut
   2,4 s   : l'arc-en-ciel se déploie le long de sa courbe, flou au départ puis de plus en plus net
   3,6 s   : les nuages tombent du ciel (puis les étoiles filantes)
   5 s     : les cubes L et A apparaissent en fondu, tournent et fusionnent ;
             à 7,7 s, en fin de rotation, ils deviennent le cube M (rose) : seul M reste,
             dans un éclat de lumière, avec de petites étincelles de temps en temps ;
             à 8,7 s, un petit L et un petit A ailés sortent de derrière M et montent de part et d'autre.
   À la sortie, tout s'efface ensemble, sans délai. */
.pavage.ambiance-2h38-active .douceur-poussiere {
  transition: opacity 0.2s ease 1.2s, visibility 0s;
  -webkit-mask: linear-gradient(to top, #000 40%, transparent 60%) 0 0 / 100% 250% no-repeat;
          mask: linear-gradient(to top, #000 40%, transparent 60%) 0 0 / 100% 250% no-repeat;
  animation: poussiere-monte 2.4s ease-out 1.2s both;
}
@keyframes poussiere-monte {     /* le masque glisse : le bas de l'image se dévoile en premier */
  from { -webkit-mask-position: 0 0;    mask-position: 0 0; }
  to   { -webkit-mask-position: 0 100%; mask-position: 0 100%; }
}
.pavage.ambiance-2h38-active .arc-en-ciel { transition: opacity 0.3s ease 2.4s, visibility 0s; }
.arc-trace { stroke-dasharray: 1 1; stroke-dashoffset: 0; }      /* tracé du masque de déploiement */
.pavage.ambiance-2h38-active .arc-trace { animation: arc-deploie 1.9s cubic-bezier(.45, 0, .25, 1) 2.4s both; }
@keyframes arc-deploie {
  from { stroke-dashoffset: 1; }
  to   { stroke-dashoffset: 0; }
}
.pavage.ambiance-2h38-active .arc-bandes { animation: arc-depoli 2.4s ease-out 2.4s both; }
@keyframes arc-depoli {          /* verre dépoli au départ, puis les couleurs deviennent nettes */
  from { filter: blur(7px);   fill-opacity: 0.3; }
  to   { filter: blur(0.8px); fill-opacity: 0.62; }
}
.pavage.ambiance-2h38-active .nuages { transition: opacity 0.2s ease 3.6s, visibility 0s; }
.pavage.ambiance-2h38-active .n1 { animation: nuage-tombe 1.4s 3.6s both,  nuage-passe 36s ease-in-out infinite alternate; }
.pavage.ambiance-2h38-active .n4 { animation: nuage-tombe 1.4s 3.8s both,  nuage-passe 44s ease-in-out infinite alternate-reverse; }
.pavage.ambiance-2h38-active .n2 { animation: nuage-tombe 1.4s 4.0s both,  nuage-passe 44s ease-in-out infinite alternate-reverse; }
.pavage.ambiance-2h38-active .n3 { animation: nuage-tombe 1.4s 4.15s both, nuage-passe 36s ease-in-out -14s infinite alternate; }
@keyframes nuage-tombe {         /* chute depuis le haut, léger rebond à l'arrivée */
  0%   { opacity: 0; translate: 0 -120px; animation-timing-function: cubic-bezier(.55, 0, .9, .45); }
  15%  { opacity: 1; }
  62%  { translate: 0 6px;  animation-timing-function: ease-out; }
  80%  { translate: 0 -2px; animation-timing-function: ease-in-out; }
  100% { opacity: 1; translate: 0 0; }
}
.pavage.ambiance-2h38-active .etoiles-filantes  { transition-delay: 4.4s, 0s; }
.pavage.ambiance-2h38-active .famille-halo {
  animation: fondu 1s ease-out 7.9s both, halo-respire 5s ease-in-out 8.9s infinite;
}
.pavage.ambiance-2h38-active .famille-groupe > .bloc-l,
.pavage.ambiance-2h38-active .famille-groupe > .bloc-a { animation: fusion 2.9s ease-in-out 5s both; }
.pavage.ambiance-2h38-active .bloc-m { animation: naissance 1.1s linear 7.65s both, famille-berce-2 6s ease-in-out 9s infinite; }
/* (copies sous un autre nom : une animation déjà en cours sous le même nom
   ne redémarrerait pas au clic, et son délai compterait depuis le chargement de la page) */
@keyframes halo-respire    { 0%, 100% { opacity: 1; } 50% { opacity: 0.75; } }
@keyframes famille-berce-2 { 0%, 100% { translate: 0 0; } 50% { translate: 0 -4px; } }
/* Le fondu des cubes passe par --o, appliqué à chaque face : une opacité sur le cube lui-même
   l'aplatirait (fin de la 3D) et ferait passer une face arrière devant la lettre. */
@property --o { syntax: '<number>'; inherits: true; initial-value: 1; }
.bloc .face { opacity: var(--o); backface-visibility: hidden; }
@keyframes fondu-cube {
  from { --o: 0; }
  to   { --o: 1; }
}
@keyframes fondu {
  from { opacity: 0; }
  to   { opacity: 1; }
}
/* L et A (2,9 s) : apparition en fondu (0,5 s), rapprochement en tournant (1,2 s), fusion tenue 1 s en finissant de tourner ;
   à la fin de la rotation ils s'effacent et deviennent le cube M (rose) : seul M reste.
   Ils se rejoignent à mi-chemin l'un de l'autre, sur l'arc (vecteur --mx, --my propre à chaque cube). */
@keyframes fusion {
  0%    { --o: 0;             translate: 0 0; rotate: y 0deg; }
  17.2% { --o: 1; scale: 1;   translate: 0 0; rotate: y 0deg;    animation-timing-function: ease-in; }
  58.6% { scale: 0.85; translate: calc(var(--mx) * 100cqw / 768) calc(var(--my) * 100cqw / 768); rotate: y 540deg;  animation-timing-function: ease-out; }
  93.1% { --o: 1; scale: 0.85; translate: calc(var(--mx) * 100cqw / 768) calc(var(--my) * 100cqw / 768); rotate: y 1080deg; }
  100%  { --o: 0; scale: 0.6;  translate: calc(var(--mx) * 100cqw / 768) calc(var(--my) * 100cqw / 768); rotate: y 1080deg; }
}
/* M naît de la fusion, dans un éclat de lumière, à l'endroit même où L et A se sont rejoints :
   une lueur rose et blanche gonfle pendant les derniers tours de L et A, un anneau de lumière s'élargit,
   des grains de lumière s'envolent, et M sort de l'éclat en pivotant, avec un petit rebond. */
@keyframes naissance {
  0%   { --o: 0; scale: 0.15; rotate: y -220deg; animation-timing-function: cubic-bezier(.2, .7, .3, 1); }
  15%  { --o: 1; }
  62%  { scale: 1.14; rotate: y 0deg; animation-timing-function: ease-in-out; }
  80%  { scale: 0.96; }
  100% { --o: 1; scale: 1; rotate: y 0deg; }
}
.famille-halo { z-index: 0; }
.ange         { z-index: 1; }        /* les petits cubes ailés partent de derrière M */
.bloc-m       { z-index: 2; }
.eclat        { z-index: 3; }
.m-etincelle  { z-index: 4; }
.eclat > span { position: absolute; left: 0; top: 0; border-radius: 50%; opacity: 0; }
.eclat-lueur {
  width: 16cqw; height: 16cqw; margin: -8cqw 0 0 -8cqw;
  background: radial-gradient(closest-side, #fff 0%, rgba(255, 250, 253, 0.95) 25%, rgba(252, 211, 232, 0.65) 50%, rgba(249, 168, 212, 0.25) 72%, transparent);
}
.eclat-anneau {
  width: 7cqw; height: 7cqw; margin: -3.5cqw 0 0 -3.5cqw;
  border: 0.25cqw solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 0 0.8cqw rgba(251, 207, 232, 0.9), inset 0 0 0.8cqw rgba(251, 207, 232, 0.9);
}
.eclat-grain {
  width: 0.55cqw; height: 0.55cqw; margin: -0.275cqw 0 0 -0.275cqw;
  background: #fff;
  box-shadow: 0 0 0.5cqw 0.15cqw #fbcfe8;
}
.pavage.ambiance-2h38-active .eclat-lueur  { animation: eclat-lueur 1.6s ease-out 7.25s both; }
.pavage.ambiance-2h38-active .eclat-anneau { animation: eclat-anneau 1s ease-out 7.7s both; }
.pavage.ambiance-2h38-active .eclat-grain  { animation: eclat-grain 1.1s cubic-bezier(.15, .7, .3, 1) 7.7s both; }
@keyframes eclat-lueur {         /* gonfle pendant les derniers tours, culmine à la naissance, puis s'efface */
  0%   { opacity: 0;    scale: 0.1; }
  28%  { opacity: 1;    scale: 0.85; }
  45%  { opacity: 0.85; scale: 0.95; }
  100% { opacity: 0;    scale: 1; }
}
@keyframes eclat-anneau {        /* (0 % invisible : avec « both », l'état de départ s'affiche pendant le délai) */
  0%   { opacity: 0; scale: 0.2; }
  1%   { opacity: 1; scale: 0.2; }
  100% { opacity: 0; scale: 2.2; }
}
@keyframes eclat-grain {         /* chaque grain part dans sa direction (--a) et s'éteint */
  0%   { opacity: 0; transform: rotate(var(--a)) translateX(0)       scale(1); }
  1%   { opacity: 1; transform: rotate(var(--a)) translateX(0)       scale(1); }
  70%  { opacity: 0.9; }
  100% { opacity: 0; transform: rotate(var(--a)) translateX(var(--d)) scale(0.3); }
}

/* Étincelles sur le cube M : discrètes mais vives, comme un éclat de lumière sur une arête.
   Un point blanc très lumineux et deux rayons fins en croix, qui jaillissent puis s'éteignent en un instant. */
.m-etincelle {
  width: 2.4cqw;
  height: 2.4cqw;
  margin: -1.2cqw 0 0 -1.2cqw;
  background: radial-gradient(circle, #fff 0 5%, rgba(255, 245, 250, 0.9) 9%, rgba(251, 207, 232, 0.35) 18%, transparent 30%);
  mix-blend-mode: screen;
  opacity: 0;
  scale: 0;
}
.m-etincelle::before, .m-etincelle::after {   /* les deux rayons */
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 100%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.95) 45%, #fff 50%, rgba(255, 255, 255, 0.95) 55%, transparent);
  box-shadow: 0 0 2px rgba(255, 255, 255, 0.8);
}
.m-etincelle::after { rotate: 90deg; scale: 0.7 1; }   /* rayon vertical un peu plus court */
.pavage.ambiance-2h38-active .m-etincelle { animation: m-scintille var(--p) ease-out var(--dl) infinite; }
@keyframes m-scintille {        /* éclat d'environ 0,4 s, puis rien jusqu'au suivant */
  0%   { opacity: 0; scale: 0;    rotate: -10deg; animation-timing-function: cubic-bezier(.2, 1.6, .5, 1); }
  3%   { opacity: 1; scale: 1;    rotate: 0deg; }
  5%   { opacity: 1; scale: 0.75; rotate: 12deg; animation-timing-function: ease-in; }
  8%   { opacity: 0; scale: 0;    rotate: 25deg; }
  100% { opacity: 0; scale: 0; }
}

/* Les petits L et A ailés : des cubes miniatures, un peu au-dessus de M, L à gauche et A à droite,
   qui flotte doucement en battant de ses petites ailes */
.ange {
  perspective: 300px;
  opacity: 0;
}
.ange .bloc { --s: 1.59cqw; animation: none; }   /* 25 % de M, agrandi deux fois de 15 % */
.aile {
  position: absolute;
  top: -1.51cqw;                  /* bas de l'aile toujours attaché au haut du cube */
  width: 1.785cqw;                /* ailes réduites de 15 % */
  height: 1.36cqw;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 30'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%23ffffff'/%3E%3Cstop offset='1' stop-color='%23fbcfe8'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg%3E%3Cpath d='M2 21 C6 9 18 2 38 2 C34 6 33 8 36 10 C30 12 29 14 32 16 C26 18 24 19 26 22 C18 25 9 25 2 21 Z' fill='url%28%23g%29' stroke='%23ec4899' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='M8 18 C16 12 24 9 34 6 M10 21 C17 17 23 15 30 13 M12 23 C17 21 21 20 24 19' fill='none' stroke='%23f472b6' stroke-width='1.2' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
  filter: drop-shadow(0 0 1.5px #fff) drop-shadow(0 0 3px rgba(255, 255, 255, 0.8));
}
.aile-d { left: 0.2cqw;  transform-origin: 0 75%;    --sens: 1; }
.aile-g { right: 0.2cqw; transform-origin: 100% 75%; --sens: -1;   /* même aile, dessinée en miroir */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 30'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%23ffffff'/%3E%3Cstop offset='1' stop-color='%23fbcfe8'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg transform='translate%2840 0%29 scale%28-1 1%29'%3E%3Cpath d='M2 21 C6 9 18 2 38 2 C34 6 33 8 36 10 C30 12 29 14 32 16 C26 18 24 19 26 22 C18 25 9 25 2 21 Z' fill='url%28%23g%29' stroke='%23ec4899' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='M8 18 C16 12 24 9 34 6 M10 21 C17 17 23 15 30 13 M12 23 C17 21 21 20 24 19' fill='none' stroke='%23f472b6' stroke-width='1.2' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E");
}
.pavage.ambiance-2h38-active .ange {
  animation: ange-sort 1.4s cubic-bezier(.3, .1, .2, 1) 8.7s both, ange-flotte 3.2s ease-in-out 10.1s infinite;
}
.pavage.ambiance-2h38-active .aile { animation: aile-bat 0.45s ease-in-out infinite alternate; }
@keyframes ange-sort {           /* part du centre de M (caché derrière lui, vecteur --rx, --ry) et monte à sa place */
  0%   { opacity: 0; scale: 0.6; translate: calc(var(--rx) * 100cqw / 768) calc(var(--ry) * 100cqw / 768); }
  12%  { opacity: 1; }
  100% { opacity: 1; scale: 1;   translate: 0 0; }
}
@keyframes ange-flotte {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -0.5cqw; }
}
@keyframes aile-bat {           /* battement : la pointe de l'aile monte et descend */
  from { rotate: calc(var(--sens) * 18deg); }
  to   { rotate: calc(var(--sens) * -22deg); }
}

/* Mouvement réduit : ambiance fixe */
@media (prefers-reduced-motion: reduce) {
  .pavage.ambiance-2h38-active .amb-2h38 { transition: none; }
  .douceur-lueur > div, .poussiere, .famille-halo, .bloc, .nuage, .arc-halo { animation: none; }
  .pavage.ambiance-2h38-active .famille-halo, .pavage.ambiance-2h38-active .bloc,
  .pavage.ambiance-2h38-active .douceur-poussiere, .pavage.ambiance-2h38-active .arc-trace,
  .pavage.ambiance-2h38-active .arc-bandes, .pavage.ambiance-2h38-active .nuage,
  .pavage.ambiance-2h38-active .m-etincelle { animation: none; }
  .pavage.ambiance-2h38-active .famille-groupe > .bloc-l, .pavage.ambiance-2h38-active .famille-groupe > .bloc-a { display: none; }
  .pavage.ambiance-2h38-active .ange, .pavage.ambiance-2h38-active .aile { animation: none; opacity: 1; }
  .eclat { display: none; }
  .pavage.ambiance-2h38-active .douceur-poussiere { -webkit-mask: none; mask: none; }
  .pavage.ambiance-2h38-active .amb-2h38 { transition-delay: 0s; }
  .filante { display: none; }
  .etincelle { animation: none; opacity: 0.7; transform: none; }
  .poussiere { opacity: 0.6; }
}

/* =========================================================
   AMBIANCE 23h10 — au survol du lien 23h10 :
   une pluie de caractères violets (façon Matrix) défile dans chaque dalle.
   Le canevas est posé sur le verre, découpé à la forme exacte des dalles grâce au masque
   (tout sauf les joints de fond.webp) et ajouté en lumière (screen) pour garder le reflet du verre. */
.matrice {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  pointer-events: none;
  mix-blend-mode: screen;
  -webkit-mask: linear-gradient(#000 0 0), url(../image/pavage/fond.webp) 0 0 / 100% 100% no-repeat;
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0), url(../image/pavage/fond.webp) 0 0 / 100% 100% no-repeat;
          mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.6s ease;
}
.pavage.ambiance-23h10-active .matrice { opacity: 1; }
/* la lueur s'assombrit pour faire ressortir les caractères */
.pavage-lueur { transition: filter 0.6s ease; }
.pavage.ambiance-23h10-active .pavage-lueur { filter: blur(20px) brightness(0.3); }

/* =========================================================
   HORLOGE POSÉE DANS LA DALLE EN BAS À GAUCHE
   Son survol (souris), son focus (clavier) ou un toucher affiche le compteur de jours
   dans la légende sous le pavage.
   ========================================================= */
.horloge-dalle {
  position: absolute;
  z-index: 1;
  width: 3.64%;                    /* 30 % plus petite ; posée droite (sans la perspective de la dalle), dans le coin */
  cursor: pointer;
  outline: none;
  /* gravée en creux dans la dalle, comme le kanji : trait plus sombre que le verre,
     ombre sur le bord haut, reflet clair sur le bord bas */
  color: rgba(0, 0, 0, 0.9);       /* noir */
  filter: drop-shadow(0 1px 0 rgba(196, 181, 253, 0.35));
  transition: color 0.3s ease;
}
.horloge-dalle svg { display: block; width: 100%; height: auto; overflow: visible; }
/* traits épaissis pour une gravure aussi lisible que le kanji */
.horloge-dalle .anneau-ext { display: none; }
.horloge-dalle .cadran { fill: none; stroke-width: 11; }
.horloge-dalle .grad.minutes { display: none; }
.horloge-dalle .grad.heures { stroke-width: 16; stroke-dasharray: 2.6 27.4; stroke-dashoffset: 1.3; }
.horloge-dalle .repere-midi { display: none; }
.horloge-dalle .aiguille { stroke: currentColor; stroke-width: 7; stroke-linejoin: round; }
.horloge-dalle .pivot { fill: currentColor; stroke: none; }
.horloge-dalle:hover,
.horloge-dalle:focus-visible,
.horloge-dalle.actif { color: #000; }
.pavage.attente .horloge-dalle { opacity: 0; }
.pavage.monte .horloge-dalle { animation: pavage-fond 0.8s ease-out 1.2s both; }

/* =========================================================
   MISE EN PAGE SMARTPHONE (page index.php)
   ========================================================= */
@media (max-width: 820px) {
  .page-pavage div.centered,
  .page-pavage div.logo,
  .page-pavage div.layer { width: auto; }
  .page-pavage div.centered { padding: 0 6px; }
  .page-pavage div.logo { height: 22vh; }
  .page-pavage div.bottom { width: auto; }      /* ce bloc de 800 px élargissait la page */
  .page-pavage { overflow-x: hidden; }
  .page-pavage .pavage-legende { font-size: 13px; padding-left: 8px; }
  .page-pavage .mot { font-size: max(9px, 1.9cqw); }
}

/* Ambiance 0h05, à partir de la 3e boucle : les petits cœurs volent aussi dans la partie droite */
.coeur-droite { visibility: hidden; }
.pavage[data-boucle="3"] .coeur-droite,
.pavage[data-boucle="fin"] .coeur-droite { visibility: visible; }

/* =========================================================
   AMBIANCE 0h05, 2e BOUCLE : ORAGE ALÉATOIRE
   Les éclairs fixes et les deux éclairs qui frappaient le cœur à chaque fois sont retirés ;
   pavage.js fait tomber des éclairs à des moments et endroits aléatoires.
   Certains touchent le cœur : un bouclier violet s'allume et il reste intact.
   ========================================================= */
.pavage[data-boucle="2"] .e1,
.pavage[data-boucle="2"] .epreuves-flash > div { display: none; }
.pavage[data-boucle="2"] .foudre,
.pavage[data-boucle="2"] .impact,
.pavage[data-boucle="2"] .bouclier,
.pavage[data-boucle="2"] .rebond,
.pavage[data-boucle="2"] .groupe-entier { visibility: hidden; }
.pavage[data-boucle="2"] .groupe-calme { visibility: visible; }   /* cœur sans les réactions aux éclairs fixes */

.eclair-aleatoire {
  filter: drop-shadow(0 0 2px #c7d2fe) drop-shadow(0 0 7px #818cf8);
  animation: eclair-aleatoire 0.65s linear forwards;
}
.eclair-aleatoire polyline {
  fill: none;
  stroke: #f8fafc;
  stroke-width: 1.8;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.eclair-aleatoire .branche { stroke-width: 1; }
.eclair-aleatoire .etincelle-rebond { stroke: #ede9fe; stroke-width: 1.4; }
@keyframes eclair-aleatoire {
  0%   { opacity: 0; }
  6%   { opacity: 1; }
  16%  { opacity: 0.3; }
  26%  { opacity: 1; }
  45%  { opacity: 0.6; }
  100% { opacity: 0; }
}
.bouclier-aleatoire {
  fill: rgba(167, 139, 250, 0.18);
  stroke: #ede9fe;
  stroke-width: 2.5;
  opacity: 0;
  filter: drop-shadow(0 0 5px #a78bfa) drop-shadow(0 0 14px #7c3aed);
  transform-box: fill-box;
  transform-origin: center;
  pointer-events: none;
}
.bouclier-aleatoire.frappe { animation: bouclier-aleatoire 0.55s ease-out; }
@keyframes bouclier-aleatoire {
  0%   { opacity: 0; transform: scale(0.85); }
  12%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.15); }
}

/* =========================================================
   AMBIANCE 0h05 « paisible » (index.php : <div class="pavage" data-fin-paisible>)
   Dès que le cœur violet est réparé, l'état final commence : plus de noir, de pluie
   ni d'éclairs permanents ; le cœur bat doucement sans fin, et de temps en temps
   une petite averse passe, plus rarement un éclair rebondit sur le cœur (pavage.js).
   ========================================================= */
.pavage.ambiance-0h05-active[data-fin-paisible] .coeur-fin {
  animation: coeur-bat-doux 1.6s ease-in-out infinite;
}
@keyframes coeur-bat-doux {      /* battement lent et léger */
  0%, 100% { transform: scale(1); }
  14%      { transform: scale(1.05); }
  30%      { transform: scale(1.005); }
  44%      { transform: scale(1.03); }
  65%      { transform: scale(1); }
}
/* petites averses : la pluie de la partie droite apparaît puis s'efface en fondu */
.pavage[data-fin-paisible][data-boucle="fin"] .amb-0h05.epreuves-pluie {
  visibility: visible !important;
  animation: none !important;
  filter: none !important;
  opacity: 0 !important;
  transition: opacity 1.5s ease;
}
.pavage[data-fin-paisible][data-boucle="fin"].averse .amb-0h05.epreuves-pluie { opacity: 0.75 !important; }

/* =========================================================
   AMBIANCE 0h05 « paisible » : BRUME
   Au début : éclairs et pluie légère dans la partie noire.
   Après 4 s, pavage.js ajoute la classe "vent" et passe à l'état final :
   la partie noire se dissipe doucement comme une brume, puis le cœur violet apparaît.
   ========================================================= */
/* pluie légère pendant les éclairs du début */
.pavage[data-fin-paisible].ambiance-0h05-active[data-boucle="1"] .amb-0h05.epreuves-pluie { visibility: visible; }
.pavage[data-fin-paisible][data-boucle="1"] .goutte:not(.legere) { display: none; }

/* la partie noire se dissipe en brume */
.pavage.vent.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.epreuves-ombre,
.pavage.vent.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.epreuves-gris,
.pavage.vent.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.epreuves-flash,
.pavage.vent.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.epreuves-eclairs {
  visibility: visible !important;
  animation: brume-dissipe 3.2s ease-in-out forwards !important;
}
@keyframes brume-dissipe {        /* sur place, sans déplacement */
  0%   { filter: opacity(1) blur(0); }
  100% { filter: opacity(0) blur(8px); }
}
/* voile de brume pâle qui passe lentement pendant la dissipation */
.vent-rafales { visibility: hidden; }
.vent-rafales .rafale { display: none; }
.pavage.vent .vent-rafales { visibility: visible; }
.vent-rafales::before {
  content: "";
  position: absolute;
  inset: -10% -20%;
  background:
    radial-gradient(30% 45% at 72% 40%, rgba(255, 205, 215, 0.16), transparent 70%),
    radial-gradient(28% 40% at 86% 70%, rgba(237, 220, 254, 0.13), transparent 70%),
    radial-gradient(25% 35% at 62% 75%, rgba(255, 205, 215, 0.11), transparent 70%);
  filter: blur(12px);
  opacity: 0;
}
.pavage.vent .vent-rafales::before { animation: brume-voile 3.8s ease-in-out forwards; }
@keyframes brume-voile {          /* le voile monte doucement, puis s'efface */
  0%   { opacity: 0;   transform: translateX(0); }
  50%  { opacity: 1; }
  100% { opacity: 0;   transform: translateX(2%); }
}
/* le cœur violet apparaît doucement à travers la brume */
.pavage.vent .groupe-fin { animation: coeur-revele 2.6s ease-out 0.9s both; }
@keyframes coeur-revele {
  from { opacity: 0; filter: blur(8px); }
  to   { opacity: 1; filter: blur(0); }
}

/* petits éclairs violets qui jaillissent du cœur */
.eclair-coeur {
  filter: drop-shadow(0 0 2px #ede9fe) drop-shadow(0 0 6px #a855f7);
  animation: eclair-coeur 0.7s ease-out forwards;
}
.eclair-coeur polyline {
  fill: none;
  stroke: #f5f3ff;
  stroke-width: 1.4;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
@keyframes eclair-coeur {
  0%   { opacity: 0; }
  10%  { opacity: 1; }
  25%  { opacity: 0.4; }
  38%  { opacity: 1; }
  100% { opacity: 0; }
}

/* Cœur gravé en creux dans la dalle (index.php), avec le même traitement que le kanji :
   creux sombre, ombre d'1 px au-dessus, reflet violet clair d'1 px en dessous. Pas de battement. */
.pavage[data-fin-paisible] .coeur-fin {
  animation: none !important;
  filter: drop-shadow(0 -1px 0 rgba(0, 0, 0, 0.55)) drop-shadow(0 1px 0 rgba(196, 181, 253, 0.45));
}
.coeur-grave-pierre .coeur-creux { fill: rgba(12, 4, 30, 0.72); }

/* Début de la brume : les éclairs s'arrêtent net, la pluie s'efface doucement */
.pavage.vent .eclair,
.pavage.vent .epreuves-flash > div { display: none; }
.pavage[data-fin-paisible][data-boucle="fin"] .amb-0h05.epreuves-pluie { transition: opacity 3s ease-out !important; }
.pavage.vent[data-fin-paisible][data-boucle="fin"] .amb-0h05.epreuves-pluie { opacity: 0 !important; }

/* le rouge plein gagne progressivement, au rythme de la brume (pas de saut de couleur) */
.pavage.vent.ambiance-0h05-active[data-boucle="fin"] .amb-0h05.amour-teinte-totale {
  animation: rouge-gagne 3.2s ease-in-out forwards !important;
}
@keyframes rouge-gagne {
  from { filter: opacity(0); }
  to   { filter: opacity(1); }
}
/* pendant la brume, aucun petit cœur dans la zone noire : ils reviennent une fois le noir disparu */
.pavage.vent .coeur-droite { visibility: hidden !important; }

/* Scénario « paisible » : rouge seul au survol, puis, à 10 s, l'orage apparaît en fondu
   (classe "orage" ajoutée par pavage.js pendant 4 s), avant la brume.
   Le cœur brisé et les éclairs qui le frappaient ne font pas partie de ce scénario. */
.pavage[data-fin-paisible] .groupe-brise,
.pavage[data-fin-paisible] .foudre,
.pavage[data-fin-paisible] .impact { visibility: hidden !important; }
.pavage.orage.ambiance-0h05-active .amb-0h05.epreuves-ombre,
.pavage.orage.ambiance-0h05-active .amb-0h05.epreuves-gris,
.pavage.orage.ambiance-0h05-active .amb-0h05.epreuves-flash,
.pavage.orage.ambiance-0h05-active .amb-0h05.epreuves-eclairs,
.pavage.orage.ambiance-0h05-active .amb-0h05.epreuves-pluie {
  animation: noir-arrive 1.4s ease-out both !important;
}
.pavage.orage.ambiance-0h05-active .amb-0h05.amour-teinte-totale {
  animation: rouge-recule 1.4s ease-out both !important;
}
@keyframes noir-arrive  { from { filter: opacity(0); } to { filter: opacity(1); } }
@keyframes rouge-recule { from { filter: opacity(1); } to { filter: opacity(0); } }

/* Mode « clic » (index.php) : la légende sous l'image porte le lien vers le site de l'animation en cours */
.pavage-legende a {
  color: inherit;
  text-decoration: none;
  opacity: 1;
  cursor: pointer;
  border-bottom: 1px solid rgba(167, 139, 250, 0.5);
}
.pavage-legende a:hover { color: #fff; text-decoration: none; border-bottom-color: #fff; }

/* Rafale de « Je t'aime » (fin du cycle de mots, data-rafale) : chaque mot surgit en un éclair,
   reste un instant et s'efface vite ; la rafale s'arrête d'un coup (pavage.js retire tous les mots) */
.mot.rafale { animation-name: mot-rafale; animation-timing-function: ease-out; }
@keyframes mot-rafale {
  0%   { opacity: 0; scale: 0.85; filter: blur(2px); }
  15%  { opacity: 1; scale: 1;    filter: blur(0); }
  70%  { opacity: 1; }
  100% { opacity: 0; scale: 1.04; }
}

/* Mots qui apparaissent puis s'évaporent (index.php : data-effet="evapore", 4,2 s) :
   le mot apparaît en fondu (0,5 s) et reste lisible environ 1,8 s ; puis ses lettres s'évaporent
   une à une, de gauche à droite : chacune monte en dérivant, se dilate, devient floue et disparaît
   comme une volute (pavage.js règle pour chaque lettre son départ --d, sa dérive --dx, --dy, --r). */
.mot.evapore { animation-name: mot-evapore-apparait; animation-timing-function: ease-out; }
@keyframes mot-evapore-apparait {
  0%   { opacity: 0; filter: blur(2px); scale: 0.96; }
  12%  { opacity: 1; filter: blur(0);   scale: 1; }
  100% { opacity: 1; filter: blur(0);   scale: 1; }
}
.mot.evapore .lettre {
  display: inline-block;
  animation-name: lettre-evapore;
  animation-delay: var(--d);
  animation-timing-function: cubic-bezier(.35, 0, .6, 1);
  animation-fill-mode: forwards;
}
@keyframes lettre-evapore {
  0%   { opacity: 1;   filter: blur(0);     translate: 0 0;                         scale: 1;    rotate: 0deg; }
  25%  { opacity: 0.9; filter: blur(0.6px); }
  100% { opacity: 0;   filter: blur(4px);   translate: var(--dx) var(--dy);         scale: 1.5;  rotate: var(--r); }
}
@media (prefers-reduced-motion: reduce) {
  .mot.evapore .lettre { animation: none; }
}

/* Mots qui apparaissent puis disparaissent dans un clignotement (index.php : data-effet="clignote") */
.mot.clignote { animation-name: mot-clignote; animation-timing-function: linear; }
@keyframes mot-clignote {         /* (2,25 s) apparition, lisible 1,5 s, 2 clignotements rapides, puis fondu */
  0%   { opacity: 0; filter: blur(2px); scale: 0.95; animation-timing-function: ease-out; }
  11.1% { opacity: 1; filter: blur(0);   scale: 1; }
  66.7% { opacity: 1; }
  69.3% { opacity: 0.1; }
  72.0% { opacity: 1; }
  74.7% { opacity: 0.1; }
  77.8% { opacity: 1; animation-timing-function: ease-in-out; }
  100% { opacity: 0; filter: blur(1.5px); scale: 1; }
}


