/* ══════════════════════════════════════════════════════════════════
   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;
  --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;

  /* ─── Maß und Rundung ───────────────────────────────────────────────
     Abstände kommen aus einer Leiter, nicht aus dem Gefühl: alles ist
     ein Vielfaches von 4. Wer einen Wert dazwischen braucht, braucht ihn
     meistens nicht. Rundungen in drei Stufen — klein für Marken und
     Felder, mittel für Knöpfe, groß für Tafeln und Fenster. */
  --mass-1:4px;  --mass-2:8px;  --mass-3:12px; --mass-4:16px;
  --mass-5:24px; --mass-6:32px; --mass-7:48px;
  --rund-1:4px;  --rund-2:6px;  --rund-3:14px; --rund-voll:999px;

  --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;
}
/* **Über allem, was man drücken kann** (seit 349): derselbe Handschuh mit
   goldenem Schein. Wer mit der Maus über ein Band, einen Knopf oder einen
   Verweis fährt, sieht sofort, dass hier etwas passiert — der Zeiger
   wechselt nicht die Form, er leuchtet. Der heiße Punkt wandert mit dem
   Rand um 3 (bzw. 2) Punkte. Gesperrte Knöpfe leuchten nicht. */
:is(a[href],button,label,select,summary,[role="button"],.knopf):not([disabled]):not([aria-disabled="true"]):hover,
:is(a[href],button,label,select,summary,[role="button"],.knopf):not([disabled]):not([aria-disabled="true"]):hover *{
  cursor:url("../assets/zeiger-hand.png") 11 4,url("../assets/zeiger-hand-klein.png") 6 3,pointer !important;
}

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

html,body{margin:0;padding:0;
  user-select:none;-webkit-user-select:none;}
/* Bilder sind hier Spielmaterial, kein Inhalt zum Mitnehmen: Ziehen
   verschöbe sonst die Landkarte quer über den Schirm (siehe auch
   js/griffe.js, das dasselbe für Browser ohne diese Eigenschaft tut). */
img{-webkit-user-drag:none;user-drag:none;}
/* In Eingabefeldern gilt das Gegenteil: dort will man auswählen. */
input,textarea{user-select:text;-webkit-user-select:text;}
/* 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.) */
/* 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. */
  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;
}
/* ─── Der Zierrahmen ────────────────────────────────────────────────
   Ein gemaltes Kartenblatt (assets/kartenrahmen.webp): Bildrahmen mit
   Sternmedaillons, dunkles Namensband, Textfeld. Es liegt **über** dem
   Kartenbild, nicht darunter — die Medaillons ragen in das Bildfeld
   hinein und müssen das Motiv überdecken, wie bei einer gedruckten
   Karte. Das Bildfeld selbst ist im Rahmenbild ausgeschnitten.

   Auf einer eigenen Ebene (5) zwischen Bild (4) und Text (6), Band (8),
   Steinen (16). Die Tinte des Kartenrandes zeichnet der Zierrahmen
   gleich mit: die Vorlage hat einen eigenen, der auf Kartengröße nur
   einen Punkt breit wäre — die 2,5 Punkte hier verbinden Vorderseiten,
   Rückseiten und Diener auf dem Brett.

   **Gedehnt, nicht beschnitten.** Die Vorlage ist 0,752 breit zu hoch,
   die Karte 0,716. Beschneiden hätte die äußere Rahmenlinie an den
   Kartenrand gedrückt; gedehnt werden die Medaillons um knapp fünf
   Prozent schmaler — auf Kartengröße ist das ein halber Punkt. */
.karte .koerper::after{
  content:"";position:absolute;inset:0;border-radius:9px;pointer-events:none;
  border:2.5px solid var(--ink);
  background:url(../assets/kartenrahmen.webp) 0 0 / 100% 100% no-repeat;
  background-origin:border-box;
  transform:translateZ(5px);
}
.karte.ruecken .koerper::after{display:none;}

/* Der Fraktionsstreifen: im schmalen Pergamentsaum unter der untersten
   Rahmenlinie. Er lag bisher auf dem Rahmen selbst und wäre jetzt vom
   Zierrahmen verdeckt — darum eine eigene Ebene darüber. */
