/* ui/styles.css — Look & Layout. Keine externen Fonts oder CDNs; Bilder nur die
   Schauplätze aus assets/backgrounds/ (Abschnitt 20).
   ---------------------------------------------------------------------------
   AUFBAU: Die Abschnitte 1–17 sind die gemeinsame Grundlage – Layout, Maße,
   Animationen und eine Basis-Farbwelt ("Abendjahrmarkt": Pflaumenblau, Laternen-
   licht, Messing). Diese Basis war bis 09/2026 das Setting „Haustiere" und ist
   heute nur noch das Fundament, das jedes Setting mit eigenen Tokens und
   Überschreibungen (Abschnitte 18, 19) komplett übermalt; ohne Setting-Klasse
   auf <html> ist sie nie zu sehen (main.js setzt immer eine).

   Aufteilung:
     1  Tokens              alle Farben/Maße als CSS-Variablen
     2  Grundlagen          Reset, Typografie, Hintergrund
     3  Raster              App-Grid
     4  Kopfzeile           Messingschiene mit Spielstand
     5  Knöpfe
     6  Panels & Markisen
     7  Slots
     8  Karten              Pet / Food / Toy
     9  Tooltip
    10  Drag & Drop
    11  Kampf
    12  Overlays & Dialoge
    13  Toasts
    14  Startbildschirm
    15  FX-Ebene            Partikel, Flüge, Konfetti (ui/fx.js)
    16  Responsiv
    17  Reduzierte Bewegung
    18  Setting „Konvoi“    Farbwelt des Standardsettings (Tokens + Überschreibungen)
    19  Setting „Cyberpunk-Crew“
    20  Schauplätze         Hintergrundbild je Setting und Spieler
    21  Ladezustand (boot)  textfreier Puls, bis die Sprachdatei da ist
    22  Mehrspieler         Ranglisten-Spalte, große Rundenuhr, Warte- und Zuschauertafel
   --------------------------------------------------------------------------- */

/* ============================================================ 1  Tokens */
:root {
  /* Nachtplatz */
  --ink: #130e1e;
  --ink-2: #1a1329;
  --plum: #241a35;
  --plum-2: #2e2242;
  --plum-3: #392b50;
  --line: #46335f;
  --line-soft: #33254a;

  /* Laternenlicht */
  --brass: #e8a94a;
  --brass-deep: #b47a25;
  --lantern: #ffc66b;
  --sawdust: #d8b88c;

  /* Signalfarben */
  --mint: #4fd6a8;
  --mint-deep: #2c9d78;
  --punch: #ff5871;
  --punch-deep: #c22f46;
  --neon: #a87cff;
  --frost: #86d9ff;

  /* Rollen */
  --text: #f4eeff;
  --text-dim: #a898c2;
  --text-faint: #7a6b95;
  --gold: var(--brass);
  --atk: #ff8360;
  --hp: #6fd98a;
  --temp: var(--lantern);
  --bad: var(--punch);
  --ok: var(--mint);

  /* Form */
  --r-panel: 18px;
  --r-card: 14px;
  --r-ctrl: 10px;
  --r-pill: 999px;

  /* Licht & Schatten: warm-violett, nie neutrales Grau */
  --lift-1: 0 1px 0 rgba(255, 226, 178, .09) inset, 0 2px 6px rgba(9, 5, 16, .5);
  --lift-2: 0 1px 0 rgba(255, 226, 178, .12) inset, 0 8px 22px -6px rgba(9, 5, 16, .7);
  --lift-3: 0 1px 0 rgba(255, 226, 178, .16) inset, 0 18px 40px -10px rgba(9, 5, 16, .8);
  --glow-brass: 0 0 0 1px rgba(232, 169, 74, .55), 0 0 22px -4px rgba(255, 198, 107, .45);
  --glow-mint: 0 0 0 1px rgba(79, 214, 168, .6), 0 0 24px -4px rgba(79, 214, 168, .45);

  /* Typografie: eine Familie, zwei Rollen. ui-rounded ist auf Apple-Systemen
     SF Rounded (Jahrmarkt-Schilderschrift), sonst greift system-ui. */
  --font: ui-rounded, "SF Pro Rounded", "Hiragino Maru Gothic ProN", system-ui,
          -apple-system, "Segoe UI Variable", "Segoe UI", Roboto, sans-serif;
  /* Kartenbreite = Illustrationsbreite (die Grafik nimmt die volle Karte).
     `--card-w-max` ist das Maximum, das fünf Slots (config.js petSlots) im Panel ohne
     Umbruch hergeben; darunter greift die Media Query — sie setzt nur noch das Maximum.

     Nach oben deckelt zusätzlich die FENSTERHÖHE: Aufstellung und Auslage sind beide
     eine Kartenbreite hoch (die Grafik ist quadratisch), dazu kommt Höhe, die nicht
     mitskaliert — Polsterung der Seite (32), Kopf und Polsterung der beiden Tafeln
     (81 + 130 — die Goldplakette im Shopkopf ist 6px höher als eine Textzeile, §7),
     die Standlinie der Aufstellung (74) und die Lücke dazwischen (14),
     zusammen 331px. Passen zwei Kartenbreiten nicht mehr daneben, wird die KARTE
     kleiner, statt die Seite länger zu werden. Dieselbe Rechnung wie im Ring
     (`--bt-card-w`, Abschnitt 11). */
  --card-w-max: 208px;
  --card-h-fit: calc((100vh - 331px) / 2);
  --card-w: min(var(--card-w-max), var(--card-h-fit));
  /* Breite der Vorratsspalte rechts in der Auslage (§7). Schmaler als eine
     Einheitenkarte: die Vorratsgrafik ist ein Gegenstand, keine Figur. Nach unten
     begrenzt, sonst wird die Grafik zur Briefmarke. */
  --food-w: max(96px, calc(var(--card-w) * .64));
  /* Höhe der beiden Shop-Karten, ohne sie zu messen — die Auslage braucht sie als
     Festmaß, damit ein leergekaufter Shop nicht flacher wird als ein voller (§7).
     Einheitenkarte: quadratische Illustration über die Kartenbreite, dazu Plakette,
     Polsterung und Rand (54px, siehe Abschnitt 8). Vorratskarte: Grafik mit fester
     Höhe von 64px plus Name, Preis und Rahmen. */
  --shop-card-h: calc(var(--card-w) + 54px);
  --food-card-h: 102px;

  --ease-out: cubic-bezier(.22, .8, .24, 1);
  --ease-back: cubic-bezier(.34, 1.56, .48, 1);
}

/* ======================================================== 2  Grundlagen */
* { box-sizing: border-box; }

/* Das HTML-Attribut `hidden` muss stärker sein als jede Layoutregel: eine Klasse mit
   `display: flex` schlägt sonst die Vorgabe des Browsers, und das Element bleibt sichtbar,
   obwohl der Code es versteckt hat (so blieb die Uhr der Mehrspieler-Spalte nach dem
   Partieende stehen). */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  min-height: 100%;
  overflow-x: hidden;                 /* nie horizontal scrollen */
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.45;
  -webkit-text-size-adjust: 100%;
}
/* Die Grundfarbe liegt NUR auf <html>. Ein Body-Hintergrund würde als normaler Block über
   den festen Ebenen `body::before`/`::after` (z-index < 0) gemalt und sie komplett
   verdecken – genau das war bis 09/2026 der Fall, Laternenschein und Schauplatz blieben
   unsichtbar. */
html { background-color: var(--ink); }
body { background: transparent; }

/* Nachthimmel + Laternenschein + Bodennebel. Fest, scrollt nicht mit. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(120% 70% at 50% -12%, rgba(255, 198, 107, .16), transparent 58%),
    radial-gradient(70% 44% at 50% 106%, rgba(168, 124, 255, .13), transparent 70%),
    radial-gradient(140% 100% at 50% 0%, var(--ink-2) 0%, var(--ink) 62%);
}
/* Weiche Vignette: zieht den Blick in die Mitte des Platzes. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(115% 85% at 50% 42%, transparent 42%, rgba(6, 3, 12, .62) 100%);
}

h1, h2, h3 { margin: 0; font-weight: 800; letter-spacing: -.015em; }
p { margin: .35em 0; }
button, input, select { font-family: inherit; }

/* Tabellenziffern überall, wo Zahlen tweenen – sonst zappelt die Breite. */
.stat-value, .badge, .cost-badge, .bt-float, .fx-float, .num, .toy-ring-num { font-variant-numeric: tabular-nums; }

::selection { background: rgba(232, 169, 74, .35); }

/* ============================================================ 3  Raster */
/* Zwei Spalten: Spielfeld und daneben die schmale Spalte. Was in ihr steht, hängt am
   Modus — im Einzelspieler die Werte (`.app-header`, §4), im Netzspiel die Rangliste
   (§22). Beides steht seitlich und nicht als Leiste oben, weil die Höhe der Seite
   knapp ist und die Breite nicht: eine Leiste kostet 76 px, die unten am Shop fehlen. */
.sap-app {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--side-w);
  grid-template-areas: "view side";
  gap: 14px;
  align-items: start;
  max-width: 1440px;
  margin: 0 auto;
  --page-pad: 16px;
  padding: var(--page-pad);
  /* Voreinstellung ist die schmale Spalte des Einzelspielers – sie gilt auch, wenn kein
     Modus gesetzt ist (ui/dev.html). */
  --side-w: 156px;
}
.sap-app[data-mode="mp"] { --side-w: 232px; }
/* Das Spielfeld füllt die Fensterhöhe – `min-height`, nicht `height`: reicht die Höhe
   für die Karten trotz Deckel (§1) nicht, wächst die Seite und scrollt, statt den
   Inhalt abzuschneiden. Die Spalte daneben darf kürzer bleiben. */
.app-view {
  grid-area: view; min-width: 0; position: relative; z-index: 2;
  display: flex; flex-direction: column;
  min-height: calc(100vh - 2 * var(--page-pad));
}
.app-side { grid-area: side; min-width: 0; position: relative; z-index: 3; }

/* Unter ~1160px reichen fünf große Karten nicht in eine Zeile – zurück auf klein.
   (Bis zum Wegfall der Protokollspalte lag die Grenze bei 1380px.) */
@media (max-width: 1160px) {
  :root { --card-w-max: 112px; }
}

/* Eintritt: eine orchestrierte Sequenz beim Aufbau, danach nur noch Reaktionen. */
.sap-app > * { animation: riseIn .5s var(--ease-out) both; }
.app-view { animation-delay: .1s; }
.app-side { animation-delay: .16s; }
@keyframes riseIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

/* ========================================================= 4  Werte-Spalte */
/* Die Werte des Einzelspielers stehen rechts neben dem Feld, in derselben Spalte, in der
   das Netzspiel seine Rangliste zeigt (§22): dieselbe Tafel (`.panel.side-panel`), nur
   ein anderer Inhalt. Als Leiste über dem Feld kostete sie 76 px Höhe, und genau die
   fehlten auf einem Laptop unten am Shop.
   Die Messingfuge sitzt darum unten an der Tafel und nicht mehr unter einer Schiene. */
.app-header { overflow: hidden; }
.app-header::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: linear-gradient(90deg, transparent, var(--brass-deep) 18%, var(--lantern) 50%, var(--brass-deep) 82%, transparent);
  opacity: .7;
}

