/* La scène d'obtention d'une carte Promo.

   Elle emprunte au théâtre d'ouverture sans le copier : là-bas on déchire un
   paquet et six cartes défilent ; ici il n'y en a qu'une, et tout l'écran est
   pour elle. Un fond qui tourne, une carte qui arrive de loin dos tourné, un
   retournement, puis le nom. */

.promoscene{--foyer:40%;
  position:fixed;inset:0;z-index:60;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:clamp(10px,3vh,26px);
  padding:calc(20px + env(safe-area-inset-top,0px)) 18px calc(20px + env(safe-area-inset-bottom,0px));
  background:radial-gradient(circle at 50% 42%,#2a0f3a,#0a0510 62%,#050208);
  overflow:hidden;text-align:center;animation:pr-fade .32s ease-out}
@keyframes pr-fade{from{opacity:0}}

/* Les rayons : lents, à peine visibles, ils donnent une profondeur au vide. */
/* Le point de fuite est calé sur la carte, pas sur la fenêtre : des rayons qui
   convergent à côté de leur sujet se lisent comme un défaut d'alignement. */
.pr-rays{position:absolute;top:var(--foyer,42%);left:50%;width:220vmax;height:220vmax;translate:-50% -50%;
  pointer-events:none;opacity:0;
  background:repeating-conic-gradient(from 0deg at 50% 50%,
    rgba(255,255,255,.085) 0deg 5deg,transparent 5deg 16deg);
  -webkit-mask:radial-gradient(circle,#000 6%,rgba(0,0,0,.55) 34%,transparent 66%);
  mask:radial-gradient(circle,#000 6%,rgba(0,0,0,.55) 34%,transparent 66%);
  animation:pr-turn 44s linear infinite;transition:opacity 1s ease-out .3s}
@keyframes pr-turn{to{transform:rotate(360deg)}}
.promoscene.go .pr-rays,.promoscene.direct .pr-rays{opacity:1}

.pr-glow{position:absolute;top:var(--foyer,42%);left:50%;width:min(760px,150vw);aspect-ratio:1;translate:-50% -50%;
  pointer-events:none;border-radius:50%;opacity:0;
  background:radial-gradient(circle,rgba(255,91,176,.42),rgba(169,92,242,.2) 38%,transparent 68%);
  transition:opacity .9s ease-out}
.promoscene.face .pr-glow,.promoscene.direct .pr-glow{opacity:1;animation:pr-pulse 4.5s ease-in-out infinite 1s}
@keyframes pr-pulse{50%{opacity:.66;transform:translate(-50%,-50%) scale(1.07)}}

.pr-kicker{position:relative;display:inline-block;flex:0 0 auto;
  background:linear-gradient(90deg,var(--r-pr),var(--accent-soft));color:#fff;
  border-radius:999px;padding:6px 18px;font-size:11px;font-weight:900;letter-spacing:.14em;
  text-transform:uppercase;box-shadow:0 6px 20px rgba(255,91,176,.42);
  opacity:0;translate:0 -10px;transition:opacity .5s,translate .5s}
.promoscene.go .pr-kicker,.promoscene.direct .pr-kicker{opacity:1;translate:0 0}

/* ---------- La carte ---------- */
.pr-stage{position:relative;flex:0 1 auto;min-height:0;display:flex;flex-direction:column;
  align-items:center;perspective:1400px}
.pr-card{position:relative;width:min(62vw,calc((100dvh - 330px) * .714),286px);aspect-ratio:5/7;
  transform-style:preserve-3d;
  /* Départ : loin, de dos, penchée. */
  transform:translateZ(-620px) rotateY(180deg) rotateZ(-16deg);
  filter:drop-shadow(0 30px 46px rgba(0,0,0,.8))}
.promoscene.go .pr-card{animation:pr-come 1.15s forwards}
/* Chaque étape porte sa propre courbe, et ce n'est pas un détail de style :
   l'arrivée freine, le retournement est symétrique. C'est cette symétrie qui
   place le quart de tour au milieu exact de l'intervalle — à 76 % de
   l'animation — et permet d'y caler l'échange des deux faces (plus bas). */
@keyframes pr-come{
  0%{animation-timing-function:cubic-bezier(.22,.78,.3,1);
     transform:translateZ(-620px) rotateY(180deg) rotateZ(-16deg)}
  /* Le retournement part après l'arrivée : deux gestes, pas un seul flou. */
  52%{animation-timing-function:cubic-bezier(.5,0,.5,1);
      transform:translateZ(0) rotateY(180deg) rotateZ(0)}
  100%{transform:translateZ(0) rotateY(360deg) rotateZ(0)}}
.promoscene.face .pr-card{transform:none;animation:pr-float 5.5s ease-in-out infinite 1.2s}
@keyframes pr-float{50%{translate:0 -12px;rotate:.8deg}}
.promoscene.direct .pr-card{transform:none}

/* Les deux faces de la carte.

   `backface-visibility:hidden` **ne suffit pas** ici : la propriété ne
   s'hérite pas, et la carte posée à l'intérieur de `.pr-face` — avec son
   `overflow`, son `border-radius` et son propre contexte — se retrouve
   dessinée de dos, en miroir. C'est ce qu'on voyait : l'illustration inversée
   au lieu du dos de carte.

   On ne s'appuie donc sur rien d'implicite. Une seule face est visible à la
   fois, et le basculement se fait au quart de tour exact, quand la carte est
   sur la tranche et que personne ne peut voir l'échange (voir montrerPromo()
   dans js/promos.js). */
.pr-face,.pr-back{position:absolute;inset:0;border-radius:12px;overflow:hidden}
.pr-back{transform:rotateY(180deg);background:var(--bg-2)}
.pr-back img{width:100%;height:100%;object-fit:cover;display:block}
.pr-face .cwrap,.pr-face .card{width:100%;height:100%;margin:0}
.pr-face img{width:100%;height:100%;object-fit:cover;display:block}

/* Au départ : le dos, et rien d'autre. L'échange se fait à 76 % de
   l'animation, c'est-à-dire au quart de tour exact, quand la carte est sur la
   tranche et que personne ne peut voir le remplacement.

   En animation et non par un `setTimeout` : le minuteur du navigateur ne suit
   pas l'horloge de l'animation, il dérive d'une image ou deux — et une image
   de trop, ici, c'est le dos de la carte montré à l'envers. `steps(1,end)`
   fait une bascule franche, sans fondu.

   `opacity` plutôt que `visibility` : entre `visible` et `hidden`, une
   animation garde `visible` du début à la fin de l'intervalle, ce qui rendrait
   ces images-clés inopérantes. */
.pr-face{opacity:0}
.promoscene.go .pr-face{animation:pr-montre 1.15s steps(1,end) forwards}
.promoscene.go .pr-back{animation:pr-cache 1.15s steps(1,end) forwards}
@keyframes pr-montre{0%{opacity:0}76%{opacity:1}100%{opacity:1}}
@keyframes pr-cache{0%{opacity:1}76%{opacity:0}100%{opacity:0}}
.promoscene.face .pr-face,.promoscene.direct .pr-face{opacity:1}
.promoscene.face .pr-back,.promoscene.direct .pr-back{opacity:0}

/* Le halo rose qui déborde de la carte, une fois face visible. */
.promoscene.face .pr-face::after,.promoscene.direct .pr-face::after{content:'';position:absolute;inset:0;
  border-radius:12px;pointer-events:none;
  box-shadow:0 0 0 2px rgba(255,255,255,.55),0 0 40px rgba(255,91,176,.75),0 0 90px rgba(169,92,242,.5)}

.pr-shadow{width:52%;height:16px;margin-top:20px;border-radius:50%;opacity:0;
  background:radial-gradient(ellipse,rgba(0,0,0,.72),transparent 70%);transition:opacity .6s .5s}
.promoscene.face .pr-shadow,.promoscene.direct .pr-shadow{opacity:1}

/* ---------- Le nom ---------- */
.pr-id{position:relative;flex:0 0 auto;opacity:0;translate:0 14px;transition:opacity .45s,translate .45s}
.promoscene.dit .pr-id{opacity:1;translate:0 0}
.pr-code{display:inline-block;background:rgba(255,255,255,.12);color:#fff;border-radius:999px;
  padding:2px 11px;font-family:var(--display);font-weight:900;font-size:11.5px;letter-spacing:.1em;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.22)}
.pr-nom{font-family:var(--display);font-stretch:114%;font-weight:900;font-style:italic;
  font-size:clamp(26px,7.4vw,40px);letter-spacing:-.035em;line-height:1.02;color:#fff;
  margin:8px 0 5px;padding:0;text-transform:none;
  text-shadow:0 2px 16px rgba(255,91,176,.6),0 1px 2px rgba(0,0,0,.6)}
.pr-nom::before{display:none}
.pr-sous{margin:0 auto;max-width:34ch;font-size:13px;color:rgba(255,255,255,.66);line-height:1.4}

.pr-acts{position:relative;flex:0 0 auto;width:100%;max-width:320px;opacity:0;
  transition:opacity .4s .25s}
.promoscene.dit .pr-acts{opacity:1}
/* Tant que le bouton n'est pas apparu, il ne doit pas pouvoir être touché :
   sur mobile, un doigt posé au hasard fermait la scène avant le retournement. */
.pr-acts .btn{pointer-events:none}
.promoscene.dit .pr-acts .btn{pointer-events:auto}

/* ---------- Les Promos dans la collection ---------- */
/* Une section à part, sous l'extension : ces cartes ne comptent pas dans le
   total, elles ne doivent donc pas se fondre dans la même grille. */
.promosec{margin-top:var(--gap-5);padding-top:var(--gap-4);border-top:1px solid var(--line)}
.promohead{display:flex;align-items:center;gap:11px;margin:0 0 var(--gap-3)}
.promohead .qpico{background:var(--surface-2);color:var(--accent-soft);
  box-shadow:inset 0 0 0 1px var(--line-2)}
.promohead>div{flex:1;min-width:0}
.promohead h2{margin:0;padding:0}
.promohead h2::before{display:none}
.promohead p{margin:2px 0 0;font-size:12.5px;color:var(--muted)}
.promohead .qpreste b{color:var(--text)}

/* La case d'une promo non possédée dit comment l'obtenir : c'est la seule
   grille du jeu où le vide a une réponse. Elle reste une case vide, sans
   liseré de couleur : c'est la ligne dessous qui porte l'information, pas un
   cadre rose qui crie. */
.gcell.promovide .ghost-card{box-shadow:inset 0 0 0 1px var(--line-2)}
.promocomment{display:-webkit-box;font-size:10px;font-weight:700;line-height:1.3;
  color:var(--muted);margin-top:6px;text-align:center;overflow:hidden;
  -webkit-line-clamp:2;-webkit-box-orient:vertical;min-height:2.6em}

/* Un emplacement dont la carte n'existe pas encore : plus effacé que les
   autres, et sans promesse de date. */
.gcell.avenir .ghost-card{opacity:.55}
.gcell.avenir .promocomment{color:var(--muted);font-style:italic;opacity:.8}

@media (max-width:560px){
  .promocomment{font-size:9px;min-height:2.4em;margin-top:4px}
}