.karte .koerper::before{
  content:"";position:absolute;left:8%;right:8%;bottom:2.3%;height:2.5px;
  border-radius:2px;background:var(--fc,transparent);
  transform:translateZ(6px);pointer-events:none;
}
.karte.ruecken .koerper::before{display:none;}
.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{
  /* Das Fenster im Zierrahmen reicht von 10,2 bis 89,7 Prozent der
     Breite und von 6,2 bis 48,8 Prozent der Höhe. Das Bild ist rundum
     ein halbes Prozent größer: die Kante liegt dann unter den Linien
     des Rahmens, und nirgends blitzt Pergament durch. Einen eigenen
     Rand braucht es nicht mehr — den zeichnet der Rahmen. */
  position:absolute;left:9.7%;right:9.8%;top:5.8%;height:43.5%;
  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{
  /* Genau über der dunklen Fläche des gemalten Bandes (6,5 bis 93,4
     Prozent breit, 54,1 bis 62,6 Prozent hoch). Beim Diener ist es
     durchsichtig — das gemalte Band trägt den Namen. Zauber und
     Geheimnisse legen eine Tönung darüber (siehe unten); die Ecken sind
     dafür abgeschrägt wie die des gemalten Bandes. */
  position:absolute;left:6.5%;right:6.6%;top:54.1%;height:8.5%;
  transform:translateZ(8px);
  clip-path:polygon(2.1% 0,97.9% 0,100% 16%,100% 84%,97.9% 100%,2.1% 100%,0 84%,0 16%);
  /* 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:none;
  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{
  /* Im Textfeld des Zierrahmens, zwei Punkte unter dem Band. Drei
     Zeilen enden bei 80 Prozent — dort beginnen die Werte-Steine, die
     in den unteren Ecken auf den Medaillons sitzen. */
  position:absolute;left:9%;right:9%;top:66%;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);}
/* Mehr Leben als auf der Karte (Abenteuer: Verstärkung, seit 358). */
.karte .leben.hoch span{color:#d8ffc6;}
.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:66%;height:26%;font-size:.72em;
  -webkit-line-clamp:5;}
.karte[data-art="zauber"] .koerper::before{
  background:linear-gradient(90deg,var(--mana),#8b56aa);}
/* Die Tönung liegt halbdurchsichtig auf dem gemalten Band: dessen
   Faserung bleibt sichtbar, die Farbe sagt „Zauber". */
.karte[data-art="zauber"] .band{background:rgba(96,72,150,.74);}

/* 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:66%;height:26%;font-size:.68em;
  -webkit-line-clamp:5;}
.karte[data-art="geheimnis"] .koerper::before{
  background:linear-gradient(90deg,#b8452f,#e0b352);}
/* Kupfer statt Braun — kräftig genug, dass es neben dem Dienerband als
   eigene Farbe gelesen wird und nicht als hellere Fassung derselben. */
.karte[data-art="geheimnis"] .band{background:rgba(196,112,44,.78);}

/* 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 ihre Bedeutung: jede hat ihre eigene Farbe und
   einen Namen im title. Der Wortlaut steht zwar im Textfeld, aber auf
   dem Brett gibt es kein Textfeld, und beim schnellen Überfliegen liest
   man ohnehin die Symbole zuerst. */
/* 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{
  box-shadow:0 0 0 1.5px var(--gold),0 0 14px -2px var(--gold);
}
/* Den Rand zeichnet der Zierrahmen — dort muss auch das Gold hin. */
.karte[data-rar="legendär"] .koerper::after{border-color:var(--gold-dk);}

/* 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; mit einer Kurve für beides
     wirkt der Fall gerissen statt geworfen.

     Insgesamt 1,7 Sekunden, davon rund 0,45 für den Aufstieg. */
  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;}
}

/* ══════════════════════════════════════════════════════════════════
   DER BANDKNOPF

   Ein Spruchband als Knopf. Er steht hier und nicht im Menü-Stilblatt,
   weil ihn drei Orte brauchen: die Wege im Hauptmenü, der Weg hinaus
   auf der Landkarte und das Schließen im Beutel. Ein zweites Band
   wäre ein zweites Aussehen für dieselbe Sache.

   **Er heißt `banderole` und nicht `band`.** `band` ist weiter oben in
   dieser Datei längst vergeben: es ist das Namensband auf einer
   Spielkarte (`.karte .band`). Die Bühne der Landkarte trägt aber die
   Klasse `karte` — der Zurück-Knopf war damit ein Nachfahre und bekam
   von dort `left:3.5%` und `top:55.5%` mit. Zusammen mit dem eigenen
   `right`/`bottom` war der Kasten überbestimmt, `left` gewann, und der
   Knopf hing mitten in der Landschaft.
   ══════════════════════════════════════════════════════════════════ */
