/* Spielgefühl: Vorahnung, Schriftzüge, Konfetti, Holo-Glanz, Gross-Ansicht, Fortschritt und «Neu»-Sticker.
   Die Logik dazu steht in js/spielgefuehl.js, js/oeffnen.js und js/app.js. */

/* ---------- Pack öffnen: Vorahnung ----------
   Ab Rare leuchtet es schon vor dem Aufdecken ruhig in der Farbe der Seltenheit. Die Rückseite selbst
   bewegt sich nicht. Das Leuchten liegt flach HINTER der Karte (.flip::before).
   Weitere Regeln: «Umdrehen» und «Enthüllung ab Rare» weiter unten. */
.flip.ahnung::before {
  content: "";
  position: absolute;
  inset: -3px;
  z-index: -1;
  border-radius: 17px;
  pointer-events: none;
  box-shadow:
    0 0 0 2px var(--ahnung),
    0 0 26px 6px color-mix(in srgb, var(--ahnung) 70%, transparent),
    0 0 70px 14px color-mix(in srgb, var(--ahnung) 35%, transparent);
  opacity: .85;
  transition: opacity .4s ease;
}

/* Schriftzug und Funken dürfen keinen seitlichen Scrollbalken erzeugen */
.opener {
  overflow-x: hidden;
}

/* ---------- Grosser Schriftzug: «Rare!», «Legendary!», «Level 5!» ---------- */
.gf-banner {
  position: absolute;
  left: 50%;
  top: 8%;
  z-index: 30;
  pointer-events: none;
  white-space: nowrap;
  color: #fff;
  font: italic 800 clamp(40px, 12vw, 76px)/1 "Barlow Condensed", sans-serif;
  letter-spacing: .02em;
  text-transform: uppercase;
  -webkit-text-stroke: 2px var(--farbe);
  text-shadow: 0 0 16px var(--farbe), 0 0 42px var(--farbe), 0 4px 0 rgba(0, 0, 0, .45);
  translate: -50% 0;
  animation: gf-banner 1.7s cubic-bezier(.2, .9, .3, 1) forwards;
}

@keyframes gf-banner {
  0% { opacity: 0; scale: 2.4; rotate: -8deg; }
  16% { opacity: 1; scale: .9; rotate: -4deg; }
  26% { scale: 1.05; }
  38% { scale: 1; }
  78% { opacity: 1; translate: -50% -6px; }
  100% { opacity: 0; translate: -50% -34px; }
}

/* ---------- Konfetti über den ganzen Bildschirm ---------- */
.gf-konfetti {
  position: fixed;
  inset: 0;
  z-index: 75;
  overflow: hidden;
  pointer-events: none;
}

.gf-konfetti i {
  position: absolute;
  top: -20px;
  left: var(--x);
  width: 8px;
  height: 14px;
  border-radius: 2px;
  opacity: 0;
  animation: gf-konfetti var(--dauer) cubic-bezier(.3, .6, .5, 1) var(--warte) forwards;
}

.gf-konfetti i:nth-child(3n) {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}

@keyframes gf-konfetti {
  0% { opacity: 1; transform: translate(0, 0) rotate(0); }
  100% { opacity: .9; transform: translate(var(--drift), 110vh) rotate(var(--dreh)); }
}

/* ---------- Übersicht nach dem Öffnen: XP-Balken und Sammlung ---------- */
.op-fortschritt {
  display: grid;
  gap: 6px;
  width: min(100%, 360px);
  padding: 12px 14px;
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 14px;
  background: rgba(255, 255, 255, .06);
  color: #e8eef5;
  animation: gf-hoch .5s var(--ease-out) .2s backwards;
}

.opf-zeile {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font: 600 14px/1.2 "Source Sans 3", sans-serif;
}

.opf-zeile b {
  color: #ffd34d;
  font: 800 18px/1 "Barlow Condensed", sans-serif;
}

.opf-balken {
  display: block;
  height: 10px;
  border-radius: 10px;
  background: rgba(255, 255, 255, .12);
  overflow: hidden;
}

