/* ══════════════════════════════════════════════════════════════════
   ui.css — Grundlagen und die 3D-Karte.

   Farben und Bildsprache folgen ogerteam.de und meinquest.de,
   Aufbau und Bedienung folgen Hearthstone: räumliche Karten,
   Ziehen auf das Feld, Querformat.
   ══════════════════════════════════════════════════════════════════ */

/* Freckle Face trägt alles Hervorgehobene: Knöpfe, Kartennamen, Werte.
   Bezogen über npm (@fontsource), auf die tatsächlich benutzten Zeichen
   zusammengestrichen — 25 KB statt 40. */
@font-face{font-family:'Freckle Face';src:url('../assets/fonts/FreckleFace.woff2') format('woff2');
  font-weight:400;font-display:swap;}
@font-face{font-family:'Bangers';src:url('../assets/fonts/Bangers.woff2') format('woff2');
  font-weight:400;font-display:block;}
@font-face{font-family:'Grandstander';src:url('../assets/fonts/Grandstander.woff2') format('woff2');
  font-weight:100 900;font-display:swap;}

:root{
  --parch:#eedcab;   --parch-hi:#f8eecb;  --parch-sh:#d9c391;
  --tan:#c7a276;     --wood:#3e3327;      --wood-dk:#2b2319;  --wood-in:#221b13;
  --ink:#14100b;     --red:#9d2621;       --red-dk:#6d1714;   --red-hi:#c4382f;
  /* Gegenstück zu --red-hi für wohlwollende Ziele. Die Helligkeit ist
     nachgerechnet, nicht geschätzt: 0,155 gegen 0,148 bei --red-hi. Ein
     naheliegenderes Grün (#3faa52) lag bei 0,304 und damit doppelt so
     hell — es hätte lauter gewirkt als das Rot, obwohl beide dasselbe
     sagen sollen, nur mit anderem Vorzeichen. */
  --gruen-hi:#2a7d3a;
  --gold:#e0b352;    --gold-hi:#f7d878;   --gold-dk:#9a6f1c;
  --mana:#3fa9dd;    --mana-hi:#8fe2ff;   --mana-dk:#17527a;

  --f-licht:#e0b352; --f-orden:#4a7fb5;   --f-schatten:#8b56aa;

  --display:'Freckle Face','Bangers',Impact,fantasy;
  --ui:'Grandstander',system-ui,-apple-system,sans-serif;
}

