/* Les quatre finitions sont du CSS, pas des images.
   Quatre finitions × 600 œuvres feraient 2 400 fichiers ; il y en a 600. Et une
   finition en CSS réagit au survol, ce qu'une image cuite ne peut pas. */

.cartes-page { max-width: 1100px; margin: 0 auto; padding: 18px 16px 60px; }
.cartes-message { opacity: .8; line-height: 1.5; margin: 10px 0 18px; }

.cartes-grille {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 14px;
  /* La profondeur est portee par la grille : sans elle, rotateY sur une carte
     ne donne qu'un aplatissement, pas une inclinaison. */
  perspective: 900px;
}

/* La classe .carte est générique : ces règles sont donc portées par les deux
   conteneurs de la collection. Sans cette restriction, la feuille — chargée sur
   les 63 pages du portail — imposait position:relative et aspect-ratio:5/7 à
   toute autre .carte de la page. Le Videur, dont les cartes sont en
   position:absolute empilées, voyait les siennes se ranger dans le flux : trois
   affiches géantes l'une sous l'autre, boutons de jeu repoussés hors écran. */
.cartes-grille .carte:not(.carte--dos),
.rev-support .carte:not(.carte--dos) {
  /* Le fond sombre n'est posé QUE sur les cartes normales. Un dos porte
     sa propre image (`url(dos.jpg)`) : dans le bloc, ce sélecteur (0,2,0)
     l'écrasait et le dos s'affichait en noir uni — mesuré le 30/09/2026. */
  background: #12121a;
}
.cartes-grille .carte,
.rev-support .carte {
  position: relative;
  aspect-ratio: 5 / 7;   /* le format du dos de marque, et des vraies cartes */
  border-radius: 10px;
  overflow: hidden;
  border: 2px solid rgba(255, 255, 255, .14);
  /* --ry / --rx : l'inclinaison, en degres. --gx / --gy : ou se trouve le
     pointeur sur la carte. --tenue vaut 1 tant qu'on la manipule.
     Tout est pose par js/manipulation.js ; sans lui la carte reste a plat. */
  --ry: 0; --rx: 0; --gx: 50%; --gy: 50%; --tenue: 0;
  transform: rotateY(calc(var(--ry) * 1deg)) rotateX(calc(var(--rx) * 1deg));
  /* Zéro pendant qu'on la tient, pour que la carte colle à la main ; .35 s
     quand on la lâche, pour qu'elle se repose au lieu de claquer à plat.
     Une transition constante de .14 s faisait traîner la carte derrière le
     pointeur — on sentait le retard. */
  transition: transform calc((1 - var(--tenue)) * .35s) ease;
}
/* Pas de translateY au survol : elle se battrait avec la rotation. */
.cartes-grille .carte img,
.rev-support .carte img { width: 100%; height: 100%; object-fit: cover; display: block; }

.carte__bandeau {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 7px 9px;
  background: rgba(18, 18, 26, .88);   /* un aplat, pas un fondu */
  color: #fff;
  font-size: .78rem;
  line-height: 1.25;
}
.carte__titre { font-weight: 700; }
.carte__annee { opacity: .72; font-size: .72rem; }
/* La rareté en ÉTOILES, pas en mots.
   « PEU COMMUNE » fait douze caractères sur une carte de 150 px, et une
   étiquette de texte se pose sur le carton comme un autocollant. Une à cinq ✦
   se lisent d'un coup d'œil et se comparent sans légende. La forme est celle de
   la charte (« accents Memphis : ●, ✦ ») et celle du visuel du dos. */