.opf-balken i {
  display: block;
  width: 0;
  height: 100%;
  border-radius: 10px;
  background: linear-gradient(90deg, #ffb800, #ffd34d, #fff3b0);
  box-shadow: 0 0 12px rgba(255, 211, 77, .7);
  transition: width .8s var(--ease-out);
}

/* Sammel-Balken der Bahn: kühles Blaugrün, damit er sich vom goldenen XP-Balken abhebt */
.opf-sammel i {
  background: linear-gradient(90deg, #1fb5a0, #5be3c6);
  box-shadow: 0 0 12px rgba(91, 227, 198, .6);
  transition: width .9s var(--ease-out);
}

.op-fortschritt.aufstieg {
  border-color: #ffd34d;
  box-shadow: 0 0 0 2px rgba(255, 211, 77, .35), 0 0 30px rgba(255, 211, 77, .35);
  animation: gf-aufstieg .6s var(--spring);
}

@keyframes gf-aufstieg {
  40% { scale: 1.06; }
}

@keyframes gf-hoch {
  from { opacity: 0; translate: 0 12px; }
}

/* ---------- Karten neigen sich, Holo-Glanz folgt dem Finger oder der Maus ---------- */
.karten-grid .karte.neigt {
  transform: perspective(800px) rotateX(var(--rx)) rotateY(var(--ry)) translateY(-6px) scale(1.04);
  transition: transform .08s linear, box-shadow .3s ease;
  box-shadow: 0 18px 30px rgba(0, 0, 0, .3);
}

.karte.neigt .k-glanz,
.kv-karte .k-glanz {
  opacity: 1;
  animation: none;
  mix-blend-mode: overlay;
  background: radial-gradient(circle at var(--mx, 40%) var(--my, 25%), rgba(255, 255, 255, .8), rgba(255, 255, 255, 0) 50%);
  background-size: 100% 100%;
}

/* Ab Rare schimmert ein Regenbogen mit */
.karte.neigt:is(.rar-rare, .rar-epic, .rar-mythic, .rar-legendary, .rar-special) .k-glanz,
.kv-karte .karte:is(.rar-rare, .rar-epic, .rar-mythic, .rar-legendary, .rar-special) .k-glanz {
  background:
    radial-gradient(circle at var(--mx, 40%) var(--my, 25%), rgba(255, 255, 255, .85), transparent 45%),
    linear-gradient(115deg, transparent 15%, rgba(255, 80, 160, .45) 35%, rgba(80, 220, 255, .45) 50%, rgba(255, 230, 90, .45) 65%, transparent 85%);
  background-size: 100% 100%, 260% 260%;
  background-position: center, var(--mx, 40%) var(--my, 25%);
}

/* ---------- Gross-Ansicht einer Karte ---------- */
.kv {
  position: fixed;
  inset: 0;
  z-index: 66;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  align-content: center;
  gap: 10px;
  padding: 20px;
  background: radial-gradient(ellipse at 50% 40%, rgba(30, 40, 62, .93), rgba(5, 8, 14, .97));
  animation: viewin .3s var(--ease-out);
}

.kv-buehne {
  max-width: 100%;
  padding: 20px;
  perspective: 1000px;
  touch-action: none;
}

.kv-karte {
  /* nie breiter als der Bildschirm minus Rand (20 px Fenster + 20 px Bühne je Seite) */
  width: min(calc(100vw - 80px), 340px, calc((100dvh - 230px) * 5 / 7));
  aspect-ratio: 5 / 7;
  container-type: inline-size;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transform-style: preserve-3d;
  transition: transform .5s var(--spring);
  animation: gf-kv-rein .55s var(--spring);
}

.kv-karte .karte {
  height: 100%;
  box-shadow: 0 30px 60px rgba(0, 0, 0, .55);
}

.kv-karte.neigt {
  transition: transform .06s linear;
}

/* ohne Finger schwebt die Karte sanft hin und her, der Glanz wandert mit */
.kv-karte.ruht {
  animation: gf-kv-rein .55s var(--spring), gf-kv-schweben 6s ease-in-out .55s infinite;
}

.kv-karte.ruht .k-glanz {
  animation: gf-glanz-wandern 6s ease-in-out .55s infinite;
}

@keyframes gf-kv-rein {
  from { opacity: 0; transform: translateY(40px) rotateY(-25deg) scale(.8); }
}

@keyframes gf-kv-schweben {
  0%, 100% { transform: rotateX(5deg) rotateY(-9deg); }
  50% { transform: rotateX(-4deg) rotateY(9deg); }
}

@keyframes gf-glanz-wandern {
  0%, 100% { background-position: 20% 20%, 10% 10%; }
  50% { background-position: 80% 70%, 90% 90%; }
}

.kv-info {
  max-width: 100%;
  margin: 0;
  overflow-wrap: break-word;
  color: #e8eef5;
  font: 700 16px/1.3 "Barlow Condensed", sans-serif;
  letter-spacing: .04em;
  text-align: center;
}

.kv-tipp {
  margin: 0 0 4px;
  color: #a9b6c4;
  font-size: 13px;
}

/* ---------- Start: Lichtpunkte über den Alpen ---------- */
.gf-funkeln {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}

.gf-funkeln i {
  position: absolute;
  bottom: -10px;
  left: var(--x);
  width: var(--g);
  height: var(--g);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 8px 2px rgba(255, 255, 255, .7);
  opacity: 0;
  animation: gf-aufsteigen var(--dauer) linear var(--warte) infinite;
}

:root[data-theme="dark"] .gf-funkeln i {
  background: #ffe2b0;
  box-shadow: 0 0 8px 2px rgba(255, 190, 120, .6);
}

@keyframes gf-aufsteigen {
  0% { opacity: 0; transform: translate(0, 0); }
  15% { opacity: .85; }
  85% { opacity: .5; }
  100% { opacity: 0; transform: translate(var(--drift), -75vh); }
}

/* ---------- Start: Packs im Karussell ---------- */
/* Fokus auf das Pack in der Mitte: --f kommt aus js/app.js (1 = Mitte, 0 = daneben).
   Nachbarn sind kleiner (--s), dunkler, leicht unscharf und stehen etwas höher, also weiter hinten. */
#v-start .karussell .pk-bild {
  position: relative;
  display: block;
  max-width: 92%;
  line-height: 0;
  transform: translateY(calc((1 - var(--f, 1)) * -22px));
  filter: brightness(calc(.42 + .58 * var(--f, 1))) saturate(calc(.55 + .45 * var(--f, 1))) blur(calc((1 - var(--f, 1)) * 1.2px));
  transition: transform .12s linear, filter .12s linear;
}

#v-start .karussell .pk-bild img {
  max-width: 100%;
}