*,*::before,*::after{box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
/* Nur Seiten mit Spielbühne werden zentriert und festgehalten — das
   Kompendium ist eine scrollende Seite und darf davon nichts abbekommen. */
/* ─── Der Zeiger ──────────────────────────────────────────────────
   Ein Panzerhandschuh mit ausgestrecktem Finger, leicht nach links
   gedreht (15 Grad). Überall derselbe — auch auf Knöpfen, Karten und
   beim Ziehen, wo sonst Hand und Faust des Browsers erschienen; ein
   Spiel soll nicht mitten in der Bewegung den Zeiger wechseln.
   `!important`, weil `.diener{cursor:grab}` und Verwandte sonst
   gewännen. Die Spitze des Fingers ist der heiße Punkt (8/1 bei 64
   Punkten, 4/1 bei 33); die kleine Fassung ist der Rückfall für
   Browser, die 64 Punkte nicht mögen. Auf dem Telefon gibt es keinen
   Zeiger, dort kostet das nichts. */
*,*::before,*::after{
  cursor:url("../assets/zeiger.png") 8 1,url("../assets/zeiger-klein.png") 4 1,auto !important;
}

body.buehnenseite{display:flex;align-items:center;justify-content:center;}
html:has(body.buehnenseite),body.buehnenseite{height:100%;overflow:hidden;}

html,body{margin:0;padding:0;
  user-select:none;-webkit-user-select:none;}
/* Auf dem Brett darf keine Geste des Browsers dazwischenfunken: das
   Ziehen einer Karte ist selbst eine. Das steht hier und nicht mehr als
   user-scalable=no im Viewport — die Kopfzeile hätte das Zoomen auf der
   ganzen Seite gesperrt, auch im Kompendium und im Menü, wo es niemanden
   stört und Sehbehinderten hilft. (iOS übergeht user-scalable=no seit
   Fassung 10 ohnehin; wirksam war allein diese Zeile.) */
body.buehnenseite{overscroll-behavior:none;touch-action:none;}
/* Auf den übrigen Seiten (Kompendium, Menü) bleibt das Zusammenziehen mit
   zwei Fingern erlaubt — nur der Doppeltipp fällt weg. Genau dafür gibt
   es `manipulation`. */
body:not(.buehnenseite){touch-action:manipulation;}
body{
  font-family:var(--ui);font-weight:500;color:var(--parch);
  background:#0d0a07;

  -webkit-text-size-adjust:100%;
}
.display{font-family:var(--display);font-weight:400;letter-spacing:.01em;}
/* Bangers setzt die Umlautpunkte über die Versalhöhe — überall dort,
   wo beschnitten wird, braucht der Text Polsterung nach oben. */
.display{padding-top:.06em;}

/* ═══ DIE KARTE ═══════════════════════════════════════════════════
   Ein Stapel aus Ebenen mit echtem translateZ: beim Kippen entsteht
   Parallaxe zwischen Bild, Rahmen und Steinen.

   Alle Innenmaße sind prozentual, die Schriftgrößen in em. Dadurch
   genügt es, je Einsatzort Breite, Höhe und font-size zu setzen —
   die Karte skaliert dann als Ganzes stimmig mit.
   ══════════════════════════════════════════════════════════════ */
.karte{
  position:absolute;width:116px;height:162px;font-size:10px;
  /* Die Tiefenachse gehört der Karte selbst, nicht der Hand: läge
     preserve-3d auf dem Elternteil, würde der Browser die Karten
     räumlich sortieren und z-index ignorieren — die angehobene Karte
     verschwände hinter ihrer Nachbarin. */
  perspective:640px;
  /* Kein will-change: der Browser würde die Karte einmal in ihrer kleinen
     Größe rastern und die Textur beim Vergrößern hochskalieren — genau
     das machte die angehobene Karte klotzig. Nur die gezogene Karte
     bekommt die Beschleunigung, dort ändert sich nichts an der Größe. */
  cursor:grab;
}
.karte .koerper{position:absolute;inset:0;transform-style:preserve-3d;
  /* Die Neigung folgt dem Zeiger fast unmittelbar — sie ist eine
     Rückmeldung, keine Bewegung für sich. */
  transition:transform .08s ease-out;}

.karte .rahmen{
  position:absolute;inset:0;border-radius:9px;
  background:linear-gradient(160deg,var(--parch-hi) 0%,var(--parch) 42%,var(--parch-sh) 100%);
  border:2.5px solid var(--ink);
  box-shadow:0 0 0 1px rgba(255,255,255,.28) inset;
}
.karte .rahmen::after{
  content:"";position:absolute;left:6%;right:6%;bottom:3%;height:2.5px;
  border-radius:2px;background:var(--fc,transparent);
}
.karte[data-f="licht"]{--fc:var(--f-licht)}
.karte[data-f="orden"]{--fc:var(--f-orden)}
.karte[data-f="schatten"]{--fc:var(--f-schatten)}

/* Bild, Band und Text sind aufeinander abgestimmt — wer eines
   verschiebt, muss die anderen mitdenken.

   Der Beschreibungstext klebte am Namensband: zwischen Bandunterkante
   und Textbeginn lag knapp **ein Punkt**. Ihn einfach nach unten zu
   schieben hätte nicht gereicht, weil darunter schon die Werte-Steine
   warten — es wäre Platz für weniger als drei Zeilen geblieben, und
   dreizeilige Karten hätten Auslassungspunkte bekommen.

   Deshalb rücken Bild und Band um gut drei Prozent nach oben. Der Text
   bekommt damit **4,6 Punkte Luft** nach oben (eine halbe Zeilenhöhe,
   sichtbar als Abstand) und behält gleichzeitig Platz für 3,4 statt 2,8
   Zeilen; anderthalb Prozent bleiben als Abstand zu den Steinen
   stehen, damit Unterlängen nicht daran stoßen. Das Bild verliert dabei
   3,5 Prozent Höhe, was auf 185 Punkten
   Karte gut sechs Punkte sind — an einem Motiv, das ohnehin
   beschnitten wird, fällt das nicht auf. */
.karte .bild{
  position:absolute;left:6%;right:6%;top:4.3%;height:49.5%;
  border:2px solid var(--ink);border-radius:5px;overflow:hidden;background:#fff;
  transform:translateZ(4px);
}
.karte .bild img{width:100%;height:100%;object-fit:cover;object-position:50% 45%;
  display:block;image-rendering:auto;}

.karte .band{
  position:absolute;left:3.5%;right:3.5%;top:55.5%;height:10.5%;
  transform:translateZ(8px);
  /* Dunkler als zuvor, und zwar aus einem messbaren Grund: der helle
     Name stand auf dem alten Band bei einem Kontrast von **2,0 : 1**
     (oben) bis 2,9 : 1 (unten). Lesbar wird Schrift ab 3 : 1, und das
     auch nur, wenn sie groß ist. Mit diesem Verlauf sind es 5,3 : 1 bis
     6,4 : 1 — der Name hebt sich ab, ohne dass das Band die Karte
     dominiert. */
  background:linear-gradient(#7a5c39,#6b5032);
  border:2px solid var(--ink);border-radius:4px;
  display:grid;place-items:center;overflow:hidden;
}
.karte .band span{
  font-family:var(--display);font-size:1em;
  color:var(--parch-hi);
  white-space:nowrap;max-width:94%;overflow:hidden;text-overflow:ellipsis;
  /* Der Name saß am unteren Rand des Bandes statt in der Mitte.

     Zwei Dinge zogen ihn hinunter. Erstens `padding-top:.3em` — ein
     Ausgleich für die Schrift „Bangers", deren Zeichen hoch im
     Zeilenkasten sitzen; er war aber zu großzügig und verschob mehr,
     als er ausglich. Zweitens `line-height:1` zusammen mit
     `overflow:hidden`: bei einer Zeilenhöhe genau in Schriftgröße
     ragen Ober- und Unterlängen aus dem Kasten, und `place-items:center`
     zentriert dann diesen zu kleinen Kasten statt der sichtbaren
     Schrift.

     Jetzt trägt die Zeilenhöhe die Schrift (1.15) und der Ausgleich ist
     auf ein Zehntel geschrumpft — gerade genug für die Eigenart der
     Schriftart, nicht mehr. */
  line-height:1.15;padding-top:.1em;
  /* Eine dünne Kontur trägt den Namen über jeden Untergrund.

     Sie ist als vier Schatten gesetzt und nicht als
     `-webkit-text-stroke`: der Strich läge dort **mittig** auf der
     Kontur der Zeichen und fräße von der ohnehin schmalen Schrift die
     Hälfte weg. Vier versetzte Schatten legen sich außen an und lassen
     die Buchstabenform unangetastet. Der fünfte, weichere darunter gibt
     Tiefe. */
  /* Vier scharfe Versätze — **kein weicher Schatten**.

     Der fünfte, weiche (`0 2px 3px`) war der teuerste von allen: ein
     Weichzeichner zwingt den Browser, den Text eigens zu rastern, und
     das Namensband liegt in einem `preserve-3d`-Zusammenhang mit
     `translateZ(8px)`. Dort wird gerasterter Inhalt einmal als Textur
     abgelegt und danach transformiert — unter `zoom` in der falschen
     Auflösung. Genau daher kam die Verpixelung, und bei 133 Karten im
     Kompendium zugleich auch der Leistungseinbruch.

     Die vier scharfen Versätze haben keinen Weichzeichner und kosten
     entsprechend wenig. Für die Lesbarkeit reichen sie: das Namensband
     ist inzwischen ohnehin dunkel genug (5,3 : 1 statt 2,0 : 1). */
  text-shadow:
    -1px 0 0 var(--ink),  1px 0 0 var(--ink),
     0 -1px 0 var(--ink),  0 1px 0 var(--ink);
}

/* Der Text endet oberhalb der Steine, damit nichts angeschnitten wird.
   text-decoration:none ist Absicht: manche Erweiterungen setzen ihre
   Markierungen als Unterstreichung und lassen sich damit aussperren. */
.karte .text{
  position:absolute;left:9%;right:9%;top:68.5%;height:14%;
  transform:translateZ(6px);
  font-size:.64em;line-height:1.16;text-align:center;color:#3a2c1c;
  /* Sauber nach drei Zeilen mit Auslassungspunkten enden statt
     mitten im Wort abzureißen. */
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
  text-decoration:none;-webkit-text-decoration-skip:none;
}
.karte .text b,.karte .band span{text-decoration:none;}
.karte .text b{color:var(--red-dk);}

/* ─── Werte-Steine ────────────────────────────────────────────────
   Die Form trägt die Bedeutung: goldene Klinge = Angriff,
   rotes Herz = Leben, blaue Kugel = Kosten. Dadurch bleiben die
   Werte auch klein, gedämpft und ohne Farbsehen unterscheidbar.
   Gezeichnet als SVG, weil clip-path einen Stapelkontext erzeugt und
   eine Kontur mit negativem z-index dort über der Füllung landet.
   ══════════════════════════════════════════════════════════════ */
.karte .stein{position:absolute;display:grid;place-items:center;}
.karte .stein svg{position:absolute;inset:0;width:100%;height:100%;
  overflow:visible;stroke:var(--ink);stroke-width:3;stroke-linejoin:round;
  filter:drop-shadow(0 2px 3px rgba(0,0,0,.55));}
.karte .stein span{
  position:relative;z-index:2;transform:translateY(-6%);
  font-family:var(--display);line-height:1;padding-top:.12em;
  color:#fff;text-shadow:0 1.5px 0 rgba(0,0,0,.6);
}

.karte .kosten{width:29%;aspect-ratio:40/44;left:-5%;top:-5%;
  transform:translateZ(16px);}
.karte .kosten svg path{fill:url(#manaVerlauf);}
.karte .kosten span{font-size:1.7em;transform:translateY(-4%);}

.karte .angriff,.karte .leben{width:25%;aspect-ratio:40/44;bottom:0;
  transform:translateZ(14px);}
.karte .angriff span,.karte .leben span{font-size:1.45em;}
.karte .angriff{left:-3%;}
.karte .leben  {right:-3%;}
.karte .angriff svg path{fill:url(#goldVerlauf);}
.karte .leben   svg path{fill:url(#blutVerlauf);}
.karte .angriff.hoch svg path{fill:url(#gruenVerlauf);}
.karte .leben.wund span{color:#ffe4e0;}

/* Zauberkarten haben keinen Körper auf dem Feld — also auch keine
   Kampfwerte. Der frei werdende Platz gehört dem Wirkungstext. */
.karte[data-art="zauber"] .angriff,
.karte[data-art="zauber"] .leben{display:none;}
.karte[data-art="zauber"] .text{top:69.6%;height:26%;font-size:.72em;
  -webkit-line-clamp:5;}
.karte[data-art="zauber"] .rahmen{
  background:linear-gradient(160deg,#f3ecd6 0%,#e6dcc2 42%,#cfc1a0 100%);}
.karte[data-art="zauber"] .rahmen::after{
  background:linear-gradient(90deg,var(--mana),#8b56aa);}
.karte[data-art="zauber"] .band{
  background:linear-gradient(#8f7bb0,#5d4a7d);}

/* Geheimnisse: eigene Farbgebung, damit man sie in der Hand sofort
   von Dienern und Zaubern unterscheidet. */
.karte[data-art="geheimnis"] .angriff,
.karte[data-art="geheimnis"] .leben{display:none;}
.karte[data-art="geheimnis"] .text{top:69.6%;height:26%;font-size:.68em;
  -webkit-line-clamp:5;}
.karte[data-art="geheimnis"] .rahmen{
  background:linear-gradient(160deg,#efe4cc 0%,#ddd0b0 42%,#c3b28c 100%);}
.karte[data-art="geheimnis"] .rahmen::after{
  background:linear-gradient(90deg,#b8452f,#e0b352);}
.karte[data-art="geheimnis"] .band{
  background:linear-gradient(#b0703c,#7a4520);}

/* Glanzschleier — wandert beim Kippen über die Karte */
.karte .glanz{
  position:absolute;inset:0;border-radius:9px;pointer-events:none;
  transform:translateZ(20px);
  background:linear-gradient(105deg,transparent 34%,
    rgba(255,255,255,.42) 47%,rgba(255,255,255,.06) 56%,transparent 66%);
  background-size:260% 260%;background-position:var(--glanz,50% 50%);
  opacity:0;transition:opacity .18s;mix-blend-mode:screen;
}
.karte.angehoben .glanz{opacity:1;}

.karte .marken{position:absolute;top:4%;right:4%;display:flex;flex-direction:column;
  gap:3px;transform:translateZ(18px);}
/* Die Marken tragen jetzt ihre Bedeutung.

   Vorher war jede ein gleicher Punkt in Fraktionsfarbe — bei einer
   Karte mit Göttlichem Schild sah man also einen Punkt, der nichts
   sagte. Der Wortlaut steht zwar im Textfeld, aber auf dem Brett gibt
   es kein Textfeld, und beim schnellen Überfliegen liest man ohnehin
   die Symbole zuerst. Jede Marke hat nun ihre eigene Farbe und einen
   Namen im title. */
/* Ohne weichen Schatten: die Marken sind winzig, der Weichzeichner war
   darauf ohnehin kaum zu sehen — kostete aber auf jeder Karte einen
   eigenen Rastervorgang. Die dunkle Kontur trennt sie auch so vom
   Untergrund. */
.karte .marken i{width:.72em;height:.72em;border-radius:50%;
  background:var(--fc,var(--ink));border:1.5px solid var(--ink);}
.karte .marken i[data-kw="schild"]{
  background:radial-gradient(circle at 34% 30%,#fff8dc,var(--gold-hi) 55%,var(--gold-dk));}
.karte .marken i[data-kw="spott"]{
  background:radial-gradient(circle at 34% 30%,#cfd6e2,#7d8ba1 55%,#414b5c);}
.karte .marken i[data-kw="ansturm"]{
  background:radial-gradient(circle at 34% 30%,#ffd9a8,#e2762c 55%,#8d3f10);}
.karte .marken i[data-kw="fernkampf"]{
  background:radial-gradient(circle at 34% 30%,#cfeadf,#3f9e7c 55%,#1d4f3d);}
.karte .marken i[data-kw="gift"]{
  background:radial-gradient(circle at 34% 30%,#dcf7b0,#77c122 55%,#38610d);}
.karte .marken i[data-kw="doppelschlag"]{
  background:radial-gradient(circle at 34% 30%,#f2c9d8,#c0436e 55%,#6b1c37);}
.karte .marken i[data-kw="todesroecheln"]{
  background:radial-gradient(circle at 34% 30%,#f4efe2,#b9b0a0 55%,#4a443b);}

.karte[data-rar="legendär"] .rahmen{
  border-color:var(--gold-dk);
  box-shadow:0 0 0 1.5px var(--gold),0 0 14px -2px var(--gold);
}

/* Kartenrücken — das gestaltete Motiv, deckungsgleich beschnitten
   wie die Vorderseiten. */
.karte.ruecken .bild,.karte.ruecken .band,.karte.ruecken .text,
.karte.ruecken .stein,.karte.ruecken .marken{display:none;}
.karte.ruecken .rahmen{background:#8f1d1f;border-color:var(--ink);}
.karte.ruecken .rueckbild{
  position:absolute;inset:3px;border-radius:6px;overflow:hidden;
  transform:translateZ(3px);
}
.karte.ruecken .rueckbild img{width:100%;height:100%;object-fit:cover;display:block;}

/* Ausgespielt, aber die Hand ist noch nicht neu gezeichnet: die Karte
   ist weg vom Tisch, ihr Platz im Fächer bleibt bis zum nächsten
   Neuzeichnen offen. visibility statt display, damit die Nachbarn nicht
   im selben Moment noch zur Seite rücken — das kommt gleich ohnehin,
   und zwei Bewegungen übereinander liest niemand. */
.karte.gespielt{visibility:hidden;}

/* Eingereiht, aber noch unterwegs: der Platz im Fächer ist schon
   vergeben, die Karte selbst fliegt noch. visibility statt display,
   damit der Fächer bereits in seiner endgültigen Breite steht — sonst
   rückten die Nachbarn im Moment der Landung noch einmal zur Seite,
   und genau dorthin ist die Karte ja gerade geflogen. */
.karte.einreihend{visibility:hidden;}

/* Angekommen: ein kurzes Setzen, damit der Tausch vom Geist auf die
   echte Karte einen Abschluss bekommt statt einfach aufzuhören. */
.karte.eingereiht{animation:kartenSetzt .3s cubic-bezier(.2,.9,.3,1.4);}
@keyframes kartenSetzt{
  0%  {filter:brightness(1.5);}
  60% {filter:brightness(1.12);}
  100%{filter:none;}
}
@media (prefers-reduced-motion:reduce){
  .karte.eingereiht{animation:none;}
}

/* Herausgezogen (Spielerei): die Karte ist am Zeiger, im Fächer bleibt
   ihr Platz frei. Sichtbarkeit statt display:none — die Nachbarn sollen
   nicht nachrutschen, sondern die Lücke offen halten, damit beim
   Loslassen nichts springt. Der schwache Umriss zeigt, wo sie hingehört. */
.karte.herausgezogen{visibility:hidden;}
.hand.gegner .karte.herausgezogen{
  visibility:visible;opacity:.22;filter:grayscale(1) brightness(.5);}
.hand.gegner .karte.herausgezogen .rueckbild{opacity:.25;}

/* Zustände */
.karte.nichtspielbar{filter:brightness(.62) saturate(.5);}
.karte.nichtspielbar .kosten svg path{fill:url(#grauVerlauf);}
.karte.spielbar .rahmen{box-shadow:0 0 0 2px var(--gold),0 0 18px -2px var(--gold-hi);}
.karte.wird-gezogen{opacity:0;}
/* Karten, die am Zeiger hängen — beim Ausspielen wie bei der Spielerei.

   Die Größe steht hier fest, weil die Ziehmathematik sie kennt:
   geistX/geistY in tisch.js sind die halbe Karte (66 und 93) und setzen
   damit 132 × 185 voraus. Ohne diese Regel griff die Grundgröße von
   116 × 162, und die Karte hing um acht Punkte nach rechts und zwölf
   nach unten versetzt am Finger.

   Die räumliche Drehung der Spielerei bekommt ihre Perspektive im
   transform selbst (`perspective(900px) rotateY(...)`) und nicht von
   diesem Elternteil: eine perspective-Eigenschaft hier machte #geister
   zum Bezugsrahmen für absolut Positioniertes, und alle left/top-Werte
   bezögen sich plötzlich auf einen nulldimensionalen Kasten. */
#geister .karte{width:132px;height:185px;font-size:11.4px;}
.karte.geist{will-change:transform;}
.karte.geist.spielerei{cursor:grabbing;}

/* Die Fontäne: Karten schießen aus dem Stapel und fallen aus dem Bild.

   --dx/--dy geben die Richtung des Ausbruchs, --dreh das Trudeln. Die
   drei stehen als feste Werte in den Bildpunkten der Keyframes; sie
   werden nicht selbst überblendet, sondern der Browser rechnet zwischen
   den fertig eingesetzten Werten. Deshalb braucht es hier kein
   @property. Der Scheitelpunkt bei 45 % gibt den Bogen: erst getragen,
   dann fallengelassen. */
.karte.fontaene{
  /* Schuss und Fall haben verschiedene Zeitkurven — deshalb steht die
     Kurve **in den Bildpunkten** und nicht am animation-Kürzel.

     Der Aufstieg soll knallen: `animation-timing-function` steht auf 0 %
     hart und läuft aus, die Karte ist in gut einem Drittel der Zeit
     oben. Der Fall dagegen beginnt langsam und wird schneller, so wie
     etwas fällt, das oben kurz stehenbleibt. Vorher lief beides mit
     derselben Kurve, und der Fall wirkte gerissen statt geworfen.

     Insgesamt 1,7 Sekunden statt 1,05 — der Aufstieg ist mit rund
     0,45 Sekunden aber sogar schneller als vorher. Länger ist nur das,
     was danach kommt. */
  animation:fontaeneFlug 1.7s forwards;
  /* Kein `will-change`: die Karte wächst im Flug von 0,36 auf 1. Der
     Browser rasterte sie sonst einmal in der kleinen Größe und zöge die
     Textur beim Wachsen auf — genau die Klotzigkeit, vor der der
     Kommentar an `.karte` warnt. */
}
@keyframes fontaeneFlug{
  0%  {transform:translate(0,0) rotate(0deg) scale(.36);opacity:0;
       animation-timing-function:cubic-bezier(.05,.75,.3,1);}
  4%  {opacity:1;}
  /* Scheitel: hier ist der Schuss vorbei und der Fall beginnt. */
  26% {transform:translate(calc(var(--dx) * .72),calc(var(--dy) * 1.06))
                 rotate(calc(var(--dreh) * .42)) scale(1);opacity:1;
       animation-timing-function:cubic-bezier(.5,0,.85,.6);}
  /* Weit unter den Bildrand. Die Zahl ist nachgerechnet, nicht geraten:
     die steilste Karte steigt um --dy nach oben (bis 820 Punkte), der
     gegnerische Stapel liegt schon bei y=41, und ganz verschwunden ist
     eine Karte erst 93 Punkte unter der Bühnenunterkante von 490. Mit
     900 blieben die steilsten 463 Punkte zu kurz und lagen am unteren
     Rand herum; 1600 lässt 237 Punkte Reserve. */
  100%{transform:translate(var(--dx),calc(var(--dy) + 1600px))
                 rotate(var(--dreh)) scale(.9);opacity:1;}
}
@media (prefers-reduced-motion:reduce){
  .karte.fontaene{animation:none;display:none;}
}

/* Eine fliegende Karte mit zwei echten Seiten: Rücken bei 0°, Gesicht
   bei 180°. Beide liegen von Anfang an im Dokument — deshalb steht das
   Gesicht in dem Augenblick da, in dem die Kante durchläuft, ohne dass
   irgendwo ein Inhalt ausgetauscht werden müsste.

   `transform-style: preserve-3d` ist die Bedingung dafür, dass
   `backface-visibility` überhaupt wirkt: ohne sie flacht der Browser die
   Kindebene ein, beide Seiten liegen im selben Blatt und man sieht
   entweder beide übereinander oder — je nach Zeichenreihenfolge — keine
   von beiden. Genau daran krankte der Entwurf davor: die Karte war
   während der halben Drehung schlicht unsichtbar. */
.flug{
  position:absolute;width:132px;height:185px;
  /* Auch hier kein `will-change`: die Flugkarte wird unterwegs skaliert,
     und eine einmal gerasterte Textur würde dabei sichtbar aufgezogen. */
  transform-style:preserve-3d;
}
.flug .seite{
  position:absolute;left:0;top:0;width:132px;height:185px;font-size:11.4px;
  backface-visibility:hidden;-webkit-backface-visibility:hidden;
}
.flug .vorn{transform:rotateY(180deg);}

/* Zerreißen: die Karte wird senkrecht durchgerissen, die Hälften
   fallen auseinander.

   Der Trick sind die beiden Seiten, die die Flugkarte ohnehin hat: sie
   werden beide sichtbar gemacht und je zur Hälfte beschnitten — die
   eine zeigt die linke, die andere die rechte Hälfte. Beide tragen
   dasselbe Bild, es sieht also aus wie eine Karte, die auseinandergeht.
   Kein zusätzliches Bauteil, kein zweites Bild.

   `clip-path` statt `overflow` mit einem Elternteil: overflow und
   3D-Transformationen vertragen sich in den Browsern nicht zuverlässig,
   und die Flugkarte steht in einem preserve-3d-Zusammenhang. */
/* Genau ein Durchlauf, so lang wie das Warten in tisch.js (180 ms) —
   sonst bräche das Zittern mitten in der Bewegung ab und die Karte
   stünde für einen Moment schief da. */
.flug.zittert{animation:kartenZittert .18s linear 1;}
@keyframes kartenZittert{
  0%,100%{margin-left:0;}
  25%    {margin-left:-2.5px;}
  75%    {margin-left:2.5px;}
}

.flug.zerreisst .seite{
  /* Ab jetzt sind beide Seiten sichtbar — sonst blieb die Rückseite
     verborgen, und es fiele nur eine Hälfte. */
  backface-visibility:visible;-webkit-backface-visibility:visible;
  animation:none;
}
.flug.zerreisst .rueck{
  clip-path:polygon(0 0,50% 0,50% 100%,0 100%);
  animation:halbeLinks .62s cubic-bezier(.35,.05,.7,1) forwards;
}
.flug.zerreisst .vorn{
  transform:none;                    /* die 180°-Drehung entfällt hier */
  clip-path:polygon(50% 0,100% 0,100% 100%,50% 100%);
  animation:halbeRechts .62s cubic-bezier(.35,.05,.7,1) forwards;
}
@keyframes halbeLinks{
  0%  {transform:translate(0,0) rotate(0deg);opacity:1;}
  18% {transform:translate(-5px,0) rotate(-2deg);opacity:1;}
  100%{transform:translate(-52px,74px) rotate(-26deg);opacity:0;}
}
@keyframes halbeRechts{
  0%  {transform:translate(0,0) rotate(0deg);opacity:1;}
  18% {transform:translate(5px,0) rotate(2deg);opacity:1;}
  100%{transform:translate(52px,80px) rotate(24deg);opacity:0;}
}
@media (prefers-reduced-motion:reduce){
  .flug.zittert{animation:none;}
  .flug.zerreisst .seite{animation:none;opacity:0;}
}

@media(prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important;}
}