.brand-title {
  font-size: 17px; font-weight: 800; letter-spacing: -.02em;
  background: linear-gradient(180deg, #fff6e4, var(--brass));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.brand-pack { color: var(--text-dim); font-size: 11.5px; }

/* Untereinander, jede Zahl mit ihrer Beschriftung in einer Zeile: in einer 156 px
   schmalen Spalte ist Höhe billig und Breite teuer. */
.stats-bar { display: flex; flex-direction: column; gap: 5px; }
.stat {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  line-height: 1.15;
  padding: 3px 9px 4px;
  border-radius: var(--r-ctrl);
  background: rgba(0, 0, 0, .18);
  box-shadow: inset 0 1px 0 rgba(255, 226, 178, .06);
}
.stat-label { font-size: 10.5px; color: var(--text-faint); }
.stat-value { font-size: 17px; font-weight: 800; }
/* Das Verlaufsband bricht als einziges um – zehn Marken passen nicht neben ihre
   Beschriftung. */
.stat.history { flex-direction: column; align-items: flex-start; gap: 1px; }
.stat.gold { background: linear-gradient(180deg, rgba(232, 169, 74, .18), rgba(232, 169, 74, .06)); }
.stat.gold .stat-value { color: var(--lantern); text-shadow: 0 0 14px rgba(255, 198, 107, .5); }
.stat.gold.fx-pop { animation: goldPop .5s var(--ease-back); }
@keyframes goldPop {
  0% { transform: scale(1); } 40% { transform: scale(1.12); box-shadow: var(--glow-brass); } 100% { transform: scale(1); }
}
.hearts { display: inline-flex; gap: 3px; }
.heart { color: var(--punch); font-size: 15px; filter: drop-shadow(0 0 6px rgba(255, 88, 113, .55)); }
.heart.lost { color: #4b3b60; filter: none; }
.heart.dying { animation: heartBreak .8s ease both; }
@keyframes heartBreak {
  0% { transform: scale(1); } 25% { transform: scale(1.5) rotate(-12deg); }
  100% { transform: scale(1) rotate(0); color: #4b3b60; filter: none; }
}
/* Zehn Marken passen nicht in eine Zeile der schmalen Spalte – sie brechen um. */
.history .stat-value { display: flex; flex-wrap: wrap; gap: 3px; }
.hx {
  width: 15px; height: 15px; border-radius: 5px; font-size: 10px; font-weight: 800;
  display: inline-flex; align-items: center; justify-content: center; color: #1b1226;
  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
}
.hx-win { background: linear-gradient(180deg, #7ce8c0, var(--mint-deep)); }
.hx-loss { background: linear-gradient(180deg, #ff8194, var(--punch-deep)); }
.hx-draw { background: linear-gradient(180deg, #9c8bb8, #5c4d78); }

/* =========================================================== 5  Knöpfe */
.btn {
  position: relative;
  font: inherit; font-weight: 700; font-size: 14.5px;
  color: var(--text);
  background: linear-gradient(180deg, var(--plum-3), var(--plum));
  border: 1px solid var(--line);
  border-radius: var(--r-ctrl);
  padding: 9px 16px;
  cursor: pointer;
  box-shadow: var(--lift-1);
  transition: transform .12s var(--ease-back), box-shadow .16s ease, filter .16s ease;
}
.btn::before {                       /* Lichtsaum oben – Knöpfe sind Hardware */
  content: ''; position: absolute; inset: 1px 1px auto; height: 45%;
  border-radius: calc(var(--r-ctrl) - 1px) calc(var(--r-ctrl) - 1px) 0 0;
  background: linear-gradient(180deg, rgba(255, 236, 205, .13), transparent);
  pointer-events: none;
}
.btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: var(--lift-2); filter: brightness(1.1); }
.btn:active:not(:disabled) { transform: translateY(1px) scale(.985); box-shadow: var(--lift-1); }
.btn:disabled { opacity: .4; cursor: not-allowed; box-shadow: none; }
.btn:focus-visible { outline: 2px solid var(--lantern); outline-offset: 2px; }

.btn.primary {
  background: linear-gradient(180deg, #f0b95e, var(--brass-deep));
  border-color: #f6cd84; color: #24170a;
}
.btn.primary:hover:not(:disabled) { box-shadow: var(--lift-2), var(--glow-brass); }
.btn.go {
  background: linear-gradient(180deg, #63e0b2, var(--mint-deep));
  border-color: #8bf0cc; color: #10281f;
}
.btn.go:hover:not(:disabled) { box-shadow: var(--lift-2), var(--glow-mint); }
.btn.danger { background: linear-gradient(180deg, #ff7286, var(--punch-deep)); border-color: #ff9aa8; color: #2a0b12; }
.btn.ghost { background: rgba(255, 255, 255, .03); border-color: var(--line-soft); }
.btn.tiny { padding: 3px 9px; font-size: 12px; border-radius: 7px; font-weight: 700; }
.btn.big { padding: 12px 26px; font-size: 17px; border-radius: 12px; }
.btn.active { border-color: var(--lantern); box-shadow: var(--lift-1), var(--glow-brass); }

/* =============================================== 6  Panels & Markisen */
.panel {
  position: relative;
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(255, 198, 107, .07), transparent 60%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  padding: 14px;
  box-shadow: var(--lift-2);
}
/* Markise: gestreifter Saum am oberen Rand des Standes. */
.panel::before {
  content: '';
  position: absolute; inset: 0 0 auto; height: 6px;
  border-radius: var(--r-panel) var(--r-panel) 0 0;
  background: repeating-linear-gradient(90deg,
    rgba(232, 169, 74, .55) 0 14px, rgba(168, 124, 255, .3) 14px 28px);
  opacity: .55;
}
.team-panel::before {
  background: repeating-linear-gradient(90deg,
    rgba(79, 214, 168, .5) 0 14px, rgba(255, 198, 107, .28) 14px 28px);
}

.panel-head { display: flex; align-items: baseline; gap: 10px; justify-content: space-between; margin-bottom: 10px; }
.panel-head h2 { font-size: 15px; font-weight: 800; color: var(--text); }
.panel-head h2::after {                /* kurzer Messingstrich statt Versalien-Label */
  content: ''; display: block; width: 26px; height: 2px; margin-top: 3px;
  border-radius: 2px; background: linear-gradient(90deg, var(--brass), transparent);
}
.hint { font-size: 11.5px; color: var(--text-faint); }
.muted { color: var(--text-dim); }

.team-panel .panel-head { align-items: center; flex-wrap: wrap; row-gap: 6px; }
.team-head-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }

/* Der Shop unten ist so hoch, wie seine Karten sind; die Aufstellung nimmt den Rest
   der Fensterhöhe. Darum hat die Aufstellung keine vh-Höhe mehr: ein Bruchteil der
   Fensterhöhe passte immer nur zu genau einer Fensterhöhe. */
.shop-view { display: flex; flex-direction: column; gap: 14px; flex: 1 1 auto; }
.shop-view > .team-panel { flex: 1 1 auto; display: flex; flex-direction: column; }
.shop-view > .shop-panel { flex: 0 0 auto; }

/* Kopfzeile des Shops: Hinweis, Gold-Kopie und Neu-Rollen. Auf schmalen
   Schirmen umbrechen sie in Leserichtung (Titel, Hinweis, Bedienung). */
.shop-tools { display: flex; align-items: center; gap: 8px; margin-left: auto; }
/* Das eigene Gold ist die wichtigste Zahl im Shop — jede Kaufentscheidung hängt
   an ihr. Darum keine getönte Blase mehr, sondern eine geprägte Goldplakette:
   dunkle Schrift auf vollem Laternenlicht, doppelt so groß wie der Hinweis
   daneben. Das Licht kommt als Weiß-/Schwarzverlauf ÜBER die Farbe, damit jedes
   Setting seinen eigenen Goldton behält (Cyberpunk: Natriumgelb, nicht Magenta). */
.gold-chip {
  font-size: 22px; font-weight: 900; line-height: 1;
  color: var(--ink);
  background-color: var(--lantern);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .42), rgba(0, 0, 0, .16));
  border: 1px solid var(--lantern);
  border-radius: var(--r-pill); padding: 5px 15px 7px;
  box-shadow: var(--lift-1), 0 0 22px -4px var(--lantern);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
.shop-tools .roll-btn { padding: 5px 12px; font-size: 12.5px; }
.shop-panel .panel-head { align-items: center; flex-wrap: wrap; row-gap: 6px; }
.row { display: flex; flex-wrap: wrap; gap: 10px; }
.team-row, .shop-row, .food-row { justify-content: center; }

/* Auslage und Vorräte nebeneinander: links die Einheiten, rechts daneben die zwei
   Vorratskarten übereinander. Gestapelt sind sie so hoch wie eine Einheitenkarte,
   also kostet die Spalte keine Höhe — als eigene Zeile darunter kostete sie 156 px.
   Die Einheiten geben stattdessen etwas Breite ab (`flex: 0 1`, kein Umbruch):
   fünf Karten und die Vorratsspalte teilen sich die Panelbreite.

   Die Vorräte stehen DIREKT neben der letzten Einheit, nicht am rechten Panelrand:
   dafür wächst die Einheitenreihe nicht mehr auf die freie Breite (`flex: 0 1`),
   sondern beide Gruppen bilden einen Block, den `.shop-goods` mittig setzt. Sonst
   klebten die Vorräte bei drei Einheiten (Runde 1) am Rand, eine Kartenbreite
   entfernt von dem, worauf man sie zieht. */
.shop-goods { display: flex; align-items: flex-start; justify-content: center; gap: 12px; }
.shop-goods .shop-row { flex: 0 1 auto; min-width: 0; flex-wrap: nowrap; }
/* Alles in der Reihe gibt nach, auch die Karten INNERHALB einer Angebotsgruppe
   (`.offer-group`, Abschnitt 8): sonst schiebt eine Levelaufstiegs-Auswahl die Reihe
   über den Rand, und `overflow-x: hidden` (Abschnitt 2) schneidet sie ab. */
.shop-goods .shop-row .slot,
.shop-goods .shop-row > .offer-group { flex: 0 1 auto; min-width: 0; }
/* Feste Höhe für JEDEN Auslage-Slot, auch den leeren: sonst fiel die Auslage auf die
   156 px der Grundregel zurück, sobald die letzte Karte gekauft war — der Shop wurde
   flacher, die Aufstellung sprang nach unten. `--shop-card-h` ist die Höhe einer
   Schaukarte (Abschnitt 1). */
.shop-goods .shop-row .slot { width: var(--card-w); min-height: var(--shop-card-h); }
.food-row {
  flex: 0 0 var(--food-w);
  flex-direction: column;
  gap: 8px;
}
/* Keine Mindesthöhe von 156px je Karte: zwei davon wären zusammen höher als die
   Einheitenkarte daneben, und genau die Höhe soll die Spalte nicht kosten. Statt 0
   (dann verschwand ein leergekaufter Vorratsslot zum Strich) genau die Kartenhöhe. */
.food-row > .slot { width: 100%; flex: 0 0 auto; min-height: var(--food-card-h); }

/* Der Boden unter dem Team: warmer Lichtteppich aus dem Laternenlicht.
   `--plaque-h` ist die Höhe des Schildes unter einer Einheit, `--stand` die Standlinie: die
   Unterkante der Illustration über dem Boden der Reihe (Schild + Abstand + Polsterung).
   Auf `--stand` sitzen der Bildboden des Schauplatzes (Abschnitt 20) und die
   Stellplatz-Markierungen (Abschnitt 7) — das Schild gehört UNTER den Boden, nicht auf ihn,
   sonst steht die Einheit sichtbar eine Plakettenhöhe zu hoch. */
.team-panel .team-row {
  --plaque-h: 58px;
  --stand: calc(var(--plaque-h) + 16px);
  position: relative;
  padding: 6px 4px 10px;
  border-radius: var(--r-card);
  /* Höher als die Einheiten brauchen: sonst sieht man vom Schauplatz nur einen Streifen.
     Nie kleiner als eine Einheit hoch ist, sonst gedeckelt an der Fensterhöhe. */
  align-items: flex-end;
  /* Untergrenze, keine Wunschhöhe: gefüllt wird die Reihe vom Flex-Rest der
     Kaufphase (weiter oben in diesem Abschnitt). Nie kleiner, als eine Einheit hoch ist. */
  flex: 1 1 auto;
  min-height: calc(var(--card-w) + var(--stand));
  /* Fünf Slots (plus Gerät) stehen IMMER in einer Reihe: die Slots geben nach, statt
     umzubrechen. Bei 1440 px fehlten sonst 3 px, und Slot 1 rutschte in eine zweite Zeile
     (1077 px Innenbreite gegen 5 × 208 + 4 × 10). Die Karte füllt den Slot zu 100 %, die
     Grafik ist quadratisch über die Kartenbreite – alles skaliert mit. */
  flex-wrap: nowrap;
}
/* Feste Höhe, ob belegt oder nicht: sonst schrumpft die Aufstellung, sobald ein Slot leer
   ist, und der Rest der Seite springt bei jedem Kauf. Alles steht am unteren Rand, damit
   die Einheiten auf EINER Bodenlinie stehen – wie im Ring (`.bt-arena`).
   (`--plaque-h` steht an der Reihe.) */
.team-panel .team-row > .slot {
  flex: 0 1 var(--card-w);
  width: auto;
  min-height: calc(var(--card-w) + var(--plaque-h));
  align-items: flex-end;
}

/* Die Aufstellung zeigt dieselbe Ansicht wie der Kampf: freie Einheit auf dem Boden,
   darunter die Plakette. Kein Kartengrund, kein Rahmen – der Grund ist der Schauplatz
   (Abschnitt 20), und zwei verschiedene Ansichten derselben Einheit verwirren nur.
   Vier Klassen in den Regeln, damit sie die Setting-Blöcke (`:root.theme-… .card`,
   Abschnitte 18/19) überstimmen – dasselbe Mittel wie bei `.slot.team-slot.empty`. */
.team-panel .team-slot .card.pet-card {
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  gap: 2px;
}
.team-panel .team-slot .card.pet-card:hover {
  transform: translateY(-4px);
  box-shadow: none;
  border-color: transparent;
}
/* Level und Zustände stehen ohne Kartengrund direkt auf der Grafik – ein Schatten hält sie
   auch über hellen Stellen des Schauplatzes lesbar. */
.team-panel .team-slot .card.pet-card .card-top {
  top: 0; left: 0; right: 0; padding-right: 0;
  filter: drop-shadow(0 1px 3px rgba(6, 3, 12, .95));
}
/* Bodenschatten unter der Einheit – sie steht, sie schwebt nicht (wie `.bt-art::before`). */
.team-panel .team-slot .card.pet-card .card-art::after {
  content: ''; position: absolute; left: 12%; right: 12%; bottom: -2px; height: 13%;
  border-radius: 50%;
  background: radial-gradient(50% 50%, rgba(6, 3, 12, .6), transparent 72%);
}
.team-panel .team-slot .card.pet-card .card-art > svg,
.team-panel .team-slot .card.pet-card .card-art > img { position: relative; z-index: 1; }
/* Das Schild selbst ist `.bt-plaque` aus Abschnitt 11 – dieselbe Regel, damit Aufstellung und
   Ring nicht auseinanderlaufen (auch nicht in den Setting-Farben, Abschnitte 18/19). */
.team-panel .team-slot .card-name { font-size: 12px; }
.team-panel .team-slot .stats { margin-top: 0; }
.team-panel .team-row::before {
  content: '';
  position: absolute; left: 50%; bottom: 2px; transform: translateX(-50%);
  width: min(100%, 640px); height: 46px;
  background: radial-gradient(50% 100% at 50% 100%, rgba(216, 184, 140, .22), transparent 72%);
  pointer-events: none;
  z-index: 0;
}

/* ============================================================ 7  Slots */
.slot {
  position: relative;
  flex: 0 0 var(--card-w);
  width: var(--card-w);
  min-width: 0;
  min-height: 156px;
  border-radius: var(--r-card);
  display: flex; align-items: stretch; justify-content: center;
  transition: box-shadow .16s ease, background .16s ease, transform .16s var(--ease-out);
}
.slot.small { min-height: 124px; }
.slot.empty {
  border: 2px dashed #423061;
  background: rgba(255, 255, 255, .022);
  box-shadow: inset 0 12px 26px -18px rgba(0, 0, 0, .8);
}
.slot-placeholder {
  display: flex; align-items: flex-end; justify-content: center;
  width: 100%; padding-bottom: 10px;
  color: #493a63; font-size: 24px; font-weight: 800;
}
/* Leere Team-Slots sind Stellplätze am Boden, keine leeren Karten: ein Kreidekreis im
   Sägemehl (Basis; Konvoi: Markierung im Staub, Cyberpunk: Boden-Hologramm, siehe
   19.4 / 20.4). Die Ziffer bleibt klein am Fuß – an ihr hängt die Zugreihenfolge.
   Drei Klassen in der Regel, damit sie die Setting-Regeln `.slot.empty` überstimmt. */
.slot.team-slot.empty { border-color: transparent; background: transparent; box-shadow: none; }
.slot.team-slot.empty::before {
  content: ''; position: absolute; left: 9%; right: 9%; height: 30px;
  /* Auf der Standlinie der Einheiten, nicht am Fuß des Slots: unter der Einheit hängt noch
     ihr Schild, sonst läge der Stellplatz tiefer als das, was darauf steht. Der Abzug ist die
     halbe Markierungshöhe plus die Polsterung der Reihe, gegen die `--stand` misst. */
  bottom: calc(var(--stand, 21px) - 25px);
  border-radius: 50%;
  border: 2px dashed rgba(216, 184, 140, .32);
  background: radial-gradient(50% 50%, rgba(216, 184, 140, .14), transparent 72%);
  transition: border-color .18s ease, background .18s ease, box-shadow .18s ease;
}
.slot.team-slot.empty .slot-placeholder {
  position: relative; z-index: 1;
  padding-bottom: calc(var(--stand, 13px) - 18px); font-size: 13px; color: rgba(216, 184, 140, .6);
}
.slot.team-slot.empty.dnd-target-ok { border-color: transparent; background: transparent; animation: none; box-shadow: none; }
.slot.team-slot.empty.dnd-target-ok::before {
  border-color: var(--mint); border-style: solid;
  background: radial-gradient(50% 50%, rgba(79, 214, 168, .32), transparent 72%);
  animation: spotBreathe 1.6s ease-in-out infinite;
}
.slot.team-slot.empty.dnd-hover { box-shadow: none; }
.slot.team-slot.empty.dnd-hover::before { box-shadow: 0 0 26px 3px rgba(79, 214, 168, .6); }
@keyframes spotBreathe {
  0%, 100% { box-shadow: 0 0 0 0 rgba(79, 214, 168, 0); }
  50% { box-shadow: 0 0 22px 2px rgba(79, 214, 168, .55); }
}
.offer-slot { padding-top: 15px; }
.offer-tag, .offer-group-tag {
  position: absolute; top: -3px; left: 50%; transform: translateX(-50%);
  background: linear-gradient(180deg, var(--lantern), var(--brass-deep));
  color: #241708; font-size: 10px; font-weight: 800;
  padding: 2px 8px; border-radius: var(--r-pill); z-index: 6; white-space: nowrap;
  box-shadow: 0 2px 8px rgba(255, 198, 107, .35);
}

/* Kasse: Ablage zum Verkaufen, im Shop-Panel – erscheint nur bei Team-Auswahl.
   Bleibt (eingeklappt) im DOM statt ganz zu verschwinden, sonst verliert der
   Verkaufs-Flug (fx.fly in renderer.js) sein Ziel `.sell-zone` genau in dem
   Render, der auf den Verkauf folgt. */
.shop-sell-hint {
  display: flex; justify-content: center;
  max-height: 0; opacity: 0; overflow: hidden;
  margin-top: 0;
  transition: max-height .18s var(--ease-out), opacity .18s var(--ease-out), margin-top .18s var(--ease-out);
}
.shop-sell-hint.active { max-height: 60px; opacity: 1; margin-top: 4px; margin-bottom: 10px; }
.sell-zone {
  position: relative;
  border: 2px dashed #6a4358;
  color: #d6a3b6;
  border-radius: var(--r-ctrl);
  padding: 9px 26px;
  font-size: 12px; font-weight: 700;
  background: rgba(255, 88, 113, .05);
  transition: all .18s var(--ease-out);
}

/* =========================================================== 8  Karten */
/* Emaille-Schaukarte: Messingrand, Licht von oben, warmer Schlagschatten. */
.card {
  position: relative;
  width: 100%;
  background:
    radial-gradient(100% 58% at 50% 0%, rgba(255, 214, 160, .16), transparent 62%),
    linear-gradient(180deg, var(--plum-3), #1f1730);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 7px 7px 9px;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  box-shadow: var(--lift-1);
  transition: transform .18s var(--ease-back), box-shadow .18s ease, border-color .18s ease;
}
[data-drag-kind] { touch-action: none; }
.card:hover {
  transform: translateY(-5px) scale(1.025);
  border-color: rgba(255, 198, 107, .5);
  box-shadow: var(--lift-3), 0 0 26px -6px rgba(255, 198, 107, .5);
  z-index: 8;
}
.card:focus-visible { outline: 2px solid var(--lantern); outline-offset: 3px; }
.card-top { width: 100%; display: flex; align-items: center; justify-content: space-between; min-height: 18px; }
/* Auf der Einheitenkarte liegen Level und Zustandssymbole ÜBER der Grafik
   (rechts bleibt Platz für den Preis) – so gehört die restliche Kartenhöhe
   der Illustration. */
.pet-card .card-top {
  position: absolute; top: 5px; left: 7px; right: 7px; padding-right: 26px;
  width: auto; z-index: 3; pointer-events: none;
}
.card-art {
  position: relative;
  display: flex; align-items: flex-end; justify-content: center;
  height: 60px; width: 100%;
  filter: drop-shadow(0 4px 6px rgba(8, 4, 14, .55));
}
/* Illustration so groß, wie die Karte hergibt: quadratisch über die volle
   Breite, die SVGs skalieren mit (viewBox 64×64). Für die gerenderten Plates
   (ui/sprites_plates.js) gilt dasselbe — ohne die img-Regel blieben sie auf der
   Attributgröße von 56 px stehen, während das SVG die 96 px der Karte füllte. */
.pet-card .card-art { height: auto; aspect-ratio: 1; }
.pet-card .card-art > svg,
.pet-card .card-art > img { width: 100%; height: 100%; }
.card-art svg { display: block; overflow: visible; }
.card-art img { display: block; object-fit: contain; }
.card:hover .card-art { animation: artHop .55s var(--ease-out); }
@keyframes artHop { 0%, 100% { transform: none; } 40% { transform: translateY(-3px) scale(1.05); } }
/* Vorratskarte: die Plates (ui/sprites_plates.js) füllen die Höhe, nicht die 44 px des
   size-Arguments — bei 48 px blieb unter dem Bild Leerraum und das Motiv wurde eine Briefmarke. */
.food-card .card-art { height: 64px; }
.food-card .card-art > img { height: 100%; width: auto; }
.card-name {
  font-size: 12.5px; font-weight: 700; text-align: center; letter-spacing: -.01em;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Name + Werte als eine Einheit. Auf der Schaukarte trägt sie nichts – erst im Team wird
   daraus die Plakette unter der frei stehenden Einheit (Abschnitt 6). */
.card-plaque {
  width: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  min-width: 0;
}

/* Level: Messingnieten. Level 3 glüht (Endstufe). */
.level-pips { display: flex; align-items: center; gap: 3px; }
.level-pips .lvl { font-size: 10px; font-weight: 800; color: var(--text-faint); }
.pip {
  width: 6px; height: 6px; border-radius: 50%;
  background: #3d2f56; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08);
}
.pip.on { background: linear-gradient(180deg, #8bf0cc, var(--mint-deep)); box-shadow: 0 0 7px rgba(79, 214, 168, .8); }
.pip.max {
  width: 7px; height: 7px;
  background: linear-gradient(180deg, #fff0d0, var(--brass));
  box-shadow: 0 0 10px rgba(255, 198, 107, .95);
  animation: pipGlow 2.6s ease-in-out infinite;
}
@keyframes pipGlow {
  0%, 100% { box-shadow: 0 0 8px rgba(255, 198, 107, .7); }
  50% { box-shadow: 0 0 15px rgba(255, 198, 107, 1); }
}
.level-pips.levelled { animation: pipsBump .6s var(--ease-back); }
@keyframes pipsBump { 0%, 100% { transform: none; } 45% { transform: scale(1.35); } }

.card-icons { display: flex; gap: 3px; align-items: center; }
.ailment-icon svg { display: block; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .5)); }
.ailment-icon.fx-pop { animation: badgePop .5s var(--ease-back); }
@keyframes badgePop { 0% { transform: scale(0) rotate(-30deg); } 60% { transform: scale(1.3) rotate(8deg); } 100% { transform: none; } }

/* Perk: steigt wie Luftblasen im Wasser über die Grafik – zwei bis drei
   zugleich. Gezeigt wird dieselbe Grafik wie auf der Karte, die das Perk gibt;
   das frühere Ecksymbol ist weg. `--i` (0…2) staffelt Bahn, Größe, Tempo und
   Startzeitpunkt.
   ZWEI Animationen, mit Absicht: die Blase steigt LINEAR (senkrecht bleibt das
   Tempo also konstant, sie stockt nie), und nur das Schlingern zur Seite darf
   ein- und ausschwingen. Gestiegen wird über `bottom` statt über den Transform,
   weil die Strecke dann an der Grafik hängt: oben ist Schluss, wenn die Blase
   die Oberkante berührt – dort ist sie ausgefadet und kleingeschrumpft. */
.perk-fly {
  --i: 0;
  --cycle: 4.2s;
  --size: calc(39% + var(--i) * 6%);
  position: absolute; bottom: 0;
  left: calc(50% + (var(--i) - 1) * 15%);
  width: var(--size);
  opacity: 0; pointer-events: none; z-index: 3;
  /* Gleiche Umlaufzeit für alle drei, Start jeweils um ein Drittel versetzt:
     so steigen sie gleichmäßig nacheinander und sind nie auf derselben Höhe.
     (Ungleiche Dauern hatten die Phasen auseinanderlaufen lassen – dann
     überholten sich zwei Blasen und standen kurz nebeneinander.) */
  animation: perkRise var(--cycle) linear infinite;
  animation-delay: calc(var(--i) * (var(--cycle) / -3));
}
.perk-fly svg {
  display: block; width: 100%; height: auto;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .45));
  animation: perkSway calc(1.3s + var(--i) * .25s) ease-in-out infinite alternate;
}
/* `--perk-flip` dreht die Blase auf der gespiegelten Kampfseite zurück. */
.bt-card.side-b .perk-fly { --perk-flip: -1; }
@keyframes perkRise {
  0%   { bottom: 0; opacity: 0; transform: translateX(-50%) scale(.8) scaleX(var(--perk-flip, 1)); }
  12%  { opacity: .95; }
  50%  { transform: translateX(-50%) scale(1.05) scaleX(var(--perk-flip, 1)); }
  /* Ab hier schrumpft sie und fadet aus – beides ist an der Oberkante zu Ende,
     während `bottom` weiter gleichmäßig steigt. */
  70%  { opacity: .9; transform: translateX(-50%) scale(1) scaleX(var(--perk-flip, 1)); }
  100% { bottom: calc(100% - var(--size)); opacity: 0; transform: translateX(-50%) scale(.55) scaleX(var(--perk-flip, 1)); }
}
@keyframes perkSway {
  from { transform: translateX(-15%); }
  to { transform: translateX(15%); }
}

/* Werte auf Symbolen: Faust = Angriff, Herz = Leben (die Zahl steht darauf). */
.stats { display: flex; gap: 6px; margin-top: 1px; }
/* Im Shop sitzt unten rechts der Frost-Knopf und unten links der Tier-Chip –
   die Werte rücken beiden aus dem Weg. */
.shop-slot .stats { padding-left: 18px; padding-right: 18px; }
.badge {
  position: relative; z-index: 0;      /* eigener Stapel: das Symbol liegt HINTER der Zahl */
  width: 30px; height: 29px;
  display: grid; place-items: center;
  font-size: 13px; font-weight: 800; color: #fff;
  text-shadow: 0 1px 2px rgba(6, 3, 12, .9), 0 0 5px rgba(6, 3, 12, .7);
}
.badge::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  filter: drop-shadow(0 1px 2px rgba(8, 4, 14, .6));
}
/* Angriff: Faust aus Stahl. Grau und in jedem Setting gleich – die Zahl darauf
   soll ruhig liegen, nicht mit einer Signalfarbe streiten. Die Zahl rückt etwas
   nach unten, damit sie auf der Faust und nicht auf den Knöcheln sitzt. */
.badge.atk { padding-top: 4px; }
.badge.atk::before { background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cdefs%3E%3ClinearGradient id='f' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23b9c1d0'/%3E%3Cstop offset='.55' stop-color='%23767f90'/%3E%3Cstop offset='1' stop-color='%234a5364'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg stroke='%2321262f' stroke-width='1.5' stroke-linejoin='round' stroke-linecap='round'%3E%3Crect x='9' y='25.4' width='15' height='5.6' rx='2.4' fill='%233b4351'/%3E%3Crect x='4.6' y='8' width='22.8' height='21' rx='7' fill='url(%23f)'/%3E%3Ccircle cx='9.5' cy='9' r='3.6' fill='url(%23f)'/%3E%3Ccircle cx='15.5' cy='8.2' r='3.8' fill='url(%23f)'/%3E%3Ccircle cx='21.5' cy='8.8' r='3.6' fill='url(%23f)'/%3E%3Ccircle cx='26.2' cy='11.2' r='3.1' fill='url(%23f)'/%3E%3Crect x='2.2' y='16.2' width='9.8' height='7.4' rx='3.7' fill='url(%23f)' transform='rotate(-7 7 20)'/%3E%3C/g%3E%3C/svg%3E") center/contain no-repeat; }
/* Leben: rotes Herz. Nur die Form ist gezeichnet, die Farbe kommt aus dem
   Token des Settings. */
.badge.hp { padding-bottom: 5px; }
.badge.hp::before {
  background: linear-gradient(180deg, rgba(255, 255, 255, .5), rgba(255, 255, 255, 0) 58%), var(--punch);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23000' d='M16 28.8l-1.8-1.7C7 20.5 2.3 16.2 2.3 10.8 2.3 6.4 5.8 2.9 10.2 2.9 c2.5 0 4.7 1.1 6 3 1.3-1.9 3.5-3 6-3 4.4 0 7.9 3.5 7.9 7.9 0 5.4-4.7 9.7-11.9 16.3L16 28.8z'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23000' d='M16 28.8l-1.8-1.7C7 20.5 2.3 16.2 2.3 10.8 2.3 6.4 5.8 2.9 10.2 2.9 c2.5 0 4.7 1.1 6 3 1.3-1.9 3.5-3 6-3 4.4 0 7.9 3.5 7.9 7.9 0 5.4-4.7 9.7-11.9 16.3L16 28.8z'/%3E%3C/svg%3E") center/contain no-repeat;
}
.badge.temp::before { filter: drop-shadow(0 0 5px var(--temp)); }
.badge em {                          /* temporärer Buff als kleine Nietenzahl */
  position: absolute; top: -4px; right: -6px;
  font-size: 9px; font-style: normal; font-weight: 800;
  color: #241708; text-shadow: none;
  background: linear-gradient(180deg, var(--lantern), var(--brass-deep));
  border-radius: var(--r-pill); padding: 0 4px;
  box-shadow: 0 1px 3px rgba(8, 4, 14, .6);
}
.badge.pulse { animation: statPulse .42s var(--ease-back); }
@keyframes statPulse {
  0% { transform: scale(1); } 45% { transform: scale(1.4); filter: brightness(1.3); } 100% { transform: scale(1); }
}
.badge.up { animation: statUp .55s var(--ease-back); }
.badge.down { animation: statDown .45s ease; }
@keyframes statUp {
  0% { transform: scale(1); } 40% { transform: scale(1.45) translateY(-3px); box-shadow: 0 0 18px rgba(111, 217, 138, .9); }
  100% { transform: scale(1); }
}
@keyframes statDown {
  0% { transform: scale(1); } 40% { transform: scale(.82); filter: saturate(.5); } 100% { transform: scale(1); }
}

.cost-badge {
  position: absolute; top: 5px; right: 5px;
  background: linear-gradient(180deg, var(--lantern), var(--brass-deep));
  color: #251808;
  font-size: 10.5px; font-weight: 800;
  border-radius: var(--r-pill); padding: 1px 7px;
  box-shadow: 0 2px 6px rgba(8, 4, 14, .5);
  z-index: 2;
}
.food-card .cost-badge { top: 3px; right: 3px; }

.freeze-btn {
  position: absolute; bottom: 5px; right: 5px;
  width: 23px; height: 23px; line-height: 1;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, var(--plum-3), var(--plum));
  color: #8574a3;
  font-size: 12px; cursor: pointer; padding: 0;
  transition: transform .14s var(--ease-back), color .14s ease, box-shadow .14s ease;
  z-index: 5;
}
.freeze-btn:hover { color: var(--frost); transform: scale(1.15) rotate(15deg); box-shadow: 0 0 12px rgba(134, 217, 255, .55); }
.freeze-btn.on {
  background: linear-gradient(180deg, #2b5c78, #1b3d52);
  color: var(--frost); border-color: var(--frost);
  box-shadow: 0 0 12px rgba(134, 217, 255, .5);
}
.freeze-btn:focus-visible { outline: 2px solid var(--frost); outline-offset: 1px; }

/* Tier: unten links, spiegelbildlich zum Frost-Knopf – Sechseck in derselben
   Stahloptik wie die Angriffs-Faust, damit es als Rang-Chip und nicht als
   dritter Wert-Badge liest. Nur im Shop sichtbar (an `cost` gekoppelt, das
   Team zeigt keine Preise). */
.tier-badge {
  position: absolute; bottom: 5px; left: 5px;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  font-size: 11px; font-weight: 800; color: #fff;
  text-shadow: 0 1px 2px rgba(6, 3, 12, .9), 0 0 4px rgba(6, 3, 12, .7);
  z-index: 2;
}
.tier-badge::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  filter: drop-shadow(0 1px 2px rgba(8, 4, 14, .55));
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23b9c1d0'/%3E%3Cstop offset='.55' stop-color='%23767f90'/%3E%3Cstop offset='1' stop-color='%234a5364'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='url(%23g)' stroke='%2321262f' stroke-width='1.5' stroke-linejoin='round' d='M16 2 28 9 28 23 16 30 4 23 4 9Z'/%3E%3C/svg%3E") center/contain no-repeat;
}

.frost {
  position: absolute; inset: 0; border-radius: var(--r-card);
  background:
    linear-gradient(150deg, rgba(134, 217, 255, .3), rgba(134, 217, 255, .06) 55%, rgba(134, 217, 255, .26)),
    repeating-linear-gradient(58deg, rgba(255, 255, 255, .09) 0 2px, transparent 2px 9px);
  border: 2px solid rgba(134, 217, 255, .7);
  box-shadow: inset 0 0 18px rgba(134, 217, 255, .35);
  pointer-events: none;
  z-index: 3;
}
.slot.frozen .card { border-color: var(--frost); }

/* Frost-Schwung beim Einfrieren (fx.frostSweep) */
.fx-sweep {
  position: absolute; inset: 0; border-radius: var(--r-card);
  pointer-events: none; z-index: 6; overflow: hidden;
}
.fx-sweep::before {
  content: ''; position: absolute; inset: -30%;
  background: linear-gradient(115deg, transparent 34%, rgba(190, 240, 255, .85) 50%, transparent 66%);
  transform: translateX(-110%);
  animation: sweep .68s var(--ease-out) forwards;
}
@keyframes sweep { to { transform: translateX(110%); } }

/* --------------------------------------------------------- Toy-Karte */
.toy-slot { width: var(--card-w); }
.toy-card {
  background:
    radial-gradient(100% 58% at 50% 0%, rgba(214, 186, 255, .2), transparent 62%),
    linear-gradient(180deg, #3a2a5c, #241a3c);
  border-color: #5a4487;
  cursor: default;
  animation: toyFloat 4.2s ease-in-out infinite;
}
.toy-card:hover { transform: translateY(-5px) scale(1.025); border-color: var(--neon); box-shadow: var(--lift-3), 0 0 26px -6px rgba(168, 124, 255, .6); }
@keyframes toyFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
.toy-tag {
  font-size: 9px; font-weight: 800; letter-spacing: .04em;
  color: #e6d9ff; background: rgba(168, 124, 255, .28);
  border-radius: var(--r-pill); padding: 1px 7px;
  box-shadow: inset 0 0 0 1px rgba(168, 124, 255, .5);
}
.toy-turns { font-size: 10px; color: var(--text-dim); text-align: center; }
.toy-turns.urgent { color: var(--lantern); font-weight: 800; }

/* Countdown-Ring: wie viele Runden hält das Spielzeug noch. */
.toy-ring { position: relative; width: 34px; height: 34px; margin: 2px auto 0; }
.toy-ring svg { display: block; transform: rotate(-90deg); }
.toy-ring circle { fill: none; stroke-width: 3.5; stroke-linecap: round; }
.toy-ring .track { stroke: rgba(255, 255, 255, .1); }
.toy-ring .fill {
  stroke: var(--neon);
  transition: stroke-dashoffset .6s var(--ease-out);
  filter: drop-shadow(0 0 4px rgba(168, 124, 255, .8));
}
.toy-ring.urgent .fill { stroke: var(--lantern); filter: drop-shadow(0 0 6px rgba(255, 198, 107, .9)); animation: ringPulse 1.4s ease-in-out infinite; }
@keyframes ringPulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
.toy-ring-num {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 800; color: var(--text);
}

/* ------------------------------------- Level-Up-Angebotsgruppe */
.offer-group { position: relative; padding: 18px 12px 6px; }
.offer-group::before,
.offer-group::after {
  content: ''; position: absolute; top: 13px; bottom: 2px; width: 9px;
  border: 2px solid rgba(232, 169, 74, .8);
}
.offer-group::before { left: 0; border-right: none; border-radius: 7px 0 0 7px; }
.offer-group::after { right: 0; border-left: none; border-radius: 0 7px 7px 0; }
.offer-group-row { display: flex; gap: 9px; }
.offer-slot.in-group { padding-top: 0; }
.offer-slot .card { border-color: rgba(232, 169, 74, .45); }

/* Das ganze Shop-Panel ist Abwurfziel zum Verkaufen. */
.shop-panel { position: relative; }
.shop-panel.dnd-target-no { opacity: 1; box-shadow: var(--lift-2); }
.shop-panel.dnd-target-ok {
  box-shadow: var(--lift-2), inset 0 0 0 2px rgba(255, 88, 113, .5);
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(255, 88, 113, .1), transparent 60%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
}
.shop-panel.dnd-target-ok::after {
  content: 'Loslassen = verkaufen';
  position: absolute; bottom: 10px; right: 14px;
  font-size: 11.5px; font-weight: 800; color: #ffb0bd;
  pointer-events: none;
}
.shop-panel.dnd-hover {
  box-shadow: var(--lift-2), inset 0 0 0 3px var(--punch);
  transform: none;
}

/* ========================================================== 9  Tooltip */
.tooltip {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%; transform: translateX(-50%) translateY(6px) scale(.97);
  width: 238px;
  background: linear-gradient(180deg, #221833, #170f24);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 9px 11px;
  font-size: 12px;
  color: var(--text);
  box-shadow: 0 16px 36px -8px rgba(6, 3, 12, .9), 0 0 0 1px rgba(255, 198, 107, .12);
  opacity: 0; visibility: hidden;
  transition: opacity .16s ease, transform .2s var(--ease-back), visibility .16s;
  z-index: 60;
  pointer-events: none;
  text-align: left;
}
.tooltip::after {                     /* Zeiger */
  content: ''; position: absolute; top: 100%; left: 50%; margin-left: -6px;
  border: 6px solid transparent; border-top-color: #170f24;
}
.card:hover .tooltip,
.card:focus .tooltip,
.card:focus-within .tooltip,
.card.dnd-selected .tooltip { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0) scale(1); }

/* Randkarten: Tooltip an der Karte ausrichten statt zentriert, sonst ragt er
   aus dem Body heraus (der horizontal nie scrollen darf). */
.row > .slot:last-child .tooltip,
.row > .offer-group:last-child .offer-group-row > .slot:last-child .tooltip {
  left: auto; right: -6px; transform: translateY(6px) scale(.97);
}
.row > .slot:last-child .card:hover .tooltip,
.row > .slot:last-child .card:focus .tooltip,
.row > .slot:last-child .card:focus-within .tooltip,
.row > .slot:last-child .card.dnd-selected .tooltip,
.row > .offer-group:last-child .offer-group-row > .slot:last-child .card:hover .tooltip {
  transform: translateY(0) scale(1);
}
.row > .slot:last-child .tooltip::after { left: auto; right: 46px; }

.row > .slot:first-child .tooltip { left: -6px; right: auto; transform: translateY(6px) scale(.97); }
.row > .slot:first-child .card:hover .tooltip,
.row > .slot:first-child .card:focus .tooltip,
.row > .slot:first-child .card:focus-within .tooltip,
.row > .slot:first-child .card.dnd-selected .tooltip { transform: translateY(0) scale(1); }
.row > .slot:first-child .tooltip::after { left: 46px; margin-left: 0; }

/* Sicherheitsnetz für sehr schmale Fenster */
.tooltip { max-width: calc(100vw - 28px); }
body.dnd-active .tooltip { opacity: 0 !important; visibility: hidden !important; }
.tooltip strong { display: block; font-size: 13.5px; color: #fff3df; }
.tt-meta { color: var(--text-dim); font-size: 11px; margin-bottom: 5px; }
.tt-fine { color: var(--text-faint); font-size: 11px; font-style: italic; }
.tt-perk { color: var(--lantern); font-size: 11px; }
.tt-ail { color: var(--punch); font-size: 11px; }

/* ==================================================== 10  Drag & Drop */
.dnd-ghost {
  position: fixed; top: 0; left: 0;
  z-index: 999;
  pointer-events: none;
  opacity: .95;
  transform-origin: top left;
  box-shadow: 0 22px 44px -10px rgba(6, 3, 12, .95), 0 0 30px -8px rgba(255, 198, 107, .5);
  rotate: -4deg;
  animation: ghostLift .18s var(--ease-back);
}
@keyframes ghostLift { from { rotate: 0deg; } to { rotate: -4deg; } }
.dnd-ghost .tooltip, .dnd-ghost .freeze-btn { display: none; }
.dnd-dragging { opacity: .3; filter: grayscale(.5); }
.dnd-selected {
  border-color: var(--lantern) !important;
  box-shadow: var(--lift-2), 0 0 0 2px var(--lantern), 0 0 24px -4px rgba(255, 198, 107, .7) !important;
}
.dnd-target-ok {
  box-shadow: inset 0 0 0 2px rgba(79, 214, 168, .65);
  background: rgba(79, 214, 168, .07);
}
.slot.empty.dnd-target-ok { border-color: var(--mint); border-style: solid; animation: targetBreathe 1.6s ease-in-out infinite; }
@keyframes targetBreathe {
  0%, 100% { box-shadow: inset 0 0 0 2px rgba(79, 214, 168, .4); }
  50% { box-shadow: inset 0 0 0 2px rgba(79, 214, 168, .9), 0 0 20px -4px rgba(79, 214, 168, .55); }
}
/* Nur kleine Ziele ausblenden. Ein ganzes Panel abzudunkeln würde das eigene
   Team grau machen – und `opacity < 1` erzeugt einen Stacking-Context, der
   Tooltips unter die Knopfleiste schieben würde. */
.dnd-target-no { opacity: .5; }
.panel.dnd-target-no { opacity: 1; }
.team-panel.dnd-target-no { box-shadow: var(--lift-2); }
.dnd-hover {
  box-shadow: inset 0 0 0 3px var(--mint), 0 0 26px -4px rgba(79, 214, 168, .7);
  transform: scale(1.05);
}
.dnd-hover-bad { box-shadow: inset 0 0 0 3px var(--punch); }
.sell-zone.dnd-target-ok { border-color: var(--punch); border-style: solid; color: #ffc3cd; background: rgba(255, 88, 113, .14); }
.sell-zone.dnd-hover { background: rgba(255, 88, 113, .3); transform: scale(1.05); box-shadow: 0 0 26px -6px rgba(255, 88, 113, .8); }
.dnd-reject { animation: reject .34s ease; }
@keyframes reject {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-6px); } 75% { transform: translateX(6px); }
}

/* --- Vorschau: die Aufstellung rückt schon, bevor abgelegt wird ---------------
   `ui/renderer.js` (`showDropPreview`) setzt den `transform` je Karte auf die
   Strecke zum künftigen Slot; hier steht nur, wie sie dorthin gleitet. Die
   Transition hängt an `.dnd-previewing` und nicht dauerhaft an der Karte, damit
   sie den FLIP-Flügen aus `ui/fx.js` nicht dazwischenfunkt (die bringen ihre
   eigene Transition inline mit). */
.team-row.dnd-previewing .card.pet-card { transition: transform .18s var(--ease-out); }
/* Die Strecke kommt als `--dnd-shift` aus dem Renderer. Vier Klassen im Selektor,
   damit die Verschiebung die Hover-Regel aus Abschnitt 6 überstimmt.
   Verschobene Karten sind für den Zeiger durchlässig: sonst deckt eine Karte an
   ihrem Vorschau-Platz den Slot darunter ab und `elementFromPoint` liefert ihren
   alten Slot als Abwurfziel (die Vorschau nähme sich selbst zurück). */
.team-panel .team-slot .card.pet-card.dnd-shifted {
  transform: translateX(var(--dnd-shift, 0px));
  pointer-events: none;
}
/* Der überfahrene Slot darf sich nicht aufblasen, während die Karten in ihm
   verrutschen – der Landeplatz-Ring unten ist das ruhigere Signal. */
.team-row.dnd-previewing .team-slot.dnd-hover { transform: none; }

/* Landeplatz: hier kommt die gezogene bzw. gekaufte Einheit hin. Sitzt auf der
   Standlinie, damit er zum Boden der Reihe passt (Abschnitt 6). */
.team-slot.dnd-landing::after {
  content: '';
  position: absolute; left: 10%; right: 10%; bottom: 4px; height: 40px;
  border-radius: 50% / 60%;
  border: 2px dashed var(--mint);
  background: radial-gradient(60% 100% at 50% 100%, rgba(79, 214, 168, .24), transparent 74%);
  pointer-events: none;
  animation: targetBreathe 1.6s ease-in-out infinite;
}

/* Vereinen statt Einfügen: niemand rückt, die Einheit im Ziel leuchtet. */
.team-slot.dnd-merge .card.pet-card {
  filter: drop-shadow(0 0 10px rgba(79, 214, 168, .85));
  animation: mergeHint .9s ease-in-out infinite;
}
@keyframes mergeHint {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.06); }
}

/* =========================================================== 11  Kampf */
/* Der Ring steht mittig in der Fensterhöhe, nicht oben angeschlagen: seit das
   Spielfeld die ganze Höhe füllt (Abschnitt 3), wäre darunter sonst eine leere
   Fläche. Die Höhe des Rings selbst bleibt fest – sie ist die Rechengrundlage der
   Kartenbreite (`cqh`, unten). */
.battle-view { display: flex; flex-direction: column; gap: 12px; flex: 1 1 auto; justify-content: center; }
.bt-bar {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between;
  background: linear-gradient(180deg, var(--plum-2), var(--plum));
  border: 1px solid var(--line); border-radius: var(--r-ctrl); padding: 9px 14px;
  box-shadow: var(--lift-1);
}
.bt-labels { display: flex; align-items: center; gap: 12px; font-weight: 800; }
.bt-label.a { color: var(--mint); }
.bt-label.b { color: var(--atk); }
.bt-vs {
  color: #2a1f3d; font-size: 11px; font-weight: 800;
  background: linear-gradient(180deg, var(--lantern), var(--brass-deep));
  border-radius: var(--r-pill); padding: 1px 8px;
}
.bt-controls { display: flex; align-items: center; gap: 6px; }

/* Der Ring: Sägemehlboden unter einem Laternenkegel. Mit Schauplatz (Abschnitt 20) liegen
   die beiden Schauplätze in `.bt-ground` dahinter, der Boden bleibt als dunkler Streifen. */
.bt-field {
  position: relative;
  display: flex; flex-direction: column; justify-content: flex-end;
  /* `--stand`: Unterkante der Illustrationen über dem Boden des Rings – Polsterung des
     Feldes (2) und der Arena (24) plus Plakette (57) plus Abstand. Darauf sitzt der
     Bildboden des Schauplatzes (Abschnitt 20), damit die Einheiten auf dem Boden stehen
     und nicht eine Plakettenhöhe darüber. */
  --stand: 85px;
  /* `height` statt `min-height`: erst eine feste (nicht nur minimale) Höhe zählt als
     „definite size" für die `cqh`-Rechnung unten – mit `min-height` bliebe `cqh` 0.
     `overflow: hidden` (unten) fängt den Fall ab, dass Inhalt trotzdem höher wäre. */
  height: max(340px, min(44vh, 460px));
  /* Fixiert Breite/Höhe für die `cqw`/`cqh`-Rechnung unten auf diese Box, unabhängig
     vom Karteninhalt – sonst wäre die Kartenbreite von der Kartenbreite abhängig. */
  container-type: size;
  padding: 44px 12px 2px;      /* untere Luft steckt in `.bt-arena` (Sturzanimation) */
  background:
    radial-gradient(58% 34% at 50% 100%, rgba(216, 184, 140, .22), transparent 72%),
    radial-gradient(60% 46% at 50% -6%, rgba(255, 198, 107, .17), transparent 68%),
    linear-gradient(180deg, #1b1329 0%, #241a35 62%, #2b1f3c 100%);
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  box-shadow: var(--lift-2), inset 0 -30px 60px -30px rgba(0, 0, 0, .7);
  overflow: hidden;
}
/* Geteilter Grund: zwei Hälften, jede mit dem Schauplatz ihrer Seite (Abschnitt 20).
   Ohne Schauplatz bleiben sie leer und der Verlauf des Rings steht allein. */
.bt-ground {
  position: absolute; inset: 0; z-index: 0;
  display: flex; pointer-events: none;
}
.bt-ground-half { flex: 1 1 0; min-width: 0; }

/* Boden des Rings: ein dunkler Streifen, auf dem die Einheiten stehen. Kein Rahmen um
   die Einheiten mehr – die Sprites stehen frei, Schatten am Fuß (`.bt-art::before`). */
.bt-field::before {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; height: 110px;
  z-index: 1;
  background:
    linear-gradient(180deg, transparent, rgba(6, 3, 12, .38) 45%, rgba(6, 3, 12, .6));
  pointer-events: none;
}
.bt-field.fx-shake { animation: fieldShake .3s ease; }
@keyframes fieldShake {
  0%, 100% { transform: translate(0, 0); }
  20% { transform: translate(calc(var(--fx-shake, 4px) * -1), 1px); }
  45% { transform: translate(var(--fx-shake, 4px), -1px); }
  70% { transform: translate(calc(var(--fx-shake, 4px) * -.5), 1px); }
}
/* Pan-Fläche: schrumpft nie unter die Karten, scrollt bei Bedarf in sich. */
.bt-arena {
  position: relative; z-index: 2;
  flex: 0 0 auto;
  display: flex; align-items: flex-end;
  width: 100%;
  /* Luft nach oben UND unten: `overflow-x: auto` klemmt auch senkrecht, darum
     bekommen die Kartenanimationen (Anlauf, Puls, Sturz beim Sterben) hier
     Platz statt einer Kante. Der Ring gibt seine untere Polsterung dafür ab,
     damit die Karten weiter auf der Bodenlinie stehen. */
  padding: 30px 0 24px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.bt-arena::-webkit-scrollbar { display: none; }
.bt-half { flex: 1 1 0; min-width: max-content; display: flex; }
.bt-toy-holder { flex: 0 0 auto; }
.half-a { justify-content: flex-end; }
.half-b { justify-content: flex-start; }
.bt-mid {
  width: 30px; flex: 0 0 30px; align-self: stretch;
  background: linear-gradient(180deg, transparent, rgba(255, 198, 107, .1) 45%, transparent);
}
.bt-side { display: flex; gap: 7px; align-items: flex-end; min-width: 0; flex: 0 1 auto; }
.bt-side-a { flex-direction: row-reverse; }
.bt-side-b { flex-direction: row; }

/* Eine Einheit im Ring: freies Sprite auf dem Boden, darunter die Stat-Plakette.
   Kein Kärtchen, kein Rahmen – die Grafik trägt die Seite (A schaut nach rechts,
   B ist gespiegelt), die Plakette färbt den Rand nach Seite. */
.bt-card {
  position: relative;
  /* Schrumpfbar: bei vollem Feld (5 Tiere + Toy je Seite) müssen alle in den
     Ring passen, ohne dass etwas abgeschnitten wird. */
  flex: 0 1 var(--bt-card-w, 128px);
  min-width: 0;
  width: var(--bt-card-w, 128px);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  transition: transform .25s var(--ease-out), opacity .35s ease, filter .2s ease;
}
.bt-card.side-b .bt-art { transform: scaleX(-1); }
.bt-card .bt-art {
  position: relative; width: 100%; aspect-ratio: 1;
  display: flex; align-items: flex-end; justify-content: center;
}
.bt-card .bt-art > svg,
.bt-card .bt-art > img {
  position: relative; z-index: 1;
  width: 100%; height: 100%; object-fit: contain;
  filter: drop-shadow(0 6px 8px rgba(8, 4, 14, .6));
}
/* Bodenschatten unter dem Sprite – die Einheit steht, sie schwebt nicht. */
.bt-card .bt-art::before {
  content: ''; position: absolute; left: 12%; right: 12%; bottom: -3px; height: 14%;
  border-radius: 50%;
  background: radial-gradient(50% 50%, rgba(6, 3, 12, .62), transparent 72%);
}
/* Plakette: Name und Werte auf einem dunklen Schild, Kante in der Seitenfarbe. Dieselbe
   Plakette trägt die Aufstellung (`.card-plaque`, Abschnitt 6) – dort ist die eigene Seite
   gemeint, also gilt dort die Kante von Seite A. */
.bt-plaque,
.team-panel .card-plaque {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  width: auto; max-width: 100%; min-width: 72%;
  padding: 3px 7px 4px;
  border-radius: 9px;
  background: linear-gradient(180deg, rgba(20, 13, 34, .92), rgba(12, 7, 22, .92));
  border: 1px solid var(--line);
  box-shadow: 0 6px 14px -6px rgba(6, 3, 12, .9);
}
.bt-card.side-a .bt-plaque,
.team-panel .card-plaque { border-color: rgba(79, 214, 168, .45); }
.bt-card.side-b .bt-plaque { border-color: rgba(255, 131, 96, .45); }
.bt-name { font-size: 12px; font-weight: 700; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bt-stats { display: flex; gap: 4px; max-width: 100%; }
.bt-stats .badge { width: 26px; height: 25px; font-size: 12px; }
.bt-stats .badge.hp { padding-bottom: 4px; }
.bt-icons { display: flex; gap: 2px; min-height: 0; }
.bt-icons:empty { display: none; }

/* Auftritt: Teams laufen von beiden Seiten in den Ring. */
.bt-card.bt-march-a { animation: marchA var(--bt-dur, .6s) var(--ease-out) both; }
.bt-card.bt-march-b { animation: marchB var(--bt-dur, .6s) var(--ease-out) both; }
@keyframes marchA {
  from { opacity: 0; transform: translateX(-70px) scale(.9); } to { opacity: 1; transform: none; }
}
@keyframes marchB {
  from { opacity: 0; transform: translateX(70px) scale(.9); } to { opacity: 1; transform: none; }
}

/* Sturz: das Sprite kippt zur Seite und kommt am Boden zur Ruhe – es bleibt als
   Wrack liegen, damit man sieht, von wem die Ausfall-Fähigkeit ausgeht, die
   gleich danach zuschlägt (abgeräumt beim Nachrücken der Reihe, battleView.js
   `dropWrecks`). Animiert werden Sprite und Plakette, NICHT die Karte selbst:
   nur so bleiben Platz in der Reihe, Sprechblase und Projektilstart an ihrem
   Ort, und das Endbild ist eine Ruhelage statt einer eingefrorenen Bewegung.
   Seite B ist gespiegelt (`scaleX(-1)`) – das muss die Animation mitführen,
   sonst klappt das Sprite mitten im Sturz zurück. */
.bt-card.fainting { z-index: 2; }
.bt-card.fainting .bt-art { animation: wreckFall var(--bt-dur, .46s) cubic-bezier(.36, .03, .5, 1) forwards; }
.bt-card.side-b.fainting .bt-art { animation-name: wreckFallB; }
.bt-card.fainting .bt-plaque { animation: wreckPlaque var(--bt-dur, .46s) ease-out forwards; }
@keyframes wreckFall {
  0% { transform: none; opacity: 1; filter: none; }
  22% { transform: translate(-8px, -12px) rotate(-13deg) scale(1.03); filter: brightness(1.7) saturate(.5); }
  100% { transform: translate(-22px, 34px) rotate(-82deg) scale(.8); opacity: .72; filter: brightness(.62) saturate(.35); }
}
@keyframes wreckFallB {
  0% { transform: scaleX(-1); opacity: 1; filter: none; }
  22% { transform: translate(8px, -12px) rotate(13deg) scale(1.03) scaleX(-1); filter: brightness(1.7) saturate(.5); }
  100% { transform: translate(22px, 34px) rotate(82deg) scale(.8) scaleX(-1); opacity: .72; filter: brightness(.62) saturate(.35); }
}
/* Die Plakette geht mit: ein Wrack braucht kein Namensschild mehr. */
@keyframes wreckPlaque {
  0% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateY(7px) scale(.9); }
}
.bt-card.summoned { animation: popin var(--bt-dur, .46s) var(--ease-back); }
.bt-card.bt-appear { animation: popin var(--bt-dur, .38s) var(--ease-back); }
@keyframes popin {
  0% { transform: scale(.3); opacity: 0; } 65% { transform: scale(1.12); opacity: 1; } 100% { transform: scale(1); }
}

/* Angriff: die beiden Vordersten laufen zur Mitte und stoßen zusammen. */
.bt-card.lunge-right { animation: lungeR var(--bt-dur, .42s) cubic-bezier(.3, .9, .3, 1); z-index: 12; }
.bt-card.lunge-left { animation: lungeL var(--bt-dur, .42s) cubic-bezier(.3, .9, .3, 1); z-index: 12; }
@keyframes lungeR {
  0% { transform: translateX(0) rotate(0); }
  22% { transform: translateX(-8px) rotate(-3deg) scale(.98); }
  46% { transform: translateX(30px) rotate(6deg) scale(1.08); }
  60% { transform: translateX(18px) rotate(-2deg) scale(1.02); }
  100% { transform: translateX(0) rotate(0); }
}
@keyframes lungeL {
  0% { transform: translateX(0) rotate(0); }
  22% { transform: translateX(8px) rotate(3deg) scale(.98); }
  46% { transform: translateX(-30px) rotate(-6deg) scale(1.08); }
  60% { transform: translateX(-18px) rotate(2deg) scale(1.02); }
  100% { transform: translateX(0) rotate(0); }
}
/* Stärkung/Schwächung: das Sprite selbst leuchtet – ein Kastenglanz hätte auf dem
   rahmenlosen Sprite ein Rechteck gezeichnet. */
.bt-card.buffing { animation: buffPulse var(--bt-dur, .42s) ease; }
.bt-card.debuffing { animation: debuffPulse var(--bt-dur, .42s) ease; }
@keyframes buffPulse {
  0%, 100% { transform: scale(1); filter: none; }
  45% { transform: scale(1.1); filter: drop-shadow(0 0 14px rgba(111, 217, 138, .95)) brightness(1.25); }
}
@keyframes debuffPulse {
  0%, 100% { transform: scale(1); filter: none; }
  45% { transform: scale(.93); filter: drop-shadow(0 0 12px rgba(255, 88, 113, .9)) saturate(.5); }
}
/* Treffer-Blitz: auf Karten (Markt) eine weiße Fläche, im Ring hellt das Sprite auf. */
.fx-hit::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  background: rgba(255, 245, 225, .68);
  animation: hitFade .26s ease-out forwards;
  pointer-events: none; z-index: 9;
}
.bt-card.fx-hit::before { display: none; }
.bt-card.fx-hit .bt-art > svg,
.bt-card.fx-hit .bt-art > img { animation: hitGlow .26s ease-out forwards; }
@keyframes hitFade { from { opacity: 1; } to { opacity: 0; } }
@keyframes hitGlow {
  from { filter: brightness(2.4) saturate(.2) drop-shadow(0 0 16px rgba(255, 245, 225, .95)); }
  to { filter: drop-shadow(0 6px 8px rgba(8, 4, 14, .6)); }
}

/* Aufprall in der Mitte */
.bt-clash {
  position: absolute; bottom: 52px; left: 50%;
  width: 70px; height: 70px; margin-left: -35px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 250, 230, .98), rgba(255, 198, 107, .55) 45%, rgba(255, 88, 113, .2) 65%, transparent 72%);
  opacity: 0; pointer-events: none;
  transform: scale(.3);
  z-index: 25;
}
.bt-clash.flash { animation: clashFlash var(--bt-dur, .36s) ease-out; }
@keyframes clashFlash {
  0% { opacity: 0; transform: scale(.25) rotate(0); }
  22% { opacity: 1; transform: scale(1.15) rotate(20deg); }
  100% { opacity: 0; transform: scale(1.9) rotate(50deg); }
}

/* Kartenbreite nach Belegung: battleView setzt data-count = Tiere (inkl. Toy)
   auf der voller besetzten Seite. So passt auch ein volles Feld in den Ring,
   und beide Seiten bleiben gleich groß – auch wenn eine Seite dünner besetzt ist.
   Die Breite füllt dabei die tatsächlich verfügbare Ringhälfte (`cqw`, siehe
   `container-type` oben): Ringbreite minus Mittelsteg (30px) durch die Anzahl
   Karten je Seite, minus deren Lücken (7px). Nach oben deckelt `cqh` die
   Kartenbreite auf die Standfläche des Rings (Kunstwerk ist quadratisch, `--stand`
   plus Polsterung/Plakette ≈ 145px), damit nichts über den Ring hinauswächst; nach
   unten bleibt die bisherige Handmaß als Minimum erhalten. */
.bt-field[data-count="1"] { --bt-card-w: clamp(128px, calc(50cqw - 15px), calc(100cqh - 145px)); }
.bt-field[data-count="2"] { --bt-card-w: clamp(128px, calc((50cqw - 15px - 7px)  / 2), calc(100cqh - 145px)); }
.bt-field[data-count="3"] { --bt-card-w: clamp(128px, calc((50cqw - 15px - 14px) / 3), calc(100cqh - 145px)); }
.bt-field[data-count="4"] { --bt-card-w: clamp(118px, calc((50cqw - 15px - 21px) / 4), calc(100cqh - 145px)); --bt-toy-w: calc(var(--bt-card-w) * .65); }
.bt-field[data-count="5"] { --bt-card-w: clamp(100px, calc((50cqw - 15px - 28px) / 5), calc(100cqh - 145px)); --bt-toy-w: calc(var(--bt-card-w) * .65); }
.bt-field[data-count="6"] { --bt-card-w: clamp( 86px, calc((50cqw - 15px - 35px) / 6), calc(100cqh - 145px)); --bt-toy-w: calc(var(--bt-card-w) * .6); }
.bt-field[data-count="5"] .bt-name,
.bt-field[data-count="6"] .bt-name { font-size: 10.5px; }
.bt-field[data-count="6"] .bt-plaque { padding: 2px 5px 3px; }
.bt-field[data-count="6"] .bt-stats .badge { width: 23px; height: 22px; font-size: 11px; }

/* Toy im Kampf */
.bt-toy-holder { display: flex; align-items: flex-end; }
.holder-a { margin-right: 10px; }
.holder-b { margin-left: 10px; }
.bt-toy {
  position: relative;
  flex: 0 1 var(--bt-toy-w, 76px);
  min-width: 0;
  width: var(--bt-toy-w, 76px);
  background: linear-gradient(180deg, #3a2a5c, #241a3c);
  border: 1px solid #5a4487;
  border-radius: var(--r-card);
  padding: 5px;
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  box-shadow: var(--lift-1);
  animation: toyFloat 4.2s ease-in-out infinite;
}
.bt-toy-art { height: 44px; display: flex; align-items: center; justify-content: center; }
.bt-toy-name {
  font-size: 10px; font-weight: 700; color: #e6d9ff;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bt-toy.bt-toy-appear { animation: popin var(--bt-dur, .5s) var(--ease-back); }
.bt-toy.breaking { animation: toyBreak var(--bt-dur, .52s) ease-in forwards; }
@keyframes toyBreak {
  0% { transform: none; opacity: 1; }
  18% { transform: translateX(-4px) rotate(-7deg) scale(1.06); filter: brightness(1.6); }
  38% { transform: translateX(4px) rotate(7deg); }
  100% { transform: translateY(20px) rotate(-18deg) scale(.6); opacity: 0; }
}

/* Sprechblase für Fähigkeits-Auslöser. Eigene Ebene über dem Ring, weil sie in
   der Karte selbst von `.bt-arena`/`.bt-field` abgeschnitten würde. Position
   und Zeiger (--arrow-x) setzt battleView in Feld-Koordinaten. */
.bt-bubbles { position: absolute; inset: 0; pointer-events: none; z-index: 28; }
.bt-bubble {
  position: absolute; left: 0; bottom: 0;
  width: max-content; max-width: min(220px, calc(100% - 12px));
  transform: translateY(6px) scale(.9);
  transform-origin: bottom center;
  background: linear-gradient(180deg, #fffaf0, #f0e6ff);
  color: #241a35;
  font-size: 11px; font-weight: 700; line-height: 1.3; text-align: center;
  padding: 6px 8px; border-radius: 11px;
  box-shadow: 0 10px 24px -6px rgba(6, 3, 12, .8);
  opacity: 0; transition: opacity .18s ease, transform .24s var(--ease-back);
  pointer-events: none;
}
.bt-bubble::after {
  content: ''; position: absolute; top: 100%; left: var(--arrow-x, 50%); margin-left: -6px;
  border: 6px solid transparent; border-top-color: #f0e6ff;
}
.bt-bubble.show { opacity: 1; transform: translateY(0) scale(1); }

.bt-floats { position: absolute; inset: 0; pointer-events: none; z-index: 30; }
.bt-float {
  position: absolute; transform: translate(-50%, 0);
  font-size: 17px; font-weight: 900;
  text-shadow: 0 2px 6px rgba(6, 3, 12, .9), 0 0 14px rgba(6, 3, 12, .6);
  animation: floatUp var(--fl-dur, .95s) var(--ease-out) forwards;
  white-space: nowrap;
}
.bt-float.dmg { color: #ff8194; }
.bt-float.dmg.big { font-size: 24px; color: #fff0b8; text-shadow: 0 0 16px rgba(255, 88, 113, .95), 0 2px 6px rgba(6, 3, 12, .9); }
.bt-float.buff { color: #86eda2; }
.bt-float.info { color: var(--frost); font-size: 13px; }
.bt-float.bad { color: #ffab5e; font-size: 13px; }
.bt-float.faint { color: #d9cff0; font-size: 14px; letter-spacing: .06em; }
@keyframes floatUp {
  0% { opacity: 0; transform: translate(-50%, 10px) scale(.7); }
  18% { opacity: 1; transform: translate(-50%, -2px) scale(1.15); }
  34% { transform: translate(-50%, -10px) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -52px) scale(.95); }
}

/* Bänder: Kampfstart und Ergebnis */
.bt-banner {
  position: absolute; top: 14px; left: 50%;
  transform: translateX(-50%) scale(.85);
  font-size: 30px; font-weight: 800; letter-spacing: -.01em;
  opacity: 0; transition: opacity .22s ease, transform .28s var(--ease-back);
  text-shadow: 0 4px 18px rgba(6, 3, 12, .95);
  z-index: 40; pointer-events: none;
}
.bt-banner.show { opacity: 1; transform: translateX(-50%) scale(1); }
.bt-banner.go {
  font-size: 46px;
  background: linear-gradient(180deg, #fff6e0, var(--brass));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 4px 22px rgba(255, 198, 107, .6));
}
.bt-banner.go.show { animation: bannerSlam .7s var(--ease-out); }
@keyframes bannerSlam {
  0% { opacity: 0; transform: translateX(-50%) scale(2.6); filter: blur(14px); }
  40% { opacity: 1; transform: translateX(-50%) scale(1); filter: blur(0); }
  70% { transform: translateX(-50%) scale(1.06); }
  100% { transform: translateX(-50%) scale(1); }
}
.bt-banner.result { color: var(--lantern); font-size: 38px; }
.bt-banner.toy { color: #cfb6ff; font-size: 19px; }

/* Kampf-Intro: kurzer Lichtblitz über dem Ring */
.bt-field.intro::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(60% 60% at 50% 40%, rgba(255, 240, 210, .5), transparent 70%);
  animation: introFlash .8s ease-out forwards;
  z-index: 35;
}
@keyframes introFlash { from { opacity: 1; } to { opacity: 0; } }

.bt-progress {
  height: 5px; border-radius: var(--r-pill); overflow: hidden;
  background: rgba(0, 0, 0, .35);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .5);
}
.bt-progress-fill {
  height: 100%; width: 0;
  background: linear-gradient(90deg, var(--mint), var(--lantern));
  box-shadow: 0 0 12px rgba(255, 198, 107, .6);
  transition: width .2s linear;
}

/* ============================================== 12  Overlays & Dialoge */
.app-overlay {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  background: rgba(9, 5, 16, .74);
  backdrop-filter: blur(5px);
  animation: veilIn .25s ease both;
}
.app-overlay[hidden] { display: none; }
@keyframes veilIn { from { opacity: 0; backdrop-filter: blur(0); } to { opacity: 1; } }

.dialog {
  position: relative;
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(255, 198, 107, .12), transparent 60%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 26px 32px;
  text-align: center;
  min-width: 290px;
  max-height: calc(100vh - 32px);
  overflow: auto;
  box-shadow: 0 34px 80px -18px rgba(6, 3, 12, .95), inset 0 1px 0 rgba(255, 226, 178, .12);
  animation: dialogIn .38s var(--ease-back) both;
}
@keyframes dialogIn {
  from { opacity: 0; transform: translateY(26px) scale(.92); } to { opacity: 1; transform: none; }
}
.dialog::before {                     /* Messingbogen über dem Titel */
  content: ''; position: absolute; inset: 0 0 auto; height: 4px;
  border-radius: 20px 20px 0 0;
  background: linear-gradient(90deg, transparent, var(--brass) 22%, var(--lantern) 50%, var(--brass) 78%, transparent);
}
.dialog h2 { font-size: 30px; margin-bottom: 8px; letter-spacing: -.02em; }
.dialog-stats {
  display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;
  color: var(--text-dim); margin-bottom: 18px;
}
.dialog-stats span {
  background: rgba(0, 0, 0, .25); border-radius: var(--r-pill);
  padding: 3px 12px; font-size: 13px; font-weight: 600;
}
.dialog.result-win::before { background: linear-gradient(90deg, transparent, var(--mint) 25%, #b6ffe4 50%, var(--mint) 75%, transparent); }
.dialog.result-win h2 {
  background: linear-gradient(180deg, #d8fff0, var(--mint));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 2px 14px rgba(79, 214, 168, .5));
}
.dialog.result-loss::before { background: linear-gradient(90deg, transparent, var(--punch) 25%, #ffc2cc 50%, var(--punch) 75%, transparent); }
.dialog.result-loss h2 { color: #ff9dab; }
.dialog.result-draw::before { background: linear-gradient(90deg, transparent, #8878a8 30%, #b9a8d8 50%, #8878a8 70%, transparent); }

/* --------------------------------------------------- Auswahl-Modal */
.dialog-hint { color: var(--text-dim); font-size: 12.5px; margin-bottom: 16px; }
.choice-dialog { max-width: min(720px, 94vw); }
.choice-dialog::before { background: linear-gradient(90deg, transparent, var(--neon) 25%, #e0d0ff 50%, var(--neon) 75%, transparent); }
.choice-dialog h2 { font-size: 23px; }
.choice-options { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; }
.choice-option {
  font: inherit; color: var(--text);
  background: rgba(255, 255, 255, .035);
  border: 2px solid var(--line-soft);
  border-radius: var(--r-card);
  padding: 9px;
  width: calc(var(--card-w) + 24px);
  cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  transition: transform .18s var(--ease-back), border-color .16s ease, background .16s ease, box-shadow .16s ease;
  animation: riseIn .4s var(--ease-out) both;
}
.choice-options .choice-option:nth-child(2) { animation-delay: .07s; }
.choice-options .choice-option:nth-child(3) { animation-delay: .14s; }
.choice-options .choice-option:nth-child(4) { animation-delay: .21s; }
.choice-option:hover {
  transform: translateY(-5px);
  border-color: var(--neon);
  background: rgba(168, 124, 255, .12);
  box-shadow: var(--lift-2), 0 0 26px -6px rgba(168, 124, 255, .7);
}
.choice-option:focus-visible { outline: 2px solid var(--neon); outline-offset: 3px; }
.choice-option .card { cursor: pointer; pointer-events: none; }
.choice-option:hover .tooltip, .choice-option:focus-visible .tooltip { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0) scale(1); }
.choice-label { font-size: 12px; font-weight: 700; text-align: center; }
.choice-fallback {
  width: 100%; height: 96px; border-radius: var(--r-card);
  border: 2px dashed var(--line-soft);
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; font-weight: 800; color: #4d3f6b;
}

/* ------------------------------------------------- Endbildschirm */
.gameover-dialog { max-width: min(800px, 94vw); }
.gameover-sub {
  font-size: 13px; font-weight: 800; color: var(--text-dim);
  margin: 18px 0 8px;
}
.gameover-row { justify-content: center; }
.gameover-slot { width: var(--card-w); min-height: 0; animation: riseIn .45s var(--ease-out) both; }
.gameover-row .gameover-slot:nth-child(2) { animation-delay: .06s; }
.gameover-row .gameover-slot:nth-child(3) { animation-delay: .12s; }
.gameover-row .gameover-slot:nth-child(4) { animation-delay: .18s; }
.gameover-row .gameover-slot:nth-child(5) { animation-delay: .24s; }
.gameover-row .gameover-slot:nth-child(6) { animation-delay: .3s; }
.gameover-slot .card { cursor: default; }
.gameover-history .hx-row { display: inline-flex; gap: 3px; flex-wrap: wrap; justify-content: center; }
.history-string {
  font-size: 12.5px; color: var(--text-dim); letter-spacing: .14em; margin-top: 8px; font-weight: 700;
}

/* ========================================================== 13  Toasts */
.app-toasts {
  position: fixed; top: 14px; right: 14px; z-index: 300;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-end;
  pointer-events: none;
  max-width: min(320px, calc(100vw - 28px));
}
.toast {
  display: flex; align-items: center; gap: 8px;
  background: linear-gradient(180deg, #2c1f3f, #1c1329);
  color: var(--text);
  border: 1px solid var(--line);
  border-left: 4px solid var(--punch);
  border-radius: var(--r-ctrl);
  padding: 9px 14px; font-size: 13px; font-weight: 600;
  box-shadow: 0 16px 34px -10px rgba(6, 3, 12, .9);
  animation: toastIn .32s var(--ease-back);
}
.toast::before {
  content: '!'; flex: 0 0 auto;
  width: 17px; height: 17px; border-radius: 50%;
  background: var(--punch); color: #2a0b12;
  font-size: 12px; font-weight: 900; line-height: 17px; text-align: center;
}
.toast.good { border-left-color: var(--mint); }
.toast.good::before { content: '✓'; background: var(--mint); color: #10281f; }
.toast.out { opacity: 0; transform: translateX(24px); transition: opacity .4s ease, transform .4s ease; }
@keyframes toastIn { from { opacity: 0; transform: translateX(28px) scale(.9); } to { opacity: 1; transform: none; } }

/* ================================================= 14  Startbildschirm */
.start-screen {
  min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  padding: 24px 16px;
}
.start-card {
  width: min(760px, 100%);
  background:
    radial-gradient(120% 60% at 50% -6%, rgba(255, 198, 107, .13), transparent 62%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
  border: 1px solid var(--line);
  border-radius: 24px;
  padding: 34px 34px 30px;
  box-shadow: 0 40px 90px -24px rgba(6, 3, 12, .95), inset 0 1px 0 rgba(255, 226, 178, .12);
  animation: dialogIn .5s var(--ease-back) both;
}
.start-card > * { animation: riseIn .55s var(--ease-out) both; }
.start-hero { animation-delay: .1s; }
.start-card .field:nth-of-type(1) { animation-delay: .18s; }
.start-card .field:nth-of-type(2) { animation-delay: .26s; }
.start-card > .btn { animation-delay: .34s; }

/* Held: die Tiere selbst, unter dem Laternenlicht. */
.start-hero { text-align: center; margin-bottom: 26px; }
.start-lamp {
  position: relative;
  height: 122px; margin: -10px auto 4px;
  display: flex; align-items: flex-end; justify-content: center; gap: 2px;
}
.start-lamp::before {
  content: ''; position: absolute; top: -22px; left: 50%; transform: translateX(-50%);
  width: 400px; height: 180px;
  background: radial-gradient(50% 60% at 50% 0%, rgba(255, 198, 107, .3), transparent 72%);
  pointer-events: none;
}
.start-lamp .hero-pet {
  position: relative;
  animation: heroBob 3.4s ease-in-out infinite;
  filter: drop-shadow(0 8px 12px rgba(6, 3, 12, .7));
}
.start-lamp .hero-pet:nth-child(1) { animation-delay: 0s; }
.start-lamp .hero-pet:nth-child(2) { animation-delay: .5s; transform: scale(1.16); z-index: 2; }
.start-lamp .hero-pet:nth-child(3) { animation-delay: 1s; }
@keyframes heroBob { 0%, 100% { transform: translateY(0) scale(var(--s, 1)); } 50% { transform: translateY(-7px) scale(var(--s, 1)); } }
.start-lamp .hero-pet:nth-child(2) { --s: 1.16; }

.start-card h1 {
  font-size: clamp(38px, 8vw, 58px);
  line-height: 1;
  background: linear-gradient(180deg, #fff8ea 30%, var(--brass));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 4px 24px rgba(255, 198, 107, .35));
}
.start-card .sub {
  color: var(--text-dim); font-size: 14.5px; margin: 8px auto 0;
  max-width: 46ch;
}

.field { display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px; }
.field > label { font-size: 13px; font-weight: 700; color: var(--text-dim); }
.field-row { display: flex; gap: 9px; }
.start-card input, .start-card select {
  font: inherit; color: var(--text);
  background: rgba(0, 0, 0, .3);
  border: 1px solid var(--line);
  border-radius: var(--r-ctrl);
  padding: 10px 12px;
  flex: 1 1 auto;
  min-width: 0;
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, .35);
}
.start-card input:focus-visible, .start-card select:focus-visible { outline: 2px solid var(--lantern); outline-offset: 1px; }
.start-card > .btn.go { width: 100%; }

/* Pack-Karten mit Vorschau-Tieren */
.pack-choice { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 12px; }
.pack-card {
  position: relative; text-align: left;
  font: inherit; color: var(--text);
  background: linear-gradient(180deg, rgba(255, 255, 255, .04), rgba(0, 0, 0, .18));
  border: 2px solid var(--line-soft);
  border-radius: var(--r-card);
  padding: 12px 14px 14px;
  cursor: pointer;
  overflow: hidden;
  transition: transform .18s var(--ease-back), border-color .18s ease, box-shadow .18s ease, background .18s ease;
}
.pack-card:hover { transform: translateY(-4px); border-color: rgba(255, 198, 107, .55); box-shadow: var(--lift-2); }
.pack-card:focus-visible { outline: 2px solid var(--lantern); outline-offset: 3px; }
.pack-card[aria-pressed="true"] {
  border-color: var(--brass);
  background: linear-gradient(180deg, rgba(232, 169, 74, .16), rgba(0, 0, 0, .2));
  box-shadow: var(--lift-2), var(--glow-brass);
}
.pack-card[aria-pressed="true"]::after {
  content: '✓'; position: absolute; top: 10px; right: 12px;
  width: 22px; height: 22px; border-radius: 50%;
  background: linear-gradient(180deg, var(--lantern), var(--brass-deep));
  color: #241708; font-size: 13px; font-weight: 900; line-height: 22px; text-align: center;
}
.pack-name { font-size: 17px; font-weight: 800; }
.pack-note { font-size: 12px; color: var(--text-dim); margin-top: 1px; }
.pack-preview {
  display: flex; align-items: flex-end; justify-content: flex-start; gap: 2px;
  margin-top: 8px; min-height: 52px;
}
.pack-preview .prev-pet { filter: drop-shadow(0 4px 6px rgba(6, 3, 12, .6)); }
.pack-card:hover .pack-preview .prev-pet,
.pack-card[aria-pressed="true"] .pack-preview .prev-pet { animation: heroBob 2.6s ease-in-out infinite; }
.pack-preview .prev-pet:nth-child(2) { animation-delay: .32s; }
.pack-preview .prev-pet:nth-child(3) { animation-delay: .64s; }

/* Setting-Karten: dieselbe Karte, aber ohne Vorschau-Zeile. Etwas flacher und mit
   Platz für den Haken, damit das Paar nicht halb leer wirkt. */
.theme-choice { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.theme-card { padding-bottom: 12px; }
.theme-card .pack-name { padding-right: 26px; }

.error-box {
  background: rgba(255, 88, 113, .12);
  border: 1px solid var(--punch);
  border-radius: var(--r-ctrl);
  padding: 11px 13px; font-size: 13px; margin-bottom: 16px;
  white-space: pre-wrap;
}

/* --------------------------------------------------- Lobby (Phase 4)
   Menü, Raumliste und Warteraum. Bewusst dieselben Bausteine wie der
   Startbildschirm (.start-card, .field, .pack-card) – nur die Listen sind neu. */

.start-card > .btn.back { width: 100%; margin-top: 9px; background: transparent; box-shadow: none; }
.start-card > .btn.back:hover:not(:disabled) { background: rgba(255, 255, 255, .05); }

/* Name in der Kopfzeile: sieht aus wie Text, ist aber der Weg zum Umbenennen. */
.link-name {
  font: inherit; font-weight: 800; color: var(--lantern);
  background: none; border: 0; padding: 0; cursor: pointer;
  border-bottom: 1px dashed rgba(255, 198, 107, .5);
}
.link-name:hover { filter: brightness(1.15); }
.link-name:focus-visible { outline: 2px solid var(--lantern); outline-offset: 2px; }

/* Verbindungszustand neben der Überschrift der Raumliste. */
.room-status { font-weight: 600; color: var(--text-dim); }
.room-status[data-status="open"] { color: var(--mint, #7fd4a8); }
.room-status[data-status="error"],
.room-status[data-status="closed"] { color: var(--punch); }

.host-form {
  border: 1px dashed var(--line-soft);
  border-radius: var(--r-card);
  padding: 14px 14px 4px;
  margin-top: 12px;
}
.host-form .btn.go { width: 100%; margin-bottom: 12px; }

.room-list { display: flex; flex-direction: column; gap: 8px; }
.room-empty { font-size: 13px; color: var(--text-dim); padding: 10px 2px; }

.room-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font: inherit; color: var(--text); text-align: left;
  background: linear-gradient(180deg, rgba(255, 255, 255, .04), rgba(0, 0, 0, .18));
  border: 2px solid var(--line-soft);
  border-radius: var(--r-ctrl);
  padding: 11px 14px;
  cursor: pointer;
  transition: transform .16s var(--ease-back), border-color .16s ease, box-shadow .16s ease;
}
.room-row:hover { transform: translateY(-2px); border-color: rgba(255, 198, 107, .55); box-shadow: var(--lift-2); }
.room-row:focus-visible { outline: 2px solid var(--lantern); outline-offset: 3px; }
.room-name { font-weight: 700; }
.room-count { font-size: 13px; color: var(--text-dim); font-variant-numeric: tabular-nums; }

/* Warteraum */
.room-players { display: flex; flex-direction: column; gap: 6px; }
.room-player {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  background: rgba(0, 0, 0, .18);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-ctrl);
  padding: 9px 13px;
}
.room-player[data-self="true"] { border-color: var(--brass); background: rgba(232, 169, 74, .12); }
.room-player-name { font-weight: 700; }
.room-tag {
  font-size: 11px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  color: #241708; background: linear-gradient(180deg, var(--lantern), var(--brass-deep));
  border-radius: 999px; padding: 2px 9px;
}
.room-hint { font-size: 12.5px; color: var(--text-dim); margin: 4px 0 18px; }

/* ========================================================= 15  FX-Ebene */
.fx-layer {
  position: fixed; inset: 0; z-index: 800;
  pointer-events: none; overflow: hidden;
}
.fx { position: absolute; will-change: transform, opacity; }
.fx-flyer {
  position: fixed; top: 0; left: 0;
  transform-origin: top left;
  pointer-events: none;
  z-index: 850;
  filter: drop-shadow(0 14px 24px rgba(6, 3, 12, .8));
}

.fx-coin {
  width: 15px; height: 15px; margin: -7px 0 0 -7px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff3d4, var(--brass) 55%, var(--brass-deep));
  box-shadow: 0 0 10px rgba(255, 198, 107, .8);
  animation: coinFly .85s var(--ease-out) var(--fx-delay, 0s) forwards;
}
@keyframes coinFly {
  0% { opacity: 0; transform: translate(0, 0) scale(.4); }
  15% { opacity: 1; }
  55% { transform: translate(var(--dx, 0), var(--dy, -40px)) scale(1.1); opacity: 1; }
  100% { opacity: 0; transform: translate(calc(var(--dx, 0) * 1.3), 26px) scale(.7); }
}

.fx-dust {
  width: 13px; height: 13px; margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(216, 184, 140, .8), transparent 70%);
  animation: dustPuff .6s ease-out var(--fx-delay, 0s) forwards;
}
@keyframes dustPuff {
  0% { opacity: .9; transform: translate(0, 0) scale(.4); }
  100% { opacity: 0; transform: translate(var(--dx, 0), var(--dy, -10px)) scale(2.4); }
}

.fx-ring {
  width: 24px; height: 24px; margin: -12px 0 0 -12px;
  border-radius: 50%;
  border: 3px solid var(--lantern);
  animation: ringOut .62s var(--ease-out) forwards;
}
.fx-ring.mint { border-color: var(--mint); }
.fx-ring.neon { border-color: var(--neon); }
@keyframes ringOut {
  0% { opacity: .95; transform: scale(.3); border-width: 5px; }
  100% { opacity: 0; transform: scale(4.6); border-width: 1px; }
}

.fx-star {
  width: 8px; height: 8px; margin: -4px 0 0 -4px;
  background: var(--lantern);
  clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
  animation: starOut .7s var(--ease-out) var(--fx-delay, 0s) forwards;
}
.fx-star.mint { background: var(--mint); }
@keyframes starOut {
  0% { opacity: 1; transform: translate(0, 0) scale(.3) rotate(0); }
  100% { opacity: 0; transform: translate(var(--dx, 0), var(--dy, 0)) scale(1.5) rotate(160deg); }
}

.fx-burst-label {
  transform: translate(-50%, -50%);
  font-size: 18px; font-weight: 900; color: var(--lantern);
  text-shadow: 0 2px 10px rgba(6, 3, 12, .9), 0 0 20px rgba(255, 198, 107, .8);
  white-space: nowrap;
  animation: burstLabel 1.1s var(--ease-out) forwards;
}
@keyframes burstLabel {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.4); }
  22% { opacity: 1; transform: translate(-50%, -50%) scale(1.2); }
  40% { transform: translate(-50%, -60%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -140%) scale(.95); }
}

.fx-shard {
  width: 9px; height: 9px; margin: -4px 0 0 -4px;
  background: linear-gradient(135deg, #e6d9ff, var(--neon));
  clip-path: polygon(0 0, 100% 26%, 62% 100%);
  animation: shardOut .7s ease-out forwards;
}
@keyframes shardOut {
  0% { opacity: 1; transform: translate(0, 0) rotate(0) scale(1); }
  100% { opacity: 0; transform: translate(var(--dx, 0), calc(var(--dy, 0) + 30px)) rotate(var(--rot, 180deg)) scale(.5); }
}

/* Geschoss: groß genug, um über den ganzen Ring hinweg gesehen zu werden, und
   in einer echten Wurfparabel (Stützstellen bei ¼/½/¾, siehe fx.js). Waagerecht
   gleichmäßig – deshalb `linear`, die Höhe macht der Bogen. */
.fx-projectile {
  width: 30px; height: 30px; margin: -15px 0 0 -15px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 28%, #fff, var(--mint) 55%, var(--neon));
  box-shadow: 0 0 22px 6px rgba(140, 255, 210, .55), 0 0 8px rgba(255, 255, 255, .9) inset;
  animation: projectileFly var(--fx-dur, 900ms) linear forwards;
}
.fx-projectile.dmg {
  background: radial-gradient(circle at 34% 28%, #fff, var(--punch) 52%, #7a0f1f);
  box-shadow: 0 0 22px 6px rgba(255, 90, 110, .55), 0 0 8px rgba(255, 255, 255, .9) inset;
}
@keyframes projectileFly {
  0% { opacity: 0; transform: translate(0, 0) scale(.45); }
  8% { opacity: 1; }
  25% { transform: translate(calc(var(--dx, 0px) * .25), calc(var(--dy, 0px) * .25 - var(--arc, 0px) * .75)) scale(1.05); }
  50% { transform: translate(calc(var(--dx, 0px) * .5), calc(var(--dy, 0px) * .5 - var(--arc, 0px))) scale(1.15); }
  75% { transform: translate(calc(var(--dx, 0px) * .75), calc(var(--dy, 0px) * .75 - var(--arc, 0px) * .75)) scale(1.05); }
  92% { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx, 0px), var(--dy, 0px)) scale(.8); }
}

/* Effekt auf sich selbst: hüpft über der Karte statt irgendwohin zu fliegen. */
.fx-selfcast {
  width: 30px; height: 30px; margin: -15px 0 0 -15px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 28%, #fff, var(--mint) 55%, var(--neon));
  box-shadow: 0 0 22px 6px rgba(140, 255, 210, .55), 0 0 8px rgba(255, 255, 255, .9) inset;
  animation: selfCastHop var(--fx-dur, 420ms) var(--ease-out) forwards;
}
.fx-selfcast.dmg {
  background: radial-gradient(circle at 34% 28%, #fff, var(--punch) 52%, #7a0f1f);
  box-shadow: 0 0 22px 6px rgba(255, 90, 110, .55), 0 0 8px rgba(255, 255, 255, .9) inset;
}
@keyframes selfCastHop {
  0% { opacity: 0; transform: translateY(14px) scale(.45); }
  45% { opacity: 1; transform: translateY(-54px) scale(1.15); }
  100% { opacity: 0; transform: translateY(2px) scale(.7); }
}

.fx-float {
  transform: translate(-50%, 0);
  font-size: 17px; font-weight: 900; color: var(--lantern);
  text-shadow: 0 2px 8px rgba(6, 3, 12, .9);
  white-space: nowrap;
  animation: fxFloatUp .95s var(--ease-out) forwards;
}
.fx-float.good { color: #86eda2; }
.fx-float.bad { color: #ff8194; }
.fx-float.gold { color: var(--lantern); }
@keyframes fxFloatUp {
  0% { opacity: 0; transform: translate(-50%, 8px) scale(.7); }
  20% { opacity: 1; transform: translate(-50%, -4px) scale(1.15); }
  100% { opacity: 0; transform: translate(-50%, -48px) scale(1); }
}

.fx-confetti { position: absolute; inset: 0; overflow: hidden; pointer-events: none; border-radius: inherit; }
.fx-confetti i {
  position: absolute; top: -18px;
  width: 9px; height: 9px; border-radius: 2px;
  animation: confettiFall var(--fx-dur, 2s) linear var(--fx-delay, 0s) forwards;
}
.fx-confetti i.slim { width: 4px; height: 13px; border-radius: 1px; }
@keyframes confettiFall {
  0% { opacity: 0; transform: translate(0, 0) rotate(0); }
  8% { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--fx-drift, 0), 105vh) rotate(var(--fx-spin, 360deg)); }
}

/* Eintritt neuer Karten nach einem Roll (fx.flip enter:'pop') */
.fx-enter { animation: cardDeal .5s var(--ease-back) var(--fx-delay, 0s) both; }
@keyframes cardDeal {
  0% { opacity: 0; transform: translateY(-26px) rotateY(70deg) scale(.85); }
  60% { opacity: 1; }
  100% { opacity: 1; transform: none; }
}
.fx-fade-in { animation: fadeQuick .18s ease both; }
@keyframes fadeQuick { from { opacity: .3; } to { opacity: 1; } }
.fx-pop { animation: fxPop .5s var(--ease-back); }
@keyframes fxPop { 0% { transform: scale(1); } 42% { transform: scale(1.22); } 100% { transform: scale(1); } }

/* Karte, die gerade verschmolzen/verkauft wird (Klon in der FX-Ebene) */
.fx-vanish { animation: vanish .42s ease-in forwards; }
@keyframes vanish { to { opacity: 0; transform: scale(.4) rotate(12deg); } }

/* ======================================================= 16  Responsiv */
@media (max-width: 720px) {
  .start-card { padding: 24px 20px 22px; border-radius: 20px; }
  .pack-choice { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  :root { --card-w-max: 94px; }
  .sap-app { --page-pad: 9px; gap: 10px; }
  .app-header { padding: 9px 12px; gap: 8px; }
  .stat { padding: 1px 8px 2px; }
  .stat-value { font-size: 15px; }
  .row { gap: 7px; }
  .slot { min-height: 138px; }
  /* Auf einem Telefon stehen Auslage und Vorräte wieder ÜBEREINANDER: fünf Einheiten
     und eine Vorratsspalte nebeneinander lassen von jeder Karte einen Streifen übrig. */
  .shop-goods { flex-direction: column; align-items: stretch; }
  .shop-goods .shop-row { flex-wrap: wrap; }
  .food-row { flex: 0 0 auto; flex-direction: row; margin-top: 2px; }
  .food-row > .slot { width: var(--card-w); }
  .tooltip { width: 196px; }
  .bt-field { --bt-card-w: 78px; --bt-toy-w: 58px; }
  .bt-field[data-count="4"] { --bt-card-w: 68px; --bt-toy-w: 54px; }
  .bt-field[data-count="5"] { --bt-card-w: 60px; --bt-toy-w: 48px; }
  .bt-field[data-count="6"] { --bt-card-w: 54px; --bt-toy-w: 44px; }
  .bt-side { gap: 5px; }
  .bt-toy { width: 58px; }
  .bt-toy-art { height: 36px; }
  .holder-a { margin-right: 6px; }
  .holder-b { margin-left: 6px; }
  /* `height`, nicht `min-height`: die Basisregel setzt jetzt `height` (wegen `cqh`,
     siehe Abschnitt 11), das schlägt ein bloßes `min-height` sonst immer. */
  .bt-field { height: 234px; padding: 34px 6px 0; }
  .bt-banner { font-size: 22px; }
  .bt-banner.go { font-size: 32px; }
  .choice-option { width: calc(var(--card-w) + 16px); }
  .offer-group { padding: 17px 8px 4px; }
  .dialog { padding: 20px 18px; border-radius: 16px; }
  .dialog h2 { font-size: 24px; }
}

@media (max-width: 400px) {
  :root { --card-w-max: 86px; }
  .slot { min-height: 128px; }
  .bt-card { width: 70px; }
}

/* ============================================ 17  Reduzierte Bewegung */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .08s !important;
  }
  /* Was Information trägt, bleibt sichtbar – nur ohne Bewegung. */
  .bt-card.fainting { opacity: 0; transition: opacity .18s linear !important; }
  .bt-float, .fx-float { animation: fadeQuick .3s ease both !important; }
  .sap-app > *, .start-card > *, .choice-option, .gameover-slot { opacity: 1 !important; transform: none !important; }
  .toy-card, .bt-toy { animation: none !important; }
  /* Perk bleibt sichtbar – eine ruhige Blase über der Grafik statt drei. */
  .perk-fly {
    animation: none !important;
    left: 50%; bottom: 45%; opacity: 1; transform: translateX(-50%) scaleX(var(--perk-flip, 1));
  }
  .perk-fly svg { animation: none !important; transform: none; }
  .perk-fly ~ .perk-fly { display: none; }
}


/* ================================================ 18  Setting „Konvoi“ */
/* Standardsetting (themes/convoy). main.js setzt <html class="theme-convoy">.
   ALLES in dieser Sektion hängt an `.theme-convoy` – ohne die Klasse bleibt die
   Basis-Farbwelt Pixel für Pixel unverändert. Geändert wird ausschließlich die
   Farbwelt, nie Layout, Maße oder Animationen.

   RICHTUNG: Nachtlager am Highway. Der Grund ist kalter Asphalt und Asche, das
   Licht kommt von einer Natriumdampflampe am Mast: oben ein schmutzig gelber
   Schein, unten kalter Dunst über dem Boden. Erhabene Flächen sind lackiertes
   Blech mit Rostkante, Beschläge sind angelaufenes Metall statt Messing,
   Markisen sind Warnstreifen, Displays leuchten cyan.

   19.1 Tokens        19.4 Karten, Slots, Kasse
   19.2 Hintergrund   19.5 Geräte (Bordgeräte statt Spielzeug)
   19.3 Panels        19.6 Kampf, Tooltip, Toast, Startbildschirm
   -------------------------------------------------------------------------- */

/* ------------------------------------------------------- 19.1  Tokens */
:root.theme-convoy {
  /* Asphalt & Asche */
  --ink: #0d1110;
  --ink-2: #141a17;
  --plum: #1c2220;
  --plum-2: #242b27;
  --plum-3: #2d352f;
  --line: #3f4a41;
  --line-soft: #2d352f;

  /* Natriumdampflicht & Rost (Messing wird angelaufenes Blech) */
  --brass: #c8792e;
  --brass-deep: #8b4a16;
  --lantern: #f0b544;
  --sawdust: #bdac88;

  /* Signalfarben: Giftgrün, Signalrot, Cyan-Display */
  --mint: #8ac74c;
  --mint-deep: #57902c;
  --punch: #dd4536;
  --punch-deep: #97261d;
  --neon: #48c6cd;
  --frost: #8cc6d6;

  /* Rollen */
  --text: #eae7db;
  --text-dim: #a5a897;
  --text-faint: #6f7467;
  --atk: #f28a4c;
  --hp: #95cc59;

  /* Licht & Schatten: kalte Asche statt warmes Violett */
  --lift-1: 0 1px 0 rgba(238, 222, 176, .07) inset, 0 2px 6px rgba(4, 8, 6, .55);
  --lift-2: 0 1px 0 rgba(238, 222, 176, .10) inset, 0 8px 22px -6px rgba(4, 8, 6, .72);
  --lift-3: 0 1px 0 rgba(238, 222, 176, .13) inset, 0 18px 40px -10px rgba(3, 6, 5, .82);
  --glow-brass: 0 0 0 1px rgba(200, 121, 46, .6), 0 0 22px -4px rgba(240, 181, 68, .42);
  --glow-mint: 0 0 0 1px rgba(138, 199, 76, .6), 0 0 24px -4px rgba(138, 199, 76, .4);
}
:root.theme-convoy ::selection { background: rgba(240, 181, 68, .32); }

/* -------------------------------------------------- 19.2  Hintergrund */
/* Natriumdampflampe oben, kalter Bodendunst unten, Rußvignette. */
:root.theme-convoy body::before {
  background:
    radial-gradient(120% 70% at 50% -12%, rgba(240, 181, 68, .14), transparent 58%),
    radial-gradient(70% 44% at 50% 106%, rgba(122, 158, 148, .10), transparent 70%),
    radial-gradient(140% 100% at 50% 0%, var(--ink-2) 0%, var(--ink) 62%);
}
:root.theme-convoy body::after {
  background: radial-gradient(115% 85% at 50% 42%, transparent 42%, rgba(2, 6, 5, .66) 100%);
}

/* ------------------------------------------------------ 19.3  Panels */
:root.theme-convoy .panel {
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(240, 181, 68, .06), transparent 60%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
}
/* Aus der Markise wird ein Warnstreifen am oberen Blechrand. */
:root.theme-convoy .panel::before {
  background: repeating-linear-gradient(118deg,
    rgba(240, 181, 68, .6) 0 9px, rgba(8, 12, 10, .7) 9px 18px);
  opacity: .5;
}
:root.theme-convoy .team-panel::before {
  background: repeating-linear-gradient(118deg,
    rgba(138, 199, 76, .5) 0 9px, rgba(8, 12, 10, .65) 9px 18px);
}
/* Der Boden unter dem Konvoi: Staub im Lampenkegel. */
:root.theme-convoy .team-panel .team-row::before {
  background: radial-gradient(50% 100% at 50% 100%, rgba(189, 172, 136, .18), transparent 72%);
}
:root.theme-convoy .app-header {
  background:
    linear-gradient(180deg, rgba(240, 200, 140, .08), transparent 34%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
}
:root.theme-convoy .brand-title {
  background: linear-gradient(180deg, #f6efdc, var(--brass));
  -webkit-background-clip: text; background-clip: text;
}

/* --------------------------------------- 19.4  Karten, Slots, Kasse */
:root.theme-convoy .card {
  background:
    radial-gradient(100% 58% at 50% 0%, rgba(240, 200, 140, .12), transparent 62%),
    linear-gradient(180deg, var(--plum-3), #1a201c);
}
:root.theme-convoy .card:hover {
  border-color: rgba(240, 181, 68, .45);
  box-shadow: var(--lift-3), 0 0 26px -6px rgba(240, 181, 68, .4);
}
:root.theme-convoy .card-art { filter: drop-shadow(0 4px 6px rgba(3, 7, 5, .6)); }
:root.theme-convoy .slot.empty:not(.team-slot) { border-color: #38423a; }
:root.theme-convoy .slot-placeholder { color: #3f4a40; }
/* Stellplatz: Markierung im Staub, Reifenspuren-Sand statt Kreide. */
:root.theme-convoy .slot.team-slot.empty::before {
  border-color: rgba(189, 172, 136, .34);
  background: radial-gradient(50% 50%, rgba(189, 172, 136, .13), transparent 72%);
}
:root.theme-convoy .slot.team-slot.empty .slot-placeholder { color: rgba(189, 172, 136, .6); }
:root.theme-convoy .slot.team-slot.empty.dnd-target-ok::before {
  border-color: var(--mint);
  background: radial-gradient(50% 50%, rgba(138, 199, 76, .3), transparent 72%);
}
:root.theme-convoy .pip { background: #39433a; }
:root.theme-convoy .pip.on { background: linear-gradient(180deg, #bde08a, var(--mint-deep)); box-shadow: 0 0 7px rgba(138, 199, 76, .75); }
:root.theme-convoy .pip.max { background: linear-gradient(180deg, #ffe2a6, var(--brass)); box-shadow: 0 0 10px rgba(240, 181, 68, .9); }
:root.theme-convoy .sell-zone { border-color: #6b4034; color: #d8a292; background: rgba(221, 69, 54, .05); }
:root.theme-convoy .sell-zone.dnd-target-ok { color: #f3c3b6; background: rgba(221, 69, 54, .14); }
:root.theme-convoy .shop-panel.dnd-target-ok {
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(221, 69, 54, .1), transparent 60%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
}
:root.theme-convoy .shop-panel.dnd-target-ok::after { color: #eeb0a3; }
:root.theme-convoy .freeze-btn { color: #77806f; }
:root.theme-convoy .freeze-btn.on { background: linear-gradient(180deg, #26525c, #163840); }
:root.theme-convoy .heart { filter: drop-shadow(0 0 6px rgba(221, 69, 54, .5)); }
:root.theme-convoy .heart.lost { color: #3c463c; }
:root.theme-convoy .hx { color: #101410; }
:root.theme-convoy .hx-win { background: linear-gradient(180deg, #bfe28c, var(--mint-deep)); }
:root.theme-convoy .hx-loss { background: linear-gradient(180deg, #ef8b78, var(--punch-deep)); }
:root.theme-convoy .hx-draw { background: linear-gradient(180deg, #9ba393, #4c554b); }
:root.theme-convoy .btn.primary { background: linear-gradient(180deg, #dd9647, var(--brass-deep)); border-color: #ecb56f; color: #201202; }
:root.theme-convoy .btn.go { background: linear-gradient(180deg, #8dbd54, #4c7d26); border-color: #a9cf7c; color: #101a09; }
:root.theme-convoy .btn.danger { background: linear-gradient(180deg, #e46a56, var(--punch-deep)); border-color: #f09484; color: #250803; }

/* ------------------------------------------------------ 19.5  Geräte */
/* Kein violettes Spielzeug: Bordgeräte sind Blech mit Cyan-Display. */
:root.theme-convoy .toy-card {
  background:
    radial-gradient(100% 58% at 50% 0%, rgba(72, 198, 205, .14), transparent 62%),
    linear-gradient(180deg, #263a3c, #172426);
  border-color: #3c5c5e;
}
:root.theme-convoy .toy-card:hover { box-shadow: var(--lift-3), 0 0 26px -6px rgba(72, 198, 205, .5); }
:root.theme-convoy .toy-tag {
  color: #d6f2f4; background: rgba(72, 198, 205, .22);
  box-shadow: inset 0 0 0 1px rgba(72, 198, 205, .45);
}
:root.theme-convoy .toy-ring .fill { filter: drop-shadow(0 0 4px rgba(72, 198, 205, .75)); }
:root.theme-convoy .toy-ring.urgent .fill { filter: drop-shadow(0 0 6px rgba(240, 181, 68, .85)); }
:root.theme-convoy .bt-toy { background: linear-gradient(180deg, #263a3c, #172426); border-color: #3c5c5e; }
:root.theme-convoy .bt-toy-name { color: #d6f2f4; }
:root.theme-convoy .fx-shard { background: linear-gradient(135deg, #d6f2f4, var(--neon)); }

/* ----------------------- 19.6  Kampf, Tooltip, Toast, Startbildschirm */
:root.theme-convoy .bt-field {
  background:
    radial-gradient(58% 34% at 50% 100%, rgba(189, 172, 136, .18), transparent 72%),
    radial-gradient(60% 46% at 50% -6%, rgba(240, 181, 68, .15), transparent 68%),
    linear-gradient(180deg, #141a17 0%, #1c2220 62%, #232b26 100%);
}
:root.theme-convoy .bt-plaque,
:root.theme-convoy .team-panel .card-plaque { background: linear-gradient(180deg, rgba(28, 34, 32, .93), rgba(13, 17, 16, .93)); }
:root.theme-convoy .bt-card.side-a .bt-plaque,
:root.theme-convoy .team-panel .card-plaque { border-color: rgba(138, 199, 76, .5); }
:root.theme-convoy .bt-card.side-b .bt-plaque { border-color: rgba(242, 138, 76, .5); }
:root.theme-convoy .bt-card .bt-art > svg,
:root.theme-convoy .bt-card .bt-art > img { filter: drop-shadow(0 6px 8px rgba(3, 7, 5, .65)); }
:root.theme-convoy .bt-vs { color: #221604; }
:root.theme-convoy .bt-bubble { background: linear-gradient(180deg, #fbf6e6, #e8e6d4); color: #1c221e; }
:root.theme-convoy .bt-bubble::after { border-top-color: #e8e6d4; }
:root.theme-convoy .bt-float.dmg { color: #f4907c; }
:root.theme-convoy .bt-float.dmg.big { color: #ffe6a8; text-shadow: 0 0 16px rgba(221, 69, 54, .9), 0 2px 6px rgba(3, 7, 5, .9); }
:root.theme-convoy .bt-float.buff { color: #a9dd7c; }
:root.theme-convoy .bt-float.faint { color: #cfd2c4; }
:root.theme-convoy .bt-banner.go {
  background: linear-gradient(180deg, #fbeecd, var(--brass));
  -webkit-background-clip: text; background-clip: text;
  filter: drop-shadow(0 4px 22px rgba(240, 181, 68, .55));
}
:root.theme-convoy .bt-banner.toy { color: #93dbe1; }

:root.theme-convoy .tooltip {
  background: linear-gradient(180deg, #242b26, #161b18);
  box-shadow: 0 16px 36px -8px rgba(2, 6, 5, .9), 0 0 0 1px rgba(240, 181, 68, .1);
}
:root.theme-convoy .tooltip::after { border-top-color: #161b18; }
:root.theme-convoy .tooltip strong { color: #f5f0e0; }
:root.theme-convoy .toast { background: linear-gradient(180deg, #262e28, #171d19); }
:root.theme-convoy .toast::before { color: #250803; }
:root.theme-convoy .toast.good::before { color: #12200c; }
:root.theme-convoy .choice-fallback { color: #444f45; }
:root.theme-convoy .choice-dialog::before { background: linear-gradient(90deg, transparent, var(--neon) 25%, #cdeef1 50%, var(--neon) 75%, transparent); }
:root.theme-convoy .dialog.result-win::before { background: linear-gradient(90deg, transparent, var(--mint) 25%, #d3eeae 50%, var(--mint) 75%, transparent); }
:root.theme-convoy .dialog.result-loss::before { background: linear-gradient(90deg, transparent, var(--punch) 25%, #f5b8ac 50%, var(--punch) 75%, transparent); }
:root.theme-convoy .dialog.result-draw::before { background: linear-gradient(90deg, transparent, #77806f 30%, #a8b09f 50%, #77806f 70%, transparent); }
:root.theme-convoy .dialog.result-loss h2 { color: #ef9484; }

:root.theme-convoy .start-card {
  background:
    radial-gradient(120% 60% at 50% -6%, rgba(240, 181, 68, .11), transparent 62%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
  box-shadow: 0 40px 90px -24px rgba(2, 6, 5, .95), inset 0 1px 0 rgba(238, 222, 176, .1);
}
:root.theme-convoy .start-lamp::before {
  background: radial-gradient(50% 60% at 50% 0%, rgba(240, 181, 68, .26), transparent 72%);
}
:root.theme-convoy .start-lamp .hero-pet { filter: drop-shadow(0 8px 12px rgba(2, 6, 5, .7)); }
:root.theme-convoy .start-card h1 {
  background: linear-gradient(180deg, #f7f0dc 30%, var(--brass));
  -webkit-background-clip: text; background-clip: text;
  filter: drop-shadow(0 4px 24px rgba(240, 181, 68, .3));
}
:root.theme-convoy .pack-card:hover { border-color: rgba(240, 181, 68, .5); }
:root.theme-convoy .pack-card[aria-pressed="true"] {
  background: linear-gradient(180deg, rgba(200, 121, 46, .16), rgba(0, 0, 0, .22));
}
:root.theme-convoy .pack-card[aria-pressed="true"]::after { color: #201202; }
:root.theme-convoy .pack-preview .prev-pet { filter: drop-shadow(0 4px 6px rgba(2, 6, 5, .6)); }

/* ========================================== 19  Setting „Cyberpunk-Crew“ */
/* Zweites Setting (themes/cyberpunk). main.js setzt <html class="theme-cyberpunk">.
   ALLES in dieser Sektion hängt an `.theme-cyberpunk` – ohne die Klasse bleiben die
   Basis-Farbwelt und der Konvoi Pixel für Pixel unverändert. Geändert wird ausschließlich
   die Farbwelt, nie Layout, Maße, Animationen oder Schriftfamilie.

   RICHTUNG: Neon-Metropole bei Nacht im Regen. Der Grund ist nasser Asphalt und
   Sichtbeton, das Licht kommt von Leuchtreklame: Magenta von links oben, Cyan von rechts,
   Natriumgelb aus den Laternen, dazu feiner Regen-Dunst. Erhabene Flächen sind glatter
   Kunststoff und poliertes Chrom, Zierleisten sind dünne Neonröhren statt Markisen,
   Displays leuchten cyan, Warnungen rot.

   20.1 Tokens        20.4 Karten, Slots, Kasse
   20.2 Hintergrund   20.5 Exploits (statt Spielzeug)
   20.3 Panels        20.6 Kampf, Tooltip, Toast, Dialoge, Startbildschirm
   -------------------------------------------------------------------------- */

/* ------------------------------------------------------- 20.1  Tokens */
:root.theme-cyberpunk {
  /* Nacht-Asphalt und Sichtbeton */
  --ink: #07070f;
  --ink-2: #0e0e1d;
  --plum: #16162b;
  --plum-2: #1e1e34;
  --plum-3: #27273f;
  --line: #3d3d63;
  --line-soft: #2a2a47;

  /* Leitfarbe der Metropole: Neon-Magenta (nimmt die Messing-Rolle ein) */
  --brass: #ff2d95;
  --brass-deep: #a30f61;
  --lantern: #ffd83d;              /* Natriumgelb der Straßenlaternen */
  --sawdust: #b5addc;              /* Regen-Dunst im Lichtkegel */

  /* Displays und Signale */
  --mint: #22d3ee;
  --mint-deep: #0d7c94;
  --punch: #ff3b5c;
  --punch-deep: #a81338;
  --neon: #b06cff;
  --frost: #7be8ff;

  /* Rollen */
  --text: #f1eefc;
  --text-dim: #a8a2cc;
  --text-faint: #6b6591;
  --atk: #ff6f9b;
  --hp: #3ee6b0;

  /* Licht & Schatten: kaltes Blauschwarz, harte Kante oben */
  --lift-1: 0 1px 0 rgba(196, 224, 255, .10) inset, 0 2px 6px rgba(2, 3, 10, .6);
  --lift-2: 0 1px 0 rgba(196, 224, 255, .13) inset, 0 8px 22px -6px rgba(2, 3, 10, .78);
  --lift-3: 0 1px 0 rgba(196, 224, 255, .17) inset, 0 18px 40px -10px rgba(1, 2, 8, .88);
  --glow-brass: 0 0 0 1px rgba(255, 45, 149, .62), 0 0 22px -4px rgba(255, 45, 149, .55);
  --glow-mint: 0 0 0 1px rgba(34, 211, 238, .66), 0 0 24px -4px rgba(34, 211, 238, .5);
}
:root.theme-cyberpunk ::selection { background: rgba(255, 45, 149, .34); }

/* -------------------------------------------------- 20.2  Hintergrund */
/* Magenta-Reklame oben links, Cyan-Reklame oben rechts, Violettschein vom Boden,
   darüber ein feiner Regenschleier. Alles nur Verläufe – kein Layer, keine Animation. */
:root.theme-cyberpunk body::before {
  background:
    radial-gradient(88% 52% at 16% -10%, rgba(255, 45, 149, .22), transparent 62%),
    radial-gradient(78% 48% at 86% -4%, rgba(34, 211, 238, .17), transparent 62%),
    radial-gradient(70% 42% at 50% 108%, rgba(176, 108, 255, .15), transparent 72%),
    radial-gradient(46% 26% at 50% 4%, rgba(255, 216, 61, .07), transparent 70%),
    repeating-linear-gradient(101deg, rgba(196, 222, 255, .028) 0 1px, transparent 1px 8px),
    radial-gradient(140% 100% at 50% 0%, var(--ink-2) 0%, var(--ink) 64%);
}
:root.theme-cyberpunk body::after {
  background: radial-gradient(115% 85% at 50% 42%, transparent 40%, rgba(1, 2, 8, .72) 100%);
}

/* ------------------------------------------------------ 20.3  Panels */
:root.theme-cyberpunk .panel {
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(255, 45, 149, .08), transparent 60%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
}
/* Aus der Markise wird eine dünne Neonröhre auf der Panelkante. */
:root.theme-cyberpunk .panel::before {
  background: linear-gradient(90deg,
    transparent, rgba(255, 45, 149, .25) 8%, var(--brass) 30%, #ffd6ec 50%, var(--brass) 70%,
    rgba(255, 45, 149, .25) 92%, transparent);
  opacity: .85;
}
:root.theme-cyberpunk .team-panel::before {
  background: linear-gradient(90deg,
    transparent, rgba(34, 211, 238, .22) 8%, var(--mint) 30%, #cbf7ff 50%, var(--mint) 70%,
    rgba(34, 211, 238, .22) 92%, transparent);
}
/* Der Boden unter der Crew: nasser Asphalt, der die Reklame spiegelt. */
:root.theme-cyberpunk .team-panel .team-row::before {
  background: radial-gradient(50% 100% at 50% 100%, rgba(34, 211, 238, .16), transparent 72%);
}
:root.theme-cyberpunk .app-header {
  background:
    linear-gradient(180deg, rgba(255, 45, 149, .10), transparent 34%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
}
:root.theme-cyberpunk .brand-title {
  background: linear-gradient(180deg, #ffffff, var(--brass));
  -webkit-background-clip: text; background-clip: text;
}

/* --------------------------------------- 20.4  Karten, Slots, Kasse */
:root.theme-cyberpunk .card {
  background:
    radial-gradient(100% 58% at 50% 0%, rgba(190, 220, 255, .13), transparent 62%),
    linear-gradient(180deg, var(--plum-3), #191930);
}
:root.theme-cyberpunk .card:hover {
  border-color: rgba(255, 45, 149, .55);
  box-shadow: var(--lift-3), 0 0 26px -6px rgba(255, 45, 149, .55);
}
:root.theme-cyberpunk .card:focus-visible { outline-color: var(--mint); }
:root.theme-cyberpunk .card-art { filter: drop-shadow(0 4px 7px rgba(1, 2, 8, .7)); }
:root.theme-cyberpunk .slot.empty:not(.team-slot) { border-color: #33335a; }
:root.theme-cyberpunk .slot-placeholder { color: #3a3a60; }
/* Stellplatz: Boden-Hologramm – dünner Cyan-Ring, der leicht leuchtet. */
:root.theme-cyberpunk .slot.team-slot.empty::before {
  border: 1px solid rgba(34, 211, 238, .45);
  background: radial-gradient(50% 50%, rgba(34, 211, 238, .16), transparent 72%);
  box-shadow: 0 0 12px rgba(34, 211, 238, .22), inset 0 0 10px rgba(34, 211, 238, .18);
}
:root.theme-cyberpunk .slot.team-slot.empty .slot-placeholder { color: rgba(123, 232, 255, .7); text-shadow: 0 0 8px rgba(34, 211, 238, .6); }
:root.theme-cyberpunk .slot.team-slot.empty.dnd-target-ok::before {
  border-color: var(--frost);
  background: radial-gradient(50% 50%, rgba(123, 232, 255, .34), transparent 72%);
}
:root.theme-cyberpunk .pip { background: #2f2f52; }
:root.theme-cyberpunk .pip.on {
  background: linear-gradient(180deg, #9defff, var(--mint-deep));
  box-shadow: 0 0 8px rgba(34, 211, 238, .9);
}
:root.theme-cyberpunk .pip.max {
  background: linear-gradient(180deg, #ffd0e6, var(--brass));
  box-shadow: 0 0 10px rgba(255, 45, 149, .95);
}
:root.theme-cyberpunk .sell-zone { border-color: #6d2745; color: #ffa9bd; background: rgba(255, 59, 92, .05); }
:root.theme-cyberpunk .sell-zone.dnd-target-ok { color: #ffd0da; background: rgba(255, 59, 92, .15); }
:root.theme-cyberpunk .shop-panel.dnd-target-ok {
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(255, 59, 92, .12), transparent 60%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
}
:root.theme-cyberpunk .shop-panel.dnd-target-ok::after { color: #ffbdc9; }
:root.theme-cyberpunk .freeze-btn { color: #6c6595; }
:root.theme-cyberpunk .freeze-btn.on { background: linear-gradient(180deg, #14586e, #0b3243); }
:root.theme-cyberpunk .frost { border-color: rgba(123, 232, 255, .75); }
:root.theme-cyberpunk .heart { filter: drop-shadow(0 0 7px rgba(255, 59, 92, .65)); }
:root.theme-cyberpunk .heart.lost { color: #363258; }
:root.theme-cyberpunk .hx { color: #060a14; }
:root.theme-cyberpunk .hx-win { background: linear-gradient(180deg, #9defff, var(--mint-deep)); }
:root.theme-cyberpunk .hx-loss { background: linear-gradient(180deg, #ff8fa6, var(--punch-deep)); }
:root.theme-cyberpunk .hx-draw { background: linear-gradient(180deg, #a9a2cf, #4d4873); }
:root.theme-cyberpunk .btn.primary {
  background: linear-gradient(180deg, #ff5cae, var(--brass-deep));
  border-color: #ff8dc6; color: #2a0316;
}
:root.theme-cyberpunk .btn.go {
  background: linear-gradient(180deg, #3fdcf2, #0b6d84);
  border-color: #7be8ff; color: #041a20;
}
:root.theme-cyberpunk .btn.danger {
  background: linear-gradient(180deg, #ff5f7d, var(--punch-deep));
  border-color: #ff93a8; color: #2a0510;
}

/* ----------------------------------------------------- 20.5  Exploits */
/* Kein violettes Spielzeug: ein Exploit ist ein laufendes Programm – dunkles Glas mit
   Hologramm-Schein, Cyan-Schrift, Countdown in Violett. */
:root.theme-cyberpunk .toy-card {
  background:
    radial-gradient(100% 58% at 50% 0%, rgba(123, 232, 255, .18), transparent 62%),
    linear-gradient(180deg, #1b2a44, #101a2e);
  border-color: #35547f;
}
:root.theme-cyberpunk .toy-card:hover {
  border-color: var(--frost);
  box-shadow: var(--lift-3), 0 0 26px -6px rgba(123, 232, 255, .6);
}
:root.theme-cyberpunk .toy-tag {
  color: #d8f6ff; background: rgba(34, 211, 238, .2);
  box-shadow: inset 0 0 0 1px rgba(34, 211, 238, .5);
}
:root.theme-cyberpunk .toy-ring .track { stroke: rgba(190, 222, 255, .12); }
:root.theme-cyberpunk .toy-ring .fill { stroke: var(--frost); filter: drop-shadow(0 0 5px rgba(123, 232, 255, .85)); }
:root.theme-cyberpunk .toy-ring.urgent .fill { stroke: var(--brass); filter: drop-shadow(0 0 6px rgba(255, 45, 149, .9)); }
:root.theme-cyberpunk .bt-toy { background: linear-gradient(180deg, #1b2a44, #101a2e); border-color: #35547f; }
:root.theme-cyberpunk .bt-toy-name { color: #d8f6ff; }
:root.theme-cyberpunk .fx-shard { background: linear-gradient(135deg, #e6fbff, var(--mint)); }

/* --------------- 20.6  Kampf, Tooltip, Toast, Dialoge, Startbildschirm */
/* Der Ring ist ein Dach oder Hinterhof: Reklame von beiden Seiten, nasser Boden,
   ein feines Bodenraster wie Leuchtstreifen im Beton. */
:root.theme-cyberpunk .bt-field {
  background:
    radial-gradient(56% 32% at 50% 100%, rgba(34, 211, 238, .18), transparent 72%),
    radial-gradient(52% 42% at 14% -6%, rgba(255, 45, 149, .2), transparent 68%),
    radial-gradient(52% 42% at 86% -6%, rgba(34, 211, 238, .16), transparent 68%),
    repeating-linear-gradient(90deg, rgba(190, 222, 255, .04) 0 1px, transparent 1px 26px),
    linear-gradient(180deg, #0e0e1d 0%, #16162b 62%, #1f1f38 100%);
}
:root.theme-cyberpunk .bt-field::before {
  background: linear-gradient(90deg, transparent, rgba(34, 211, 238, .5), transparent);
}
:root.theme-cyberpunk .bt-plaque,
:root.theme-cyberpunk .team-panel .card-plaque {
  background: linear-gradient(180deg, rgba(22, 22, 43, .93), rgba(7, 7, 15, .93));
  box-shadow: 0 6px 14px -6px rgba(1, 2, 8, .95), inset 0 1px 0 rgba(196, 224, 255, .08);
}
:root.theme-cyberpunk .bt-card.side-a .bt-plaque,
:root.theme-cyberpunk .team-panel .card-plaque { border-color: rgba(34, 211, 238, .55); }
:root.theme-cyberpunk .bt-card.side-b .bt-plaque { border-color: rgba(255, 111, 155, .55); }
:root.theme-cyberpunk .bt-card .bt-art > svg,
:root.theme-cyberpunk .bt-card .bt-art > img { filter: drop-shadow(0 6px 9px rgba(1, 2, 8, .75)); }
:root.theme-cyberpunk .bt-vs { background: linear-gradient(180deg, var(--lantern), var(--brass-deep)); color: #240210; }
:root.theme-cyberpunk .bt-clash {
  background: radial-gradient(circle, rgba(255, 255, 255, .98), rgba(123, 232, 255, .6) 42%, rgba(255, 45, 149, .28) 66%, transparent 74%);
}
/* Sprechblase: Displayfenster statt Papier. */
:root.theme-cyberpunk .bt-bubble {
  background: linear-gradient(180deg, #182a40, #101a2c);
  color: #d8f6ff;
  box-shadow: 0 10px 24px -6px rgba(1, 2, 8, .85), inset 0 0 0 1px rgba(34, 211, 238, .35);
}
:root.theme-cyberpunk .bt-bubble::after { border-top-color: #101a2c; }
:root.theme-cyberpunk .bt-float.dmg { color: #ff88a5; }
:root.theme-cyberpunk .bt-float.dmg.big { color: #fff0a8; text-shadow: 0 0 16px rgba(255, 45, 149, .95), 0 2px 6px rgba(1, 2, 8, .9); }
:root.theme-cyberpunk .bt-float.buff { color: #6effcd; }
:root.theme-cyberpunk .bt-float.bad { color: #ffc24d; }
:root.theme-cyberpunk .bt-float.faint { color: #c9c4ea; }
:root.theme-cyberpunk .bt-banner.go {
  background: linear-gradient(180deg, #ffffff, var(--brass));
  -webkit-background-clip: text; background-clip: text;
  filter: drop-shadow(0 4px 22px rgba(255, 45, 149, .6));
}
:root.theme-cyberpunk .bt-banner.result { color: var(--frost); }
:root.theme-cyberpunk .bt-banner.toy { color: #8ceaff; }
:root.theme-cyberpunk .bt-progress-fill { background: linear-gradient(90deg, var(--mint), var(--brass)); }

:root.theme-cyberpunk .tooltip {
  background: linear-gradient(180deg, #1e1e34, #12121f);
  box-shadow: 0 16px 36px -8px rgba(1, 2, 8, .92), 0 0 0 1px rgba(34, 211, 238, .14);
}
:root.theme-cyberpunk .tooltip::after { border-top-color: #12121f; }
:root.theme-cyberpunk .tooltip strong { color: #ffffff; }
:root.theme-cyberpunk .toast { background: linear-gradient(180deg, #22223c, #14142a); }
:root.theme-cyberpunk .toast::before { color: #2a0510; }
:root.theme-cyberpunk .toast.good::before { color: #041a20; }
:root.theme-cyberpunk .choice-fallback { color: #3d3a63; }
:root.theme-cyberpunk .choice-option:hover {
  border-color: var(--frost);
  background: rgba(123, 232, 255, .12);
  box-shadow: var(--lift-2), 0 0 26px -6px rgba(123, 232, 255, .7);
}
:root.theme-cyberpunk .choice-dialog::before { background: linear-gradient(90deg, transparent, var(--mint) 25%, #d8f6ff 50%, var(--mint) 75%, transparent); }
:root.theme-cyberpunk .dialog.result-win::before { background: linear-gradient(90deg, transparent, var(--mint) 25%, #d8f6ff 50%, var(--mint) 75%, transparent); }
:root.theme-cyberpunk .dialog.result-loss::before { background: linear-gradient(90deg, transparent, var(--punch) 25%, #ffc6d1 50%, var(--punch) 75%, transparent); }
:root.theme-cyberpunk .dialog.result-draw::before { background: linear-gradient(90deg, transparent, #6b6591 30%, #a9a2cf 50%, #6b6591 70%, transparent); }
:root.theme-cyberpunk .dialog.result-loss h2 { color: #ff9dae; }

:root.theme-cyberpunk .start-card {
  background:
    radial-gradient(120% 60% at 20% -6%, rgba(255, 45, 149, .14), transparent 62%),
    radial-gradient(110% 58% at 84% -4%, rgba(34, 211, 238, .12), transparent 62%),
    linear-gradient(180deg, var(--plum-2), var(--plum));
  box-shadow: 0 40px 90px -24px rgba(1, 2, 8, .96), inset 0 1px 0 rgba(196, 224, 255, .12);
}
:root.theme-cyberpunk .start-lamp::before {
  background: radial-gradient(50% 60% at 50% 0%, rgba(255, 45, 149, .28), transparent 72%);
}
:root.theme-cyberpunk .start-lamp .hero-pet { filter: drop-shadow(0 8px 14px rgba(1, 2, 8, .8)); }
:root.theme-cyberpunk .start-card h1 {
  background: linear-gradient(180deg, #ffffff 26%, var(--brass));
  -webkit-background-clip: text; background-clip: text;
  filter: drop-shadow(0 4px 24px rgba(255, 45, 149, .38));
}
:root.theme-cyberpunk .start-card input:focus-visible,
:root.theme-cyberpunk .start-card select:focus-visible { outline-color: var(--mint); }
:root.theme-cyberpunk .pack-card:hover { border-color: rgba(34, 211, 238, .55); }
:root.theme-cyberpunk .pack-card[aria-pressed="true"] {
  background: linear-gradient(180deg, rgba(255, 45, 149, .18), rgba(0, 0, 0, .24));
}
:root.theme-cyberpunk .pack-card[aria-pressed="true"]::after { color: #2a0316; }
:root.theme-cyberpunk .pack-preview .prev-pet { filter: drop-shadow(0 4px 7px rgba(1, 2, 8, .7)); }

/* ======================================================== 20  Schauplätze */
/* Schauplätze je Setting und Spieler: main.js `applyBackdrop()` setzt `--bg-image` (eigener
   Schauplatz), `--bg-image-foe` (der des Gegners) und `data-backdrop` auf <html>; die Bilder
   liegen in assets/backgrounds/<theme>/ (erzeugt von scripts/art/backgrounds.py, übernommen
   von web_backgrounds.py).

   Drei Orte, drei Stärken – und die Seite ist bewusst der schwächste:

     Seite (`body::before`)   dunkel, unscharf, entsättigt. Reine Kulisse. Sie ist NICHT
                              der Schauplatz der Aufstellung oder des Kampfes; stünde das
                              Bild hier scharf, sähe alles nach einem einzigen Ort aus.
     Aufstellung (`.team-panel`)  der eigene Schauplatz, scharf unter einem Schleier: hier
                              steht das eigene Team auf seinem Grund.
     Ring (`.bt-ground`)      links/rechts geteilt – die eigene Hälfte auf `--bg-image`,
                              die gegnerische auf `--bg-image-foe`. Jede Seite kämpft auf
                              ihrem eigenen Schauplatz.

   Der Schleier ist jeweils die Tintenfarbe des Settings (`--ink` über color-mix), damit
   Karten und Schrift ihren Kontrast behalten. Ohne Bild (kein Manifest, Datei fehlt) gelten
   die Verläufe der Abschnitte 2, 6, 11, 18 und 19 unverändert – deshalb steht dieser
   Abschnitt ganz am Ende: er muss die Setting-Blöcke überschreiben. */

/* Seite: der eigene Schauplatz als Stimmung, nicht als Ort. `scale` gleicht die Ränder aus,
   die der Weichzeichner sonst aufhellt. */
:root[data-backdrop] body::before {
  background: var(--bg-image) center 45% / cover no-repeat;
  filter: blur(24px) saturate(.45) brightness(.32);
  transform: scale(1.1);
}
/* Vor der Partie (Name, Menü, Lobby, Startbildschirm) gibt es weder Aufstellung noch Ring –
   dort DARF der Schauplatz das Bild sein, also ruhiger gedämpft. */
:root[data-backdrop][data-stage="lobby"] body::before {
  filter: blur(5px) saturate(.72) brightness(.46);
  transform: scale(1.04);
}
:root[data-backdrop] .start-card { backdrop-filter: blur(2px); }

/* Aufstellung: das eigene Team steht auf seinem Schauplatz. Das Bild liegt auf der REIHE,
   nicht auf dem Panel – nur so endet der Bildboden dort, wo die Einheiten stehen. Am Panel
   säße darunter noch die Kasse, und der Boden läge tiefer als das Team (auf schmalen
   Schirmen stand es dann mitten im Bild). Die Reihe ist damit das Gegenstück zum Ring.

   Die Bildunterkante liegt `--plaque-h` über dem Boden der Reihe — also genau auf der
   Standlinie der Einheiten, nicht unter ihren Schildern. Das ist der Unterschied zwischen
   „steht auf dem Boden" und „schwebt eine Plakettenhöhe darüber". Unter der Standlinie
   läuft das Bild in die Tintenfarbe aus, damit dort keine Kante steht. */
:root[data-backdrop] .team-panel .team-row {
  background-color: var(--ink);
  background-image:
    linear-gradient(180deg,
      transparent calc(100% - var(--stand) - 34px),
      var(--ink) calc(100% - var(--stand) + 2px)),
    linear-gradient(180deg,
      color-mix(in srgb, var(--ink) 88%, transparent),
      color-mix(in srgb, var(--ink) 52%, transparent) 40%,
      color-mix(in srgb, var(--ink) 74%, transparent)),
    var(--bg-image);
  background-position: center top, center top, center bottom var(--stand);
  background-size: auto, auto, cover;
  background-repeat: no-repeat;
  box-shadow: var(--lift-1), inset 0 -26px 50px -26px rgba(0, 0, 0, .7);
}

/* Ring: geteilter Grund. Der Bildboden liegt auf der Standlinie (`--stand`, Abschnitt 11) –
   dieselbe Regel wie in der Aufstellung, denn im Ring hängt unter jeder Einheit dieselbe
   Plakette. Darunter läuft das Bild in die Tintenfarbe aus. */
:root[data-backdrop] .bt-ground-half {
  background-position: center bottom var(--stand);
  background-size: cover;
  background-repeat: no-repeat;
  background-color: var(--ink);
}
:root[data-backdrop] .ground-a { background-image: var(--bg-image); }
:root[data-backdrop] .ground-b { background-image: var(--bg-image-foe); }
/* Schleier über beiden Hälften und eine weiche Naht in der Mitte – die Kante zwischen zwei
   fremden Bildern soll man ahnen, nicht sehen. */
:root[data-backdrop] .bt-ground::after {
  content: '';
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      transparent calc(100% - var(--stand) - 40px),
      var(--ink) calc(100% - var(--stand) + 2px)),
    linear-gradient(90deg, transparent 41%,
      color-mix(in srgb, var(--ink) 72%, transparent) 50%, transparent 59%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--ink) 78%, transparent),
      color-mix(in srgb, var(--ink) 46%, transparent) 34%,
      color-mix(in srgb, var(--ink) 52%, transparent) 68%,
      color-mix(in srgb, var(--ink) 82%, transparent));
}

/* ================================================ 21  Ladezustand (boot) */
/* Steht in index.html, bis main.js die Sprachdatei hat und den ersten Bildschirm baut.
   Bewusst ohne Text: ein Wort hier wäre in einer festen Sprache und würde beim Ersetzen
   kurz aufblitzen. Der Puls hört bei `prefers-reduced-motion` auf (§17 setzt die Dauer). */
.boot {
  width: 100%;
  min-height: 60vh;
  display: grid;
  place-items: center;
}
.boot::before {
  content: '';
  width: 42px; height: 42px;
  border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--line) 70%, transparent);
  border-top-color: var(--brass);
  animation: boot-spin 900ms linear infinite;
}
@keyframes boot-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .boot::before { animation: none; opacity: .5; }
}

/* ============================================ 22  Die Spalte rechts */
/* Die Rasterfläche selbst steht in §3, samt Breite je Modus. Hier steht, was in ihr
   liegt: im Netzspiel (`.sap-app[data-mode="mp"]`, gesetzt von ui/renderer.js) die
   Rangliste, im Einzelspieler die Werte (§4). Es ist dieselbe Fläche, in der früher
   die Protokollspalte lag.

   Eine Kopfzeile gibt es in keinem Modus mehr: Runde, Leben und Pokale stehen hier
   oder in der Rangliste, Gold zusätzlich am Shop. Das spart dem Spielfeld die ganze
   Leistenhöhe — auf einem Laptop der Unterschied zwischen Scrollen und nicht. */

/* Fünf große Karten und die breite Spalte des Netzspiels gehen sich erst weiter oben
   aus als die schmale des Einzelspielers. */
@media (max-width: 1400px) {
  .sap-app[data-mode="mp"] { --card-w: min(112px, var(--card-h-fit)); }
}
/* Zu schmal für zwei Spalten: die Spalte wandert flach über bzw. unter das Feld —
   die Werte gehören nach oben (sie sind die Kopfzeile), die Rangliste nach unten. */
@media (max-width: 1080px) {
  .sap-app {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "side"
      "view";
  }
  .sap-app[data-mode="mp"] {
    grid-template-areas:
      "view"
      "side";
  }
  /* Wieder eine Leiste: Titel und Werte nebeneinander. */
  .app-header { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; }
  .app-header .side-brand { flex-direction: row; align-items: baseline; gap: 8px; }
  .stats-bar { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 5px 12px; }
  .stat { justify-content: flex-start; }
  .stat.history { flex-direction: row; align-items: baseline; gap: 8px; }
  .rank-list { display: flex; flex-wrap: wrap; gap: 6px; }
  .rank-row { flex: 1 1 200px; }
  /* Übereinander kann das Feld nicht mehr allein die Fensterhöhe füllen – die Leiste
     bzw. die Rangliste braucht ihre Höhe auch noch. Die Verteilung übernimmt darum das
     Raster: die eine Zeile so hoch wie ihr Inhalt, die andere nimmt den Rest. */
  .sap-app {
    min-height: 100vh;
    grid-template-rows: auto minmax(0, 1fr);
    align-items: stretch;
  }
  .sap-app[data-mode="mp"] { grid-template-rows: minmax(0, 1fr) auto; }
  .app-view { min-height: 0; }
}

.side-panel { display: flex; flex-direction: column; gap: 10px; padding: 12px; }
/* Titel und Pack stehen in der Spalte statt in einer Kopfzeile – leise, es ist kein
   Bedienelement. */
.side-brand { display: flex; flex-direction: column; line-height: 1.2; }
.side-panel .panel-head { align-items: baseline; }
.side-panel h2 { font-size: 15px; }
.side-round { white-space: nowrap; }

/* Die große Uhr über der eigenen Aufstellung: die wichtigste Zahl der Kaufphase.
   Absolut in der Kopfzeile des Team-Panels, damit sie über der MITTE des Feldes
   steht — zwischen Titel und Bereit-Knopf wäre sie nur ungefähr mittig. */
.team-panel .panel-head { position: relative; }
.turn-clock {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  pointer-events: none;                 /* nichts abfangen, was darunter liegt */
  z-index: 2;
}
.turn-secs {
  font-size: 38px; font-weight: 800; line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  text-shadow: 0 2px 10px rgba(0, 0, 0, .65);
}
.turn-bar {
  width: 120px; height: 5px; border-radius: 999px; overflow: hidden;
  background: rgba(0, 0, 0, .38);
  box-shadow: inset 0 1px 0 rgba(255, 226, 178, .07);
}
.turn-fill {
  display: block; height: 100%; width: 100%;
  background: linear-gradient(90deg, var(--brass-deep), var(--lantern));
  transition: width .2s linear;
}
/* Die letzten Sekunden: Farbe und ein ruhiger Puls im Sekundentakt. */
.turn-clock[data-low="true"] .turn-secs { color: var(--punch); animation: turnPulse 1s ease-in-out infinite; }
.turn-clock[data-low="true"] .turn-fill { background: linear-gradient(90deg, var(--punch-deep), var(--punch)); }
@keyframes turnPulse {
  0%, 100% { transform: scale(1); }
  30% { transform: scale(1.12); }
}
/* Schmale Fenster: kleiner, aber nicht weg – die Spalte gibt ihre Uhr ab, solange
   diese hier sichtbar ist, und ganz ohne Countdown dazustehen wäre schlimmer als
   eine Zahl, die neben dem Titel etwas eng steht. */
@media (max-width: 720px) {
  .turn-secs { font-size: 26px; }
  .turn-bar { width: 84px; }
}

/* Uhr: der Balken IST die Restzeit (ui/matchView.js zählt lokal herunter). */
.match-clock { display: flex; flex-direction: column; gap: 5px; }
.clock-bar {
  height: 7px; border-radius: 999px; overflow: hidden;
  background: rgba(0, 0, 0, .28);
  box-shadow: inset 0 1px 0 rgba(255, 226, 178, .06);
}
.clock-fill {
  display: block; height: 100%; width: 100%;
  background: linear-gradient(90deg, var(--brass-deep), var(--lantern));
  transition: width .2s linear;
}
.match-clock[data-phase="battle"] .clock-fill {
  background: linear-gradient(90deg, var(--punch-deep), var(--punch));
}
/* Die letzten zehn Sekunden sieht man, ohne die Zahl zu lesen. */
.match-clock[data-low="true"] .clock-fill { background: linear-gradient(90deg, var(--punch-deep), var(--punch)); }
.match-clock[data-low="true"] .clock-text { color: var(--punch); }
.clock-text { font-size: 12px; color: var(--text-dim); font-variant-numeric: tabular-nums; }

/* Rangliste: eine Zeile je Spieler, der eigene Platz hervorgehoben. */
.rank-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.rank-row {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr) auto auto;
  align-items: center; gap: 6px;
  padding: 5px 7px;
  border-radius: var(--r-ctrl);
  background: rgba(0, 0, 0, .18);
  box-shadow: inset 0 1px 0 rgba(255, 226, 178, .05);
  font-size: 12.5px;
}
.rank-row[data-selectable] { cursor: pointer; }
.rank-row.rank-self {
  background: linear-gradient(180deg, rgba(232, 169, 74, .20), rgba(232, 169, 74, .07));
  box-shadow: inset 0 0 0 1px rgba(232, 169, 74, .35);
}
.rank-row.rank-out { opacity: .5; }
.rank-no { color: var(--text-faint); font-size: 11px; text-align: right; font-variant-numeric: tabular-nums; }
.rank-name { display: flex; align-items: baseline; gap: 4px; min-width: 0; }
.rank-who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; }
.rank-you { color: var(--text-faint); font-size: 10.5px; font-style: normal; }
.rank-lives, .rank-tro { font-variant-numeric: tabular-nums; white-space: nowrap; font-size: 11.5px; }
.rank-lives { color: var(--punch); }
.rank-tro { color: var(--text-dim); }
/* Der Zustandsvermerk steht in der zweiten Zeile, sonst reißt die Spalte auf. */
.rank-tag {
  grid-column: 2 / -1;
  font-size: 10.5px; color: var(--text-faint);
  text-transform: uppercase; letter-spacing: .04em;
}
.rank-row.rank-ready .rank-tag { color: var(--mint); }
/* Ergebnis der letzten Runde als schmale Kante links. */
.rank-row.rank-win { border-left: 3px solid var(--mint-deep); }
.rank-row.rank-loss { border-left: 3px solid var(--punch-deep); }
.rank-row.rank-draw { border-left: 3px solid var(--line); }

.match-note { font-size: 12px; color: var(--text-dim); }
/* Der Ausgang sitzt unten und leise – er soll erreichbar sein, nicht einladend. */
.match-leave { align-self: flex-start; margin-top: auto; opacity: .65; }
.match-leave:hover { opacity: 1; }
.match-leave.is-confirming { opacity: 1; color: var(--punch); border-color: var(--punch-deep); }
.rank-final { margin: 12px 0; max-width: 420px; }

/* Wartetafel und Abschluss stehen anstelle des Spielfelds – mittig in der Höhe,
   aus demselben Grund wie der Ring (Abschnitt 11). */
.wait-panel, .outcome-panel {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 28px 18px; text-align: center;
  margin-block: auto;
}
.wait-panel h2, .outcome-panel h2 { font-size: 20px; }
.outcome-panel.result-win h2 { color: var(--mint); }
.match-hint { color: var(--text-dim); font-size: 13px; }
/* Der Hinweis unter dem Shop, sobald man „bereit" gemeldet hat. */
.shop-view + .match-hint, .app-view > .match-hint { margin-top: 10px; text-align: center; }

/* Solange ein Kommando unterwegs ist: kein zweiter Klick, sichtbares Warten. */
.sap-app[data-busy] .app-view { cursor: progress; }
.btn.go.is-pressed {
  filter: saturate(.7) brightness(.92);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, .35);
}