/* Glanz, der über das Pack in der Mitte streicht (nur in der Form des Packs) */
.karussell .pk-bild::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, .7) 48%, rgba(255, 255, 255, .15) 54%, transparent 62%);
  background-size: 300% 100%;
  mix-blend-mode: overlay;
  -webkit-mask: var(--bild) center / 100% 100% no-repeat;
  mask: var(--bild) center / 100% 100% no-repeat;
  transition: opacity .3s ease;
}

.karussell li.aktiv .pk-bild::after {
  opacity: 1;
  animation: gf-pack-glanz 4.5s ease-in-out infinite;
}

@keyframes gf-pack-glanz {
  0% { background-position: 100% 0; }
  40%, 100% { background-position: 0 0; }
}

/* Packs, die man jetzt öffnen kann, leuchten warm von hinten */
.karussell .pk-bild::before {
  content: "";
  position: absolute;
  inset: -14% -48%;
  z-index: -1;
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  background: radial-gradient(closest-side, rgba(var(--licht), calc(.9 * var(--staerke))), rgba(var(--licht), calc(.45 * var(--staerke))) 50%,
    rgba(var(--licht), calc(.15 * var(--staerke))) 75%, transparent);
  transition: opacity .12s linear;
}

/* Das Leuchten folgt beim Wischen dem Fokus: es blendet am Pack aus, das weggeht, und am neuen ein */
.karussell li.kann .pk-bild::before {
  opacity: var(--f, 0);
  animation: gf-pack-atmen 2.4s ease-in-out infinite;
}

@keyframes gf-pack-atmen {
  50% { scale: 1.08; }
}

/* dazu ein fester Lichtrand in der Form des Packs, ebenfalls nach Fokus (ohne Dauer-Animation, damit nichts ruckelt) */
#v-start .karussell li.kann img {
  filter: drop-shadow(0 0 calc(4px + 8px * var(--staerke)) rgba(var(--licht), calc(.95 * var(--staerke) * var(--f, 0))))
    drop-shadow(0 0 calc(8px + 22px * var(--staerke)) rgba(var(--licht), calc(.6 * var(--staerke) * var(--f, 0))));
}

/* ---------- Podest: Licht und Schatten folgen dem Pack ----------
   --podest kommt aus js/app.js: 1, wenn ein Pack genau auf dem Podest steht, 0 mitten im Wischen.
   Auf der Podest-Oberseite: ein Lichtfleck in der Farbe der Stufe und ein weicher Schatten unter dem Pack. */
#v-start .karussell-bereich > .podest::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 52px;
  border-radius: 50%;
  pointer-events: none;
  opacity: var(--podest, 1);
  background:
    radial-gradient(ellipse 26% 30% at 50% 44%, rgba(0, 0, 0, .38), transparent 75%),
    radial-gradient(ellipse 58% 70% at 50% 46%, rgba(var(--licht, 255, 255, 255), calc(.55 * var(--staerke, .5) + .15)), transparent 72%);
  transition: opacity .15s linear;
}

/* der Lichtkegel über dem Podest wird mit dem Fokus heller oder schwächer */
#v-start .karussell-bereich::before {
  background: conic-gradient(from 170deg at 50% 100%, transparent, rgba(var(--licht, 255, 255, 255), calc(.22 * var(--podest, 1))), transparent 20%,
    transparent 75%, rgba(var(--licht, 255, 255, 255), calc(.16 * var(--podest, 1))), transparent);
}

/* ---------- Licht je Pack-Stufe ----------
   Gold bleibt für Gold-Packs und seltene Funde reserviert: Basis leuchtet weiss, Silver kühl silberblau,
   Gold golden, Platinum prismatisch (schillernder Ring, der sich dreht). --staerke: wie kräftig. */
.karussell li[data-stufe="standard"],
.karussell-bereich[data-stufe="standard"],
#opener[data-stufe="standard"] { --licht: 255, 255, 255; --staerke: .5; }
.karussell li[data-stufe="silber"],
.karussell-bereich[data-stufe="silber"],
#opener[data-stufe="silber"] { --licht: 185, 222, 255; --staerke: .7; }
.karussell li[data-stufe="gold"],
.karussell-bereich[data-stufe="gold"],
#opener[data-stufe="gold"] { --licht: 255, 200, 80; --staerke: .9; }
.karussell li[data-stufe="platin"],
.karussell-bereich[data-stufe="platin"],
#opener[data-stufe="platin"] { --licht: 210, 190, 255; --staerke: 1; }