/* ─── Ein Band als Knopf ───────────────────────────────────────────
   Die Vorlage ist ein Spruchband von 2146 × 361 mit zwei hängenden
   Faltungen. Sie wird als `border-image` gesetzt und nicht als
   Hintergrund: nur so behalten die Enden ihre Form, während die Mitte
   auf jede Breite wächst.

   **Drei Zahlen stecken in der Vorlage und stehen deshalb hier:**
     340 von 2146  die Breite eines Endstücks (15,8 Prozent)
     250 von 361   dort endet der Bandkörper; darunter hängen nur noch
                   die Faltungen
     127 von 361   die Mitte des Körpers, also 35,3 Prozent der Höhe

   Die letzte ist die wichtigste: der Inhalt gehört auf die Mitte des
   **Körpers**, nicht auf die Mitte des Kastens. Mittig gesetzt stünde
   die Schrift sichtbar zu tief, weil das untere Drittel des Bildes
   nur herabhängendes Band ist.

   Alles hängt an `--bandhoehe`. Ändert sie sich, wandern Endbreite,
   Zeichengröße und der Ausgleich von selbst mit. */
/* ─── Symbolknopf ─────────────────────────────────────────────────────
   Ein Knopf, der nur ein Zeichen trägt: schließen, bearbeiten, löschen,
   Ton an und aus. Es gibt genau **einen** davon im ganzen Spiel — vorher
   hatte jede Stelle ihren eigenen runden Knopf mit eigener Größe, eigener
   Kante und eigenem Übergang.

   Zwei Größen: `klein` (28) für Marken an Kacheln, sonst 40. Die
   Zustände sind dieselben wie beim großen Knopf: heben beim Überfahren,
   eindrücken beim Klicken, matt wenn gesperrt. */
.ikonknopf{
  width:40px;height:40px;padding:0;flex:0 0 auto;
  display:inline-grid;place-items:center;
  border-radius:var(--rund-voll);cursor:pointer;
  background:rgba(20,16,11,.72);border:1px solid rgba(238,220,171,.35);
  color:var(--parch-hi);font-family:var(--display);font-size:20px;line-height:1;
  transition:border-color .18s ease,background .18s ease,transform .18s ease;
}
.ikonknopf img{width:58%;height:58%;object-fit:contain;display:block;
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.55));}
.ikonknopf:hover{border-color:var(--gold-hi);background:rgba(58,40,22,.9);}
.ikonknopf:active{transform:translateY(2px);}
.ikonknopf:focus-visible{outline:2px solid var(--gold-hi);outline-offset:2px;}
.ikonknopf:disabled{opacity:.35;cursor:default;transform:none;}
.ikonknopf.klein{width:28px;height:28px;font-size:15px;}

.knopf.banderole{
  --bandhoehe:62px;
  --bandende:calc(var(--bandhoehe) * 340 / 361);
  width:100%;height:var(--bandhoehe);min-height:0;
  border-style:solid;border-width:0 var(--bandende);
  border-image-source:url(../assets/banner.webp?v=387);
  border-image-slice:0 340 fill;
  border-image-repeat:stretch;
  background:none;box-shadow:none;border-radius:0;padding:0;
  display:flex;align-items:center;
  font-family:var(--display);font-weight:400;font-size:22px;
  /* Dieselbe Tinte wie der Schriftzug, nicht das Schwarz der übrigen
     Knöpfe: Band und Titel sind aus einer Feder. */
  color:#5c341a;text-shadow:none;
  transition:filter .18s ease,transform .18s ease;
}
/* Der Ausgleich auf die Körpermitte: 35,3 statt 50 Prozent. */
.knopf.banderole > *{transform:translateY(calc(var(--bandhoehe) * -0.147));}
.knopf.banderole .zeichen{
  width:calc(var(--bandhoehe) * 0.56);height:calc(var(--bandhoehe) * 0.56);
  /* Ein Stück in die Faltung hinein: genau an der Naht wirkte das
     Zeichen eingeklemmt. */
  margin-left:calc(var(--bandende) * -0.22);flex:0 0 auto;
}
/* Die Beschriftung mittig im **freien** Teil des Bandes, also rechts
   vom Zeichen — mittig im ganzen Knopf säße sie sichtbar verschoben. */