.carte__rarete {
  position: absolute; top: 7px; left: 8px;
  font-size: .72rem; line-height: 1; letter-spacing: .06em;
  /* Le contour net de la charte, en quatre ombres dures : les étoiles se posent
     aussi bien sur une affiche claire que sur une nuit. */
  text-shadow: 1px 1px 0 #1a1a1a, -1px 1px 0 #1a1a1a, 1px -1px 0 #1a1a1a, -1px -1px 0 #1a1a1a;
}
.carte__rarete--courante    { color: #8b93ff; }
.carte__rarete--peu_commune { color: #16c08a; }
.carte__rarete--rare        { color: #2b2bff; }
.carte__rarete--tres_rare   { color: #ff5da2; }
.carte__rarete--legendaire  { color: #ffd23f; }
.carte__nombre {
  position: absolute; top: 7px; right: 7px;
  padding: 2px 7px; border-radius: 999px;
  font-size: .68rem; font-weight: 700;
  background: rgba(0, 0, 0, .62); color: #fff;
}

/* ── Le reflet et le bord argenté ─────────────────────────── */
/* Une carte de collection se regarde en la bougeant : c'est le reflet qui se
   déplace qui donne le relief. Ces deux couches sont INERTES au repos
   (--tenue: 0) et ne coûtent donc rien aux 600 cartes d'une page immobile. */
.carte__reflet, .carte__bord {
  position: absolute; inset: 0; pointer-events: none;
  opacity: calc(var(--tenue) * 1);
  /* Allumage immédiat, extinction lente : la brillance suit la main sans
     retard, et ne fait pas un à-coup quand on quitte la grille. Symétrique,
     elle clignotait à chaque aller-retour. */
  transition: opacity calc((1 - var(--tenue)) * .45s) ease;
}

/* Le reflet : une tache claire posée là où se trouve le pointeur.
   ⚠️ Discret, et c'est le point. Une première version montait à .42 en
   « screen » sur plus de la moitié de la carte : l'affiche passait sous un
   voile blanc et on ne voyait plus ses couleurs. Un reflet doit se poser SUR
   l'image, pas la remplacer — d'où « overlay », qui éclaircit sans délaver, et
   une tache resserrée. */
.carte__reflet {
  background: radial-gradient(circle at var(--gx) var(--gy),
    rgba(255, 255, 255, .34) 0%, rgba(255, 255, 255, .10) 16%, transparent 38%);
  mix-blend-mode: overlay;
}

/* Le bord : un liseré argenté PAILLETÉ, qui tourne avec l'inclinaison.
   Deux couches masquées en anneau — le métal, puis les paillettes. */
.carte__bord {
  border-radius: 10px;
  padding: 4px;
  background:
    /* Les paillettes : des points clairs ET sombres. Des points blancs seuls
       disparaissaient sur un métal déjà clair — c'est le contraste entre les
       deux qui fait scintiller, pas la brillance des points. */
    radial-gradient(circle at 30% 30%, #ffffff 0 1px, transparent 1.4px) var(--gx) 0 / 6px 6px,
    radial-gradient(circle at 70% 60%, #404650 0 .9px, transparent 1.3px) 3px 3px / 8px 8px,
    radial-gradient(circle at 20% 80%, #ffffff 0 .7px, transparent 1px) 5px 2px / 11px 11px,
    /* le métal : gris, blanc, gris — il tourne avec l'inclinaison */
    conic-gradient(from calc(var(--ry) * 6deg + 40deg),
      #6b7280, #e8eaed, #ffffff, #9aa1ab, #e8eaed, #ffffff, #6b7280, #e8eaed, #6b7280);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
}
/* Plus la finition est belle, plus le bord accroche la lumière. Une courante
   garde un liseré discret : sinon les quatre finitions se ressemblent. */
.carte--courante .carte__bord { opacity: calc(var(--tenue) * .35); }
.carte--brillante .carte__bord { opacity: calc(var(--tenue) * .6); }
.carte--doree .carte__bord { opacity: calc(var(--tenue) * .85); filter: sepia(.55) saturate(2.2) hue-rotate(-12deg); }
.carte--holographique .carte__bord { opacity: var(--tenue); filter: saturate(1.5); }

/* Un dos ne se penche pas et n'a rien à refléter. */
.carte--dos .carte__reflet, .carte--dos .carte__bord { display: none; }

@media (prefers-reduced-motion: reduce) {
  .cartes-grille .carte, .rev-support .carte { transition: none; }
}

/* Le bouton de permission gyroscope (iOS l'exige sur un geste). */
.cartes-gyro {
  background: #ffd23f; color: #1a1a1a;
  border: 2px solid #1a1a1a; box-shadow: 4px 4px 0 #1a1a1a;
  font-family: inherit; font-weight: 800; font-size: .85rem;
  padding: 8px 16px; border-radius: 999px; cursor: pointer;
}

/* Une carte manquante : la silhouette, pour qu'on voie le trou à combler. */
.carte--manquante img { filter: grayscale(1) brightness(.28); }
.carte--manquante .carte__bandeau { opacity: .55; }

/* ── Les quatre finitions ─────────────────────────────────── */
.carte--courante { border-color: rgba(255, 255, 255, .14); }

.carte--brillante {
  border-color: #9ec5ff;
  box-shadow: 0 0 12px rgba(158, 197, 255, .38);
}

.carte--doree {
  border-color: #f4c04a;
  box-shadow: 0 0 16px rgba(244, 192, 74, .48);
}
/* Le lustre doré suit la main au lieu d'être figé en travers de la carte. */
.carte--doree::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg,
    transparent calc(var(--gx) - 18%), rgba(255, 233, 160, .30) var(--gx), transparent calc(var(--gx) + 18%));
}

.carte--holographique {
  border-color: #fff;
  box-shadow: 0 0 22px rgba(190, 120, 255, .6);
}
/* ⚠️ L'irisation ne tourne PLUS toute seule.
   Elle bouclait en permanence sur chaque carte holographique, survol ou non :
   plusieurs dans une même grille faisaient un mur qui scintille sans qu'on le
   demande, et le color-dodge à .34 effaçait les couleurs de l'affiche.
   Une vraie carte foil ne fait rien tant qu'on ne la bouge pas. Ici l'irisation
   est posée au repos, et c'est l'INCLINAISON qui la fait courir. */
.carte--holographique::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg,
    rgba(255, 0, 128, .26), rgba(0, 220, 255, .26), rgba(180, 255, 0, .26), rgba(255, 0, 128, .26));
  background-size: 300% 300%;
  background-position: calc(var(--gx) * 3) 50%;
  mix-blend-mode: overlay;
  opacity: calc(.45 + var(--tenue) * .55);
  transition: opacity calc((1 - var(--tenue)) * .45s) ease;
}
/* Une animation en boucle sur une grille entière est exactement ce que ce
   réglage système demande d'éviter. */
@media (prefers-reduced-motion: reduce) {
  .cartes-grille .carte, .rev-support .carte { transition: none; }
}

/* ── Séries et éclats ─────────────────────────────────────── */
.serie { margin: 26px 0; }
.serie__entete { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
.serie__nom { font-weight: 700; font-size: 1.05rem; }
.serie__compte { opacity: .68; font-size: .85rem; }
.serie__barre { height: 6px; border-radius: 999px; background: rgba(255, 255, 255, .12); overflow: hidden; margin-bottom: 12px; }
/* Violet → orange : c'est l'exemple que design.md §1 cite comme le look qu'on
   refuse. Un aplat bleu de marque, avec l'encre en séparation. */
.serie__barre > span { display: block; height: 100%; background: #2b2bff; }
.serie__barre { border: 2px solid #fbf2dd; background: #17151f; height: 10px; }

.eclats { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: 1.05rem; }

/* ── Le dos d'une carte pas encore gagnée ─────────────────── */
/* Ni image d'œuvre, ni titre : la surprise est l'état par défaut. Un clic
   retourne la carte, pour qui veut viser une fabrication précise.

   Le dos est le visuel de marque (brand/doscartes.png), préparé pour le web par
   tools/preparer-dos.mjs : 2 774 Ko → 67 Ko. UNE seule image pour les 600
   emplacements — un fichier chargé une fois, pas six cents.

   Le visuel porte son propre cadre noir et ses coins arrondis, détourés sur un
   gris clair. Le border-radius de la carte coupe ce gris : rien à détourer. */
.carte--dos {
  display: flex; align-items: flex-start; justify-content: flex-start;
  cursor: pointer; padding: 0; font: inherit; width: 100%;
  border: none;
  background: #f2e0c4 url('../img/dos.jpg?v=1') center / cover no-repeat;
  box-shadow: 4px 4px 0 #000000;           /* dure, jamais de blur */
  transition: transform var(--fast, 140ms ease);
}
.carte--dos:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 #000000; }
.carte--dos:focus-visible { outline: 3px solid #2b2bff; outline-offset: 3px; }

/* Sur un dos, les étoiles disent combien vaut ce qui manque — pas ce que c'est.
   À gauche : les rubans et l'étoile du visuel passent par l'axe médian.
   Le contour est clair ici, le carton étant crème. */
.carte--dos .carte__rarete {
  top: 12px; left: 12px;
  text-shadow: 1px 1px 0 #f2e0c4, -1px 1px 0 #f2e0c4, 1px -1px 0 #f2e0c4, -1px -1px 0 #f2e0c4;
}

@media (prefers-reduced-motion: reduce) {
  .carte--dos:hover { transform: none; }
}

/* ── La révélation d'une carte gagnée ─────────────────────── */
/* Transposée de la surcouche du Pronostic Coupe du Monde, mais remise à la
   charte Zikof : l'originale empilait backdrop-filter, halo en radial-gradient
   et titre en dégradé — les trois choses que design.md §1 nomme comme le look
   qu'on refuse. Ici : aplats, contours nets, ombres dures. */
#cartes-revelation {
  /* L'échelle du portail, telle qu'elle est déjà écrite ailleurs :
       11000–12500   badges, notifications
       2000000000    onboarding (shared/css/onboarding.css)
       2147483000    écran « déjà joué » (shared/js/DailyGameManager.js)
     La révélation vient d'un clic volontaire sur le coffre : elle passe devant
     l'onboarding, qui est passif. Mesuré : à 9999, l'onboarding de ZikoMap
     recouvrait entièrement la carte gagnée. */
  position: fixed; inset: 0; z-index: 2000000500;
  display: none; opacity: 0; transition: opacity .2s ease;
  flex-direction: column; align-items: center; justify-content: center;
  padding: 24px;
  background: #17151f;                     /* --bg, plein. Pas de verre dépoli. */
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
  color: #fbf2dd;
}
/* .visible plutôt qu'une animation : une animation gelée laisserait la
   surcouche invisible, et le joueur ne verrait jamais sa carte. */
#cartes-revelation.visible { display: flex; opacity: 1; }

.rev-titre {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(1.3rem, 5.5vw, 2rem); font-weight: 800; letter-spacing: -.02em;
  text-align: center; margin-bottom: 8px;
  color: var(--eclat, #ffd23f);            /* la couleur du palier, en aplat */
  animation: rev-pop .35s .05s both;
}
.rev-sous { color: #b9b3c9; font-size: .88rem; margin-bottom: 20px; min-height: 1.1em; text-align: center; }
@keyframes rev-pop { from { opacity: 0; transform: translateY(-14px); } to { opacity: 1; transform: none; } }

.rev-scene { position: relative; width: 230px; max-width: 74vw; perspective: 900px; }

/* L'éclat : un disque PLEIN de la couleur du palier, qui grandit derrière la
   carte et disparaît. Un halo dégradé ferait le contraire de la charte. */
.rev-eclat {
  position: absolute; left: 50%; top: 50%; z-index: 0;
  width: 150%; aspect-ratio: 1; margin: -75% 0 0 -75%;
  border-radius: 999px;
  background: var(--eclat, #ffd23f);
  opacity: 0; pointer-events: none;
  animation: rev-eclat .9s ease-out .15s;
}
@keyframes rev-eclat {
  0% { opacity: 0; transform: scale(.2); }
  30% { opacity: .5; }
  100% { opacity: 0; transform: scale(1.5); }
}
/* La carte surgit : minuscule et de travers, puis elle se pose. Le ressort du
   cubic-bezier est ce qui fait qu'elle ARRIVE au lieu d'apparaître. */
.rev-support {
  position: relative; z-index: 1;
  transform: scale(.15) rotate(-14deg); opacity: 0;
  animation: rev-carte .85s cubic-bezier(.16, 1.7, .4, 1) .2s forwards;
}
@keyframes rev-carte { to { transform: scale(1) rotate(0); opacity: 1; } }
/* Dans la surcouche, la carte est une prise : jamais grisée, même si c'est la
   première fois qu'on la voit. */
.rev-support .carte--manquante img { filter: none; }
.rev-support .carte--manquante .carte__bandeau { opacity: 1; }

.rev-actions { margin-top: 26px; display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; animation: rev-pop .3s .9s both; }
.rev-btn {
  background: #2b2bff; color: #ffffff;     /* --blue / --on-blue */
  border: 2px solid #fbf2dd;
  font-family: inherit; font-weight: 800; font-size: .92rem;
  padding: 12px 22px; border-radius: 999px; cursor: pointer;
  box-shadow: 4px 4px 0 #000000;
  transition: transform var(--fast, 140ms ease);
}
.rev-btn:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 #000000; }
.rev-btn.rev-fantome { background: transparent; color: #fbf2dd; box-shadow: 2px 2px 0 #000000; }

/* Les confettis : des rectangles pleins, z-index 2 donc PAR-DESSUS la carte.
   Derrière elle — comme dans la surcouche d'origine — ils partent d'un point
   situé au milieu d'une scène de 230 px : la carte les masque presque tous, et
   on lance 48 éléments pour rien. */
.rev-confetti {
  position: absolute; left: 50%; top: 46%; z-index: 2;
  width: 9px; height: 14px; border: 1px solid #1a1a1a;
  pointer-events: none; opacity: 0;
}
@keyframes rev-conf {
  0% { opacity: 1; transform: translate(0, 0) rotate(0); }
  100% { opacity: 0; transform: translate(var(--dx, 0), calc(var(--dy, 0) + 130px)) rotate(380deg); }
}
@media (prefers-reduced-motion: reduce) {
  .rev-support { animation: none; transform: none; opacity: 1; }
  .rev-eclat, .rev-confetti { display: none; }
  .rev-btn:hover { transform: none; }
}

/* La légende des étoiles, sur la page de collection. Une seule ligne : elle
   rend le barème décodable sans rien écrire sur les cartes elles-mêmes. */
.cartes-legende {
  display: flex; flex-wrap: wrap; gap: 4px 16px;
  font-size: .78rem; opacity: .8; margin: 6px 0 18px;
  list-style: none; padding: 0;
}
.cartes-legende b { font-weight: 700; letter-spacing: .06em; margin-right: 5px; }
/* Dans la légende, les étoiles ne sont plus posées sur une carte — mais le
   contour reste : sans lui, le bleu de « Rare » disparaît sur le fond sombre.
   Un liseré clair ici, l'inverse d'une carte. */
.legende__etoiles {
  position: static;
  text-shadow: 1px 1px 0 rgba(251, 242, 221, .5), -1px 1px 0 rgba(251, 242, 221, .5),
               1px -1px 0 rgba(251, 242, 221, .5), -1px -1px 0 rgba(251, 242, 221, .5);
}
body.light-theme .legende__etoiles {
  text-shadow: 1px 1px 0 rgba(26, 26, 26, .35), -1px 1px 0 rgba(26, 26, 26, .35),
               1px -1px 0 rgba(26, 26, 26, .35), -1px -1px 0 rgba(26, 26, 26, .35);
}

/* ═══ SEQUENCE DE REVELATION — ajoutee le 20260930-123053 ═══ */
/* ═══════════════════════════════════════════════════════════════════════
   La séquence de révélation — CSS (v2, corrigée après mesure)

   ⛔ CE QUI A ÉTÉ CORRIGÉ, ET POURQUOI — la v1 ne marchait pas.

   Mesure du 30/09/2026 : le navigateur retenait `animationDelay = 0s, 0.5s,
   0.85s` — le REPLI de 0,35 s au lieu des 1,75 s d'une légendaire. La carte
   se retournait donc à 0,85 s au lieu de 2,25 s, et on la voyait de profil
   (une simple ligne) pendant toute l'attente. Deux fautes :

     ① `var()` placé dans le SHORTHAND `animation`. Le navigateur ne le
        résout pas de façon fiable : la durée restait bloquée au repli.
     ② TROIS animations sur la MÊME propriété `transform`. Seule la dernière
        de la liste s'applique ; les deux autres ne servaient à rien, et
        leurs délais se sont retrouvés décalés d'un cran.

   La règle à retenir : UN ÉLÉMENT = UNE ANIMATION = UNE PROPRIÉTÉ.

   D'où deux conteneurs imbriqués :
     .rev-tensionneur  → l'arrivée, puis le tremblement (transform 2D)
     .rev-pivot        → le retournement seul (rotateY)
   Et les délais sont calculés EN JAVASCRIPT (variables inline), jamais en
   `calc()` sur une variable CSS.

   La chronologie, avec T = la tension du palier (0,30 s → 2,30 s) :
     0        → 0,50+T      le DOS arrive puis la TENSION monte
     0,50+T   → +0,62       le RETOURNEMENT (rotateY 180°)
     +0,12                  le titre claque

   ⛔ La charte ne bouge pas : mêmes couleurs, même fond sombre, mêmes formes.
   Le reveal n'invente pas un thème, il met en scène celui du site.
   ═══════════════════════════════════════════════════════════════════════ */

.rev-scene {
  position: relative;
  width: 230px;
  max-width: 74vw;
  perspective: 900px;
}

/* ── L'éclat de fond, teinté du palier (délais posés en JS) ── */
.rev-eclat {
  position: absolute; left: 50%; top: 50%; z-index: 0;
  width: 150%; aspect-ratio: 1; margin: -75% 0 0 -75%;
  border-radius: 999px;
  background: var(--eclat, #ffd23f);
  opacity: 0; pointer-events: none;
}

/* ── Le flash du retournement ── */
.rev-flash {
  position: absolute; inset: -45%; z-index: 5;
  border-radius: 999px;
  background: radial-gradient(circle at 50% 50%,
      #ffffff 0%, var(--eclat, #ffd23f) 30%, transparent 66%);
  opacity: 0; pointer-events: none;
}

/* ── LA CARTE ELLE-MÊME ────────────────────────────────────────────────
   ⛔ Sans ce bloc, la carte est INVISIBLE — mesuré le 30/09/2026.
   L'ancien CSS donne ses dimensions à la carte par `.rev-support .carte`
   (`aspect-ratio: 5/7`, l'image en 100 %). Le HTML de la v5 n'utilise plus
   la classe `rev-support`, donc la carte reste à hauteur nulle et la scène
   apparaît vide au milieu de la surcouche.

   On reprend ici les règles de dimensionnement — MAIS PAS le `transform`
   (`rotateY(var(--ry))`) ni la `transition` de manipulation : ils
   appartiennent à `CartesManipulation`, qui les écrit APRÈS l'animation.
   Les reprendre ici ferait tourner la carte sur elle-même pendant le flip. */
.rev-tensionneur .carte,
.rev-pivot .carte {
  position: relative;
  aspect-ratio: 5 / 7;
  border-radius: 10px;
  overflow: hidden;
  border: 2px solid rgba(255, 255, 255, .14);
  /* ⛔ PAS de `background` ici : `.carte--dos` porte le sien
     (`url('../img/dos.jpg')`) et ma règle a une spécificité SUPÉRIEURE
     (0,2,0 contre 0,1,0) — elle écrasait l'image du dos. Mesuré le
     30/09/2026 : le dos s'affichait en noir uni. */
}
.rev-tensionneur .carte img,
.rev-pivot .carte img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── Le tensionneur : arrivée du dos, puis tremblement. Une seule animation
      sur cet élément à la fois (le JS passe de l'une à l'autre). ── */
.rev-tensionneur {
  position: relative;
  transform-origin: center 55%;
}

/* ── Le pivot : le retournement seul. ── */
.rev-pivot {
  position: relative; z-index: 1;
  transform-style: preserve-3d;
  transform-origin: center 55%;
}

.rev-face {
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  width: 100%;
}
.rev-face-avant {
  position: absolute; inset: 0;
  transform: rotateY(180deg);
}

/* Le dos : cadre sombre + liseré de la couleur du palier qui s'allume.
   ⛔ `overflow: visible` et pas `hidden` : le halo du liseré est un
   `box-shadow` externe, que `hidden` rognerait. La carte garde son propre
   `border-radius` + `overflow: hidden` (règle du site), donc rien ne dépasse.
   ⛔ Et le liseré vit sur un `::after` séparé, PAS sur `.rev-face-dos`
   lui-même : animer son opacité effacerait aussi la carte qu'il contient. */
.rev-face-dos {
  position: relative;
  border-radius: 12px;
  overflow: visible;
}
.rev-face-dos .carte { box-shadow: 0 18px 40px rgba(0, 0, 0, .55); }
/* Le liseré est un ÉLÉMENT À PART, pas un pseudo-élément ni le porteur de la
   carte : le JS lui pose son animation, et animer `opacity` sur un conteneur
   effacerait tout ce qu'il contient. */
.rev-lisere {
  position: absolute; inset: -3px;
  border-radius: 14px;
  border: 3px solid var(--eclat, #ffd23f);
  opacity: 0;
  pointer-events: none;
  z-index: 2;
}

/* ═══════════════════ LES KEYFRAMES ═══════════════════ */

/* 1. Le dos arrive — petit et de travers, il se pose. Le ressort existait
      déjà en v3 : c'est lui qui fait ARRIVER la carte au lieu de la faire
      apparaître. */
@keyframes rev-arrivee {
  from { transform: scale(.15) rotate(-14deg); opacity: 0; }
  to   { transform: scale(1) rotate(0deg); opacity: 1; }
}

/* 2. La tension — le dos tremble de plus en plus, sans jamais se retourner.
      Amplitude faible : c'est l'accélération qui porte l'attente, un
      tremblement large ferait brouillon. */
@keyframes rev-tension {
  0%   { transform: translate(0, 0) rotate(0deg) scale(1); }
  18%  { transform: translate(-3px, 1px) rotate(-1.1deg) scale(1.012); }
  36%  { transform: translate(3px, -1px) rotate(1.1deg) scale(1.018); }
  54%  { transform: translate(-3px, 0) rotate(-1.3deg) scale(1.026); }
  72%  { transform: translate(3px, 1px) rotate(1.3deg) scale(1.034); }
  86%  { transform: translate(-2px, 0) rotate(-1.5deg) scale(1.042); }
  100% { transform: translate(0, 0) rotate(0deg) scale(1.05); }
}

/* 3. Le retournement — 180° avec un léger dépassement qui se remet en place.
      ⛔ Pas de `scale` ici : le tensionneur porte déjà `scale(1.05)` en fin de
      tension. En remettre un ferait 1.05 × 1.05 et la carte sauterait de 10 %
      à l'instant du retournement. Le pivot ne fait que tourner. */
@keyframes rev-flip {
  0%   { transform: rotateY(0deg); }
  68%  { transform: rotateY(191deg); }
  100% { transform: rotateY(180deg); }
}

/* 4. Le flash — court, une seule frame franche. */
@keyframes rev-flash {
  0%   { opacity: 0; transform: scale(.55); }
  22%  { opacity: .92; }
  100% { opacity: 0; transform: scale(1.5); }
}

/* 5. Le liseré du dos qui s'allume pendant l'attente. */
@keyframes rev-lisere {
  from { opacity: 0; box-shadow: 0 0 0 rgba(0, 0, 0, 0); }
  to   { opacity: .85; box-shadow: 0 0 26px var(--eclat, #ffd23f); }
}

/* 6. Le titre qui claque : il tombe de haut et se pose avec du poids. */
@keyframes rev-titre-pop {
  0%   { opacity: 0; transform: translateY(-22px) scale(.82); letter-spacing: -.06em; }
  60%  { opacity: 1; transform: translateY(3px) scale(1.04); }
  100% { opacity: 1; transform: translateY(0) scale(1); letter-spacing: -.02em; }
}

/* 7. L'apparition simple (sous-titre, boutons). */
@keyframes rev-pop {
  from { opacity: 0; transform: translateY(-14px); }
  to   { opacity: 1; transform: none; }
}

/* 8. Les confettis. */
@keyframes rev-conf {
  0%   { opacity: 1; transform: translate(0, 0) rotate(0deg) scale(1); }
  100% { opacity: 0; transform: translate(var(--dx), var(--dy)) rotate(320deg) scale(.6); }
}

/* ⛔ Accessibilité : la séquence s'efface, on garde l'apparition simple.
      Une animation qu'on ne peut pas couper est un défaut, pas une finition. */
@media (prefers-reduced-motion: reduce) {
  .rev-tensionneur, .rev-pivot {
    animation: rev-arrivee .2s ease-out both !important;
  }
  .rev-eclat, .rev-flash, .rev-face-dos::after, .rev-confetti { display: none; }
  .rev-titre, .rev-sous, .rev-actions { animation: none !important; opacity: 1; transform: none; }
}