/* Gold: der Glanz über dem Pack ist golden */
.karussell li[data-stufe="gold"] .pk-bild::after {
  background: linear-gradient(105deg, transparent 38%, rgba(255, 228, 140, .85) 48%, rgba(255, 210, 90, .2) 54%, transparent 62%);
  background-size: 300% 100%;
}

/* Platinum: schillernder Ring hinter dem Pack, der sich langsam dreht */
.karussell li[data-stufe="platin"].kann .pk-bild::before {
  background: conic-gradient(rgba(255, 120, 200, .6), rgba(120, 220, 255, .6), rgba(200, 180, 255, .65), rgba(255, 240, 150, .55), rgba(255, 120, 200, .6));
  filter: blur(14px);
  animation: gf-pack-atmen 2.4s ease-in-out infinite, gf-dreh 6s linear infinite;
}

@keyframes gf-dreh {
  to { rotate: 360deg; }
}

/* Im Pack-Fenster: Lichtschein hinter dem Pack in der Farbe der Stufe */
#opener[data-stufe] .op-stage::before {
  background: radial-gradient(rgba(var(--licht), calc(.45 * var(--staerke))), transparent 65%);
}

#opener[data-stufe="platin"] .op-stage::before {
  background: conic-gradient(rgba(255, 120, 200, .35), rgba(120, 220, 255, .35), rgba(200, 180, 255, .4), rgba(255, 240, 150, .35), rgba(255, 120, 200, .35));
  filter: blur(26px);
  animation: strahl-atmen 4s infinite, gf-dreh 9s linear infinite;
}

#opener[data-stufe] .op-pack img {
  filter: drop-shadow(0 0 calc(10px + 14px * var(--staerke)) rgba(var(--licht), calc(.55 * var(--staerke)))) drop-shadow(0 20px 30px #0008);
}

/* ---------- Pack öffnen als kurze Szene ----------
   Drücken: Pack gibt nach → federt zurück → Naht reisst → Hülle fällt → Kartenstapel erscheint */
.op-stage > * {
  grid-area: 1 / 1;
}

.op-pack img {
  transition: scale .15s ease;
}

.op-pack.op-druck img {
  scale: .94;
}

.op-pack.op-feder {
  animation: gf-feder .18s ease-out;
}

@keyframes gf-feder {
  0% { transform: scale(.94); }
  60% { transform: scale(1.04); }
  100% { transform: scale(1); }
}

/* Naht reisst: kürzer und gespannter als vorher */
.op-pack.op-shake {
  animation-duration: .45s !important;
}

.op-pack.op-shake::after {
  animation-duration: .45s !important;
}

/* Der alte gezeichnete Stapel entfällt: jetzt liegen echte Karten auf dem Stapel */
.op-stage:has(.op-pack.op-shake)::after,
.op-stage:has(.op-pack.op-reisst)::after {
  display: none;
}

/* Kartenstapel: steigt auf, während die Hülle fällt */
.op-einzeln.stapel-rein .op-slot {
  animation: gf-stapel-rein .42s var(--spring);
}

@keyframes gf-stapel-rein {
  from { opacity: 0; transform: translateY(46px) scale(.82); }
}

.op-slot {
  position: relative;
  /* so gross, dass Titel, Zähler, Hinweis und Knopf (zusammen etwa 270 px) immer daneben Platz haben */
  width: min(72vw, 300px, calc((100vh - 270px) * 5 / 7));
  width: min(72vw, 300px, calc((100dvh - 270px) * 5 / 7));
  margin-bottom: 16px; /* Platz für den aufgefächerten Stapel, damit der Hinweis darunter frei bleibt */
  perspective: none; /* keine 3D-Tiefe für den ganzen Bereich: Strahlen, Ring und Funken bleiben flach */
}

/* Beim Aufdecken scrollt das Fenster nicht. Strahlen, Ring und Funken ragen über den Rand hinaus.
   Durfte das Fenster scrollen (niedriger Bildschirm, z. B. das Artefakt in der Claude-App), wuchs und
   schrumpfte der Scrollbereich mit den drehenden Strahlen, und das Bild sprang hin und her. */
.opener.einzeln {
  overflow: hidden;
}

.opener.einzeln .op-status:empty {
  display: none;
}