.knopf.banderole span{
  flex:1;text-align:center;
  padding:0 calc(var(--bandende) * -0.22 + 12px) 0 12px;
}
/* Ohne Zeichen sitzt die Schrift exakt in der Mitte (382, Wunsch Max). */
.knopf.banderole span:only-child{padding:0 12px;}

/* ══════════════════════════════════════════════════════════════════
   DAS SIEGEL EINER AUFGABE

   Ein rotes Wachssiegel mit Fragezeichen — die verdeckte Belohnung. Es
   ist das verbindende Bild: dasselbe Siegel steht auf dem Endbildschirm
   („Aufgabe erfüllt") und in der Lupe des Kompendiums, wo es bricht und
   die Fähigkeit freigibt. Man erkennt dort wieder, was man nach der
   Partie gesehen hat.
   ══════════════════════════════════════════════════════════════════ */
.siegelmedaillon{
  display:inline-grid;place-items:center;flex:0 0 auto;
  width:40px;height:40px;border-radius:50%;
  background:radial-gradient(circle at 35% 30%,#c0453a 0%,#8f2219 55%,#5e1410 100%);
  border:2.5px solid var(--ink);
  box-shadow:inset 0 0 0 3px rgba(232,181,58,.55),0 2px 5px rgba(0,0,0,.45);
  font-family:var(--display);font-size:22px;line-height:1;padding-top:.08em;
  color:#f3dfb0;text-shadow:0 1px 0 rgba(0,0,0,.5);
  transform:rotate(-8deg);
}


/* ══════════════════════════════════════════════════════════════════
   MANA

   Mana hat **ein** Gesicht, auf dem Brett wie daneben: die blaue Kugel
   aus assets/mana.webp, ihr Klang (`manakugel`, spentOrb_08.mp3) und
   ihr Wabern. Boosterseite, Kompendium und Brett zeigen dieselbe Kugel;
   wer Mana bekommt oder ausgibt, hört und sieht dasselbe wie beim
   Antippen einer Kugel im Kampf. Gold klingt nach Münzen, Mana nie.
   Das Verhalten (Klang, Wabern, fliegende Kugeln) steht in
   js/manakugel.js.
   ══════════════════════════════════════════════════════════════════ */
.manakugel{display:inline-block;flex:0 0 auto;width:1.3em;height:1.3em;vertical-align:-.3em;
  background:url('../assets/mana.webp?v=387') center/contain no-repeat;}
.manakugel.wabert{animation:kugelWabert 1.56s linear;}
/* Mana unterwegs: eine Leinwand über allem (js/manakugel.js → fliegen).
   Sie nimmt keine Klicks und liegt über Lupe und Kopfleisten. */
.manaleinwand{position:fixed;inset:0;width:100%;height:100%;z-index:200;pointer-events:none;}
/* Eine Zahl, die mit Mana zu tun hat, leuchtet kurz im Blau der Kugel. */
.manawert.tickt{color:var(--mana-hi);text-shadow:0 0 12px rgba(120,200,255,.8);}

/* Angetippt: die Kugel **wabert**. Hell, zurück, wieder hell — dem
   Geräusch nach, nicht nach Gefühl.

   Die Hüllkurve von spentOrb_08.mp3 wurde dafür ausgemessen: das
   Geräusch schwillt in Stößen an, mit hellen Stellen bei 0,24 / 0,44 /
   0,60 / 0,76 Sekunden, dazwischen jedes Mal ein Rückgang, und der
   lauteste Punkt liegt bei 0,76 s. Die Bildpunkte unten sind genau
   diese Zeiten, geteilt durch die Gesamtlänge von 1,56 s. Deshalb
   pulsiert das Licht im Takt des Klangs, statt bloß daneben zu blinken.

   **Keine Größenänderung.** Jede würde sich als Zustandswechsel lesen,
   als wäre ein Kristall dazugekommen. Es ist allein der Schein.

   Die ersten fünf Prozent bleiben dunkel: das Geräusch braucht diesen
   Moment, um zu tragen. Erst passiert kurz nichts, dann kommen Bild und
   Ton zusammen. */
@keyframes kugelWabert{
  0%    {filter:drop-shadow(0 0 5px rgba(63,169,221,.85));}
  5%    {filter:brightness(1.05) drop-shadow(0 0 6px rgba(63,169,221,.9));}
  15.4% {filter:brightness(1.42) drop-shadow(0 0 15px var(--mana-hi));}
  21.2% {filter:brightness(1.12) drop-shadow(0 0  8px var(--mana-hi));}
  28.2% {filter:brightness(1.46) drop-shadow(0 0 16px var(--mana-hi));}
  33.3% {filter:brightness(1.15) drop-shadow(0 0  9px var(--mana-hi));}
  38.5% {filter:brightness(1.52) drop-shadow(0 0 18px var(--mana-hi));}
  43.6% {filter:brightness(1.14) drop-shadow(0 0  9px var(--mana-hi));}
  48.7% {filter:brightness(1.6)  drop-shadow(0 0 21px var(--mana-hi));}
  56.4% {filter:brightness(1.12) drop-shadow(0 0  8px var(--mana-hi));}
  61.5% {filter:brightness(1.3)  drop-shadow(0 0 12px var(--mana-hi));}
  74.4% {filter:brightness(1.1)  drop-shadow(0 0  7px var(--mana-hi));}
  100%  {filter:drop-shadow(0 0 5px rgba(63,169,221,.85));}
}
@media (prefers-reduced-motion:reduce){
  .manakugel.wabert{animation:none;}
}

/* ─── Qualität „niedrig“ (js/qualitaet.js) ────────────────────────────
   Für den alten Laptop ohne Grafikbeschleunigung: alles, was den
   Prozessor **je Bild** rastern lässt, steht still — Filter in
   Schlüsselbildern, atmende Schatten, Glanzbänder, Weichzeichner hinter
   Tafeln. Die Bewegungen des Spiels selbst (Karten, Treffer, Kugeln)
   bleiben; sie sind kurz und laufen über Transformationen. Die
   Landkarte regelt js/atmosphaere.js (leichte Schichten, halbe
   Leinwand, 15 Bilder), der Kampf js/funken.js und js/manakugel.js. */
html[data-qualitaet="niedrig"] .zugtaste.bereit{animation:none;filter:brightness(1.12);}
html[data-qualitaet="niedrig"] .diener.tarnung .scheibe,
html[data-qualitaet="niedrig"] .diener.tarnung .scheibe::after,
html[data-qualitaet="niedrig"] .erfolg.neu img,
html[data-qualitaet="niedrig"] .wartemarke::before,
html[data-qualitaet="niedrig"] .ebenen li.jetzt,
html[data-qualitaet="niedrig"] .abenteuerneu,
html[data-qualitaet="niedrig"] .held .kraft.bereit .symbol{animation:none;}
html[data-qualitaet="niedrig"] .nachfrage,
html[data-qualitaet="niedrig"] .schleier{backdrop-filter:none;}

/* ─── Rollbalken im eigenen Gewand (382, Wunsch Max) ─────────────────
   Überall, wo gerollt wird (Rüstkammer, Altar, Logbuch, Werkstatt),
   derselbe schmale Goldbalken statt des grauen Systembalkens. */
*{scrollbar-width:thin;scrollbar-color:#9a7433 rgba(20,14,8,.55);}
::-webkit-scrollbar{width:10px;height:10px;}
::-webkit-scrollbar-track{background:rgba(20,14,8,.55);border-radius:8px;}
::-webkit-scrollbar-thumb{background:linear-gradient(180deg,#c99a4b,#8a6428 70%,#6e4e1d);
  border-radius:8px;border:2px solid rgba(20,14,8,.8);}
::-webkit-scrollbar-thumb:hover{background:linear-gradient(180deg,#e0b35e,#9a7433);}
::-webkit-scrollbar-corner{background:transparent;}