.op-stapel {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.op-stapel-karte {
  position: absolute;
  inset: 0;
  container-type: inline-size;
  transform: translate(calc(var(--n) * 4px), calc(var(--n) * 5px)) rotate(calc(var(--n) * 1.6deg));
  filter: brightness(calc(1 - var(--n) * .1));
}

.op-stapel-karte > .k-rueck {
  position: absolute;
  inset: 0;
}

/* auf dem Stapel ruhen die Rückseiten (keine Dauer-Animationen) */
.op-stapel-karte * {
  animation: none !important;
}

.op-slot > .flip {
  position: relative;
  z-index: 1;
}

/* erste Karte kommt mit dem Stapel, jede weitere hebt sich kurz vom Stapel ab */
.flip.flip-naechste {
  animation: gf-abheben .22s ease-out;
}

@keyframes gf-abheben {
  from { transform: translateY(5px) scale(.97); }
}

/* ---------- Umdrehen ohne verschachteltes 3D ----------
   Früher drehte sich .flip-innen mit beiden Seiten darin (transform-style: preserve-3d). Auf vielen Handys
   schneidet der Browser darin nichts mehr sauber zu: der grosse Lichteffekt der Rückseite ragte über den
   ganzen Bildschirm und alles sah verzerrt aus. Jetzt dreht sich jede Seite einzeln und flach:
   erst klappt die Rückseite weg (bis 90°), dann klappt die Vorderseite her (von -90°).
   --halb ist die Dauer einer Hälfte: gewöhnliche Karten zügig, ab Rare etwas langsamer. */
.flip {
  --halb: .17s;
}

.flip.ahnung {
  --halb: .28s;
}

.flip .flip-innen,
.flip.offen .flip-innen {
  transform: none;
  transform-style: flat;
  transition: none;
  animation: none;
}

.flip .flip-rueck {
  transform: perspective(1000px) rotateY(0deg);
  transition: transform var(--halb) ease-in;
}

.flip.offen .flip-rueck {
  transform: perspective(1000px) rotateY(90deg);
}

.flip .flip-vorne {
  transform: perspective(1000px) rotateY(-90deg);
  transition: transform var(--halb) ease-out var(--halb);
}

.flip.offen .flip-vorne {
  transform: perspective(1000px) rotateY(0deg);
}

/* Rückseite im Pack-Fenster ganz ruhig: kein drehender Lichtkeil (er war 2,2-mal so gross wie die Karte) */
.flip .k-rueck-licht,
.op-stapel .k-rueck-licht {
  display: none;
}

.flip .k-rueck-r {
  animation: none;
}

/* ---------- Enthüllung ab Rare ----------
   Heben, Zittern und «Pop» macht die Hülle .flip in 2D; Leuchten, Strahlen, Ring und Funken liegen
   flach hinter der Karte. So bleibt das Bild auf dem Handy scharf und unverzerrt. */

/* Spannung vor einer seltenen Karte: die Hülle hebt sich und zittert, das Leuchten wird voll.
   Beim Umdrehen sinkt sie weich zurück (Übergang statt Sprung). */
.op-slot > .flip {
  transition: translate .35s ease-out, scale .35s ease-out;
}

.flip.spannung {
  translate: 0 -7px;
  scale: 1.04;
  animation: gf-spannung-zittern .1s linear .15s infinite;
}

@keyframes gf-spannung-zittern {
  0%, 100% { rotate: 0deg; }
  25% { rotate: -.5deg; }
  75% { rotate: .5deg; }
}

.flip.spannung::before {
  animation: none;
  opacity: 1;
}

.flip.spannung .k-rueck {
  filter: none;
}

/* Ab Epic atmet das Leuchten um die Rückseite schon vor dem Tippen (nur die Helligkeit, die Karte bleibt ruhig) */
.flip.ahnung-hoch:not(.spannung):not(.offen)::before {
  animation: gf-ahnung-atmen 1.6s ease-in-out infinite;
}

@keyframes gf-ahnung-atmen {
  0%, 100% { opacity: .5; }
  50% { opacity: 1; }
}

/* ---------- Aufladen ab Epic ----------
   Nach dem Tippen hebt sich die Karte höher und zittert immer stärker (nur flach, 2D), das Leuchten wächst,
   von hinten kommt ein Lichtball (.fx-glut), Lichtpunkte fliegen zur Karte (.fx-sog), alles andere tritt zurück.
   Dauer: --laden aus js/oeffnen.js (AUFLADEN). */
.flip.spannung.laedt {
  translate: 0 -12px;
  scale: 1.07;
  transition: translate .45s ease-out, scale var(--laden) cubic-bezier(.4, 0, .9, .6);
  animation: gf-laden-zittern var(--laden) linear both;
}

/* --wucht aus js/oeffnen.js (WUCHT): je seltener, desto stärker */
@keyframes gf-laden-zittern {
  0% { rotate: 0deg; }
  10% { rotate: calc(-.3deg * var(--wucht, 1)); }
  20% { rotate: calc(.4deg * var(--wucht, 1)); }
  29% { rotate: calc(-.5deg * var(--wucht, 1)); }
  37% { rotate: calc(.6deg * var(--wucht, 1)); }
  44% { rotate: calc(-.8deg * var(--wucht, 1)); }
  51% { rotate: calc(.9deg * var(--wucht, 1)); }
  57% { rotate: calc(-1.1deg * var(--wucht, 1)); }
  63% { rotate: calc(1.2deg * var(--wucht, 1)); }
  68% { rotate: calc(-1.4deg * var(--wucht, 1)); }
  73% { rotate: calc(1.5deg * var(--wucht, 1)); }
  77% { rotate: calc(-1.7deg * var(--wucht, 1)); }
  81% { rotate: calc(1.8deg * var(--wucht, 1)); }
  85% { rotate: calc(-2deg * var(--wucht, 1)); }
  88% { rotate: calc(2deg * var(--wucht, 1)); }
  91% { rotate: calc(-2deg * var(--wucht, 1)); }
  94% { rotate: calc(1.6deg * var(--wucht, 1)); }
  97% { rotate: calc(-1deg * var(--wucht, 1)); }
  100% { rotate: 0deg; }
}

.flip.laedt::before {
  opacity: 1;
  animation: gf-laden-leuchten var(--laden) ease-in both;
}

@keyframes gf-laden-leuchten {
  to { scale: 1.05; }
}

.opener :is(.op-titel, .op-zaehler, .op-hilfe, .op-knoepfe) {
  transition: opacity .35s ease;
}

.opener.fx-laedt :is(.op-titel, .op-zaehler, .op-hilfe, .op-knoepfe) {
  opacity: .15;
}

/* Lichtball hinter der Karte: wächst beim Aufladen, bleibt nach dem Aufdecken und atmet */
.fx-glut {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 0;
  width: 240%;
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(closest-side, var(--farbe) 35%, transparent);
  opacity: 0;
  scale: .45;
  animation: fx-glut-an var(--laden, .6s) cubic-bezier(.3, .6, .6, 1) forwards;
}

@keyframes fx-glut-an {
  to { opacity: .85; scale: 1; }
}

.fx-glut.da {
  opacity: .85;
  scale: 1;
  animation: fx-glut-atmen 2.4s ease-in-out infinite;
}

@keyframes fx-glut-atmen {
  50% { opacity: .5; scale: .92; }
}

/* Special: Lichtflecken in allen Farben, die langsam um die Karte kreisen (die Drehung bleibt an zweiter Stelle) */
.fx-glut.bunt {
  /* jeder Fleck läuft aus, bevor er den Rand des Kreises erreicht (Mitte höchstens 30 % + Radius 20 %) */
  background:
    radial-gradient(20% 20% at 28% 32%, #ff5f6d, transparent),
    radial-gradient(20% 20% at 72% 32%, #ffc371, transparent),
    radial-gradient(20% 20% at 76% 64%, #47e891, transparent),
    radial-gradient(20% 20% at 50% 80%, #4face0, transparent),
    radial-gradient(20% 20% at 24% 64%, #b06ab3, transparent);
  animation: fx-glut-an var(--laden, .6s) cubic-bezier(.3, .6, .6, 1) forwards, fx-glut-dreh 5s linear infinite;
}

.fx-glut.bunt.da {
  animation: fx-glut-atmen 2.4s ease-in-out infinite, fx-glut-dreh 5s linear infinite;
}

@keyframes fx-glut-dreh {
  to { rotate: 360deg; }
}

/* Lichtpunkte fliegen von aussen zur Mitte und verschwinden hinter der Karte */
.fx-sog {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 0;
  width: 6px;
  height: 6px;
  margin: -3px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 6px 2px var(--farbe);
  pointer-events: none;
  opacity: 0;
  animation: fx-sog .6s cubic-bezier(.5, 0, .9, .5) var(--warte) forwards;
}

@keyframes fx-sog {
  0% { opacity: 0; transform: translate(var(--x), var(--y)) scale(.5); }
  25% { opacity: 1; }
  100% { opacity: .9; transform: translate(0, 0) scale(1.2); }
}

/* Rare: nach dem Umdrehen geht das Vorahnungs-Leuchten aus */
.flip.ahnung.offen:not(.selten)::before {
  animation: none;
  opacity: 0;
}

/* Ab Epic: die Hülle macht einen kräftigen «Pop», sobald die Vorderseite da ist
   (startet dort, wo das Aufladen aufgehört hat, darum kein Sprung) */
.flip.selten.offen {
  animation: gf-enthuellt .9s ease-out both;
}

@keyframes gf-enthuellt {
  0%, 30% { translate: 0 -12px; scale: 1.07; }
  45% { translate: 0 -6px; scale: 1.13; }
  100% { translate: 0 0; scale: 1; }
}

/* Ab Epic: die Vorderseite kommt weiss aus dem Licht, danach streicht ein Glanz einmal darüber */
.flip.selten.offen .karte::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, .75) 50%, transparent 62%) 100% 0 / 250% 100% no-repeat;
  animation: gf-karte-blitz .5s ease-out var(--halb) both, gf-karte-streif .9s ease-in-out calc(var(--halb) + .3s) both;
}

@keyframes gf-karte-blitz {
  from { background-color: #fff; }
  to { background-color: rgba(255, 255, 255, 0); }
}

@keyframes gf-karte-streif {
  from { background-position: 100% 0; }
  to { background-position: 0 0; }
}

/* neue Karten (unter Epic): kleiner Hüpfer der Hülle, nachdem sie zurückgesunken ist */
.flip.offen.neu:not(.selten) {
  animation: gf-neu-huepfer .4s ease-out .3s;
}

@keyframes gf-neu-huepfer {
  0% { scale: 1; }
  45% { scale: 1.03; }
  100% { scale: 1; }
}

/* Ab Epic: pulsierendes Leuchten in der Farbe der Seltenheit (--ahnung, aus js/oeffnen.js), eng um die Karte.
   Ersetzt die frühere drehende, unscharfe Oval-Aura, die den Bildschirm verzerrt aussehen liess. */
.flip.selten.offen::before {
  inset: -3px;
  border-radius: 17px;
  background: none;
  filter: none;
  box-shadow:
    0 0 0 2px rgba(255, 255, 255, .9),
    0 0 30px 8px color-mix(in srgb, var(--ahnung, #fff) 70%, transparent),
    0 0 90px 24px color-mix(in srgb, var(--ahnung, #fff) 35%, transparent);
  opacity: 1;
  animation: gf-aura-puls 2.4s ease-in-out infinite;
}

@keyframes gf-aura-puls {
  0%, 100% { opacity: .7; }
  50% { opacity: 1; }
}

/* auf der Karte selbst kein grosses Leuchten (das kommt von hinten) */
.flip.selten .karte,
.flip.selten.offen .karte {
  box-shadow: 0 6px 16px rgba(0, 0, 0, .35);
}

/* Glanz ohne Mischmodus: «mix-blend-mode» stört auf Handys das 3D-Umdrehen */
.flip .karte .k-glanz {
  mix-blend-mode: normal;
  opacity: .45;
}

/* Special: nur der Regenbogen-Rahmen läuft, kein Farb-Filter über die ganze Karte */
.flip.offen.special .karte {
  animation: schillern 6s linear infinite;
}

/* Lichtstrahlen ab Epic: ein runder Strahlenkranz hinter der Karte, dreht sich langsam.
   Gezeichnet als SVG (js/oeffnen.js, strahlenSvg): jeder Strahl wird nach aussen von selbst durchsichtig.
   Früher eine CSS-Maske auf einem grossen Feld; manche Handys ignorierten die Maske und zeigten ein
   riesiges eckiges Strahlenfeld. Nur «transform» und «opacity», damit es überall gleich läuft. */
.fx-strahlen {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 0;
  width: 200%;
  height: auto;
  aspect-ratio: 1;
  translate: -50% -50%;
  pointer-events: none;
  opacity: 0;
  animation: fx-strahlen-an .6s ease-out .1s forwards, fx-strahlen-dreh 20s linear infinite;
}

@keyframes fx-strahlen-an {
  to { opacity: 1; }
}

@keyframes fx-strahlen-dreh {
  to { transform: rotate(360deg); }
}

/* Ab Mythic: beim Aufladen brechen die Strahlen schon schwach hervor, beim Aufdecken werden sie voll.
   Die Drehung bleibt an zweiter Stelle, so läuft sie beim Wechsel ohne Sprung weiter. */
.fx-strahlen.vorab {
  animation: fx-strahlen-vorab var(--laden, 1s) linear forwards, fx-strahlen-dreh 20s linear infinite;
}

.fx-strahlen.vorab.voll {
  animation: fx-strahlen-voll .5s ease-out forwards, fx-strahlen-dreh 20s linear infinite;
}

@keyframes fx-strahlen-vorab {
  from { opacity: 0; scale: .6; }
  to { opacity: .6; scale: .9; }
}

@keyframes fx-strahlen-voll {
  from { opacity: .6; scale: .9; }
  to { opacity: 1; scale: 1; }
}

/* Leuchtring und Funken: der Ring läuft hinter der Karte durch, nicht quer über das Bild */
.op-slot .fx-ring {
  z-index: 0;
  animation-fill-mode: both; /* der zweite Ring ab Legendary wartet unsichtbar */
}

/* Blitz ab Mythic etwas sanfter */
.opener.fx-blitz::after {
  animation: gf-blitz-sanft .7s ease-out forwards;
}

@keyframes gf-blitz-sanft {
  0% { opacity: .55; }
  100% { opacity: 0; }
}

/* ---------- Nach «Fertig»: alle Karten in einer Reihe, dann einzeln ins Album (Bewegung in js/spielgefuehl.js) ---------- */
.gf-reihe {
  position: fixed;
  z-index: 80;
  container-type: inline-size;
  transform-origin: 0 0;
  pointer-events: none;
  filter: drop-shadow(0 8px 14px rgba(0, 0, 0, .35));
}

.gf-reihe .karte {
  height: 100%;
}

.gf-reihe-schleier {
  position: fixed;
  inset: 0;
  z-index: 79;
  opacity: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 42%, rgba(5, 10, 20, .55), rgba(5, 10, 20, .25) 70%);
}

/* neue Karten tragen in der Reihe einen kleinen «Neu»-Punkt */
.gf-reihe.neu::after {
  content: "Neu";
  position: absolute;
  top: -8px;
  left: 50%;
  translate: -50% 0;
  padding: 2px 6px;
  border-radius: 99px;
  background: #d71920;
  color: #fff;
  font: 800 10px/1 "Barlow Condensed", sans-serif;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.tabbar a.gf-empfang {
  animation: gf-empfang .5s var(--spring);
}

@keyframes gf-empfang {
  35% { scale: 1.28; }
}

/* Badge beim Warten: ein Balken füllt sich bis zum nächsten Gratis-Pack */
#v-start .badge.wartet {
  padding-bottom: 15px;
}

#v-start .badge.wartet::after {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 6px;
  height: 3px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent) var(--fortschritt, 0%), rgba(0, 0, 0, .14) 0);
}

/* ---------- Album: Hintergrund wie eine Bahnkarte über verschneiten Alpen ----------
   Oben neblige, helle Alpen (das Alpenbild entsättigt, aufgehellt und nach unten ausgeblendet),
   darüber ein feines Bahnnetz am Rand (assets/welt/bahnnetz.svg). Im schwarzen Design als Nachtversion. */
#v-album {
  position: relative;
  isolation: isolate;
}

#v-album::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: -2;
  height: min(75vh, 620px);
  pointer-events: none;
  background: url('../assets/welt/alpenpanorama.png') center 35% / cover no-repeat;
  filter: saturate(.3) brightness(1.38) contrast(.62);
  opacity: .62;
  -webkit-mask-image: linear-gradient(to bottom, #000, rgba(0, 0, 0, .85) 40%, transparent);
  mask-image: linear-gradient(to bottom, #000, rgba(0, 0, 0, .85) 40%, transparent);
}

#v-album::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: url('../assets/welt/bahnnetz.svg') center top / 100% auto no-repeat;
}

:root[data-theme="dark"] #v-album::before {
  filter: saturate(.45) brightness(.42) contrast(1.05);
  opacity: .9;
}

:root[data-theme="dark"] #v-album::after {
  filter: invert(1) hue-rotate(180deg) brightness(.85);
  opacity: .45;
}

/* Computer: das Netz nicht riesig aufblasen */
@media (min-width: 1100px) {
  #v-album::after {
    background-size: 900px auto;
  }
}

/* ---------- Album: Fortschritt der Sammlung ---------- */
.sam-fortschritt {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 14px;
}

.sam-balken {
  flex: 1;
  height: 12px;
  border-radius: 12px;
  background: var(--surface-2);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .18);
  overflow: hidden;
}

.sam-balken i {
  position: relative;
  display: block;
  width: 0;
  height: 100%;
  border-radius: 12px;
  background: linear-gradient(90deg, #ffb800, #ff7a00 55%, var(--accent));
  overflow: hidden;
  transition: width 1s var(--ease-out);
}

.sam-balken i::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, .6) 50%, transparent 70%);
  background-size: 250% 100%;
  animation: glanz 2.8s ease-in-out infinite;
}

#st-prozent {
  min-width: 48px;
  color: var(--fg);
  font: 800 20px/1 "Barlow Condensed", sans-serif;
  text-align: right;
}

/* Kategorien: dünner Balken unten zeigt, wie viel schon entdeckt ist */
.rar {
  position: relative;
  overflow: hidden;
}

.rar-balken {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: rgba(0, 0, 0, .08);
}

.rar-balken i {
  display: block;
  height: 100%;
  background: var(--rar);
  box-shadow: 0 0 6px var(--rar);
}

/* Neu gefundene Karten: Sticker und roter Rand, bis man das Album verlässt */
.karten-grid li.ist-neu {
  position: relative;
}

.karten-grid li.ist-neu::before {
  content: "Neu";
  position: absolute;
  top: 3px;
  left: 50%;
  translate: -50% 0;
  z-index: 6;
  padding: 4px 9px;
  border-radius: 99px;
  background: linear-gradient(#ff4251, #c3101e);
  color: #fff;
  font: 800 13px/1 "Barlow Condensed", sans-serif;
  letter-spacing: .1em;
  text-transform: uppercase;
  box-shadow: 0 3px 10px rgba(0, 0, 0, .35);
  pointer-events: none;
  animation: gf-neu-hops 1.6s ease-in-out infinite;
}

.karten-grid li.ist-neu .karte {
  box-shadow: 0 0 0 2px #ff4251, 0 0 18px rgba(255, 66, 81, .45);
}

@keyframes gf-neu-hops {
  50% { scale: 1.12; }
}

/* ---------- Münzen fliegen zur Münz-Anzeige oben ---------- */
.gf-flugmuenze {
  position: fixed;
  z-index: 80;
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  animation: gf-flug .8s cubic-bezier(.5, 0, .75, .4) forwards;
}

@keyframes gf-flug {
  0% { opacity: 0; transform: translate(0, 0) scale(.6); }
  15% { opacity: 1; transform: translate(calc(var(--dx) * .08), var(--bogen)) scale(1.25); }
  100% { opacity: .9; transform: translate(var(--dx), var(--dy)) scale(.7); }
}

/* Gesammelte Karten im Album lassen sich antippen */
.karten-grid .karte:not(.fehlt) {
  cursor: zoom-in;
}
