/* ══════════════ Gemeinsame Lobby-Basis ══════════════ Anfang ═══════════════
   ERZEUGT – NICHT HIER ÄNDERN. Quelle: /var/www/html/gemeinsam/lobby.css
   Ändern, dann `node werkzeug/verteilen.mjs` – das schreibt diesen Block in
   jedes Spiel. `--pruefen` meldet, wo er abgewichen ist.

   --akzent/--akzent2 setzt jedes Spiel unterhalb des Endmarkers selbst;
   alles davon oberhalb ist in allen Spielen gleich.
   ────────────────────────────────────────────────────────────────────────── */

:root {
  --bg: #0a0612;
  --bg2: #140b23;
  --panel: rgba(30, 18, 52, .72);
  --line: rgba(160, 120, 255, .18);
  --ink: #f2ecff;
  --muted: #9c8fc2;
  --hot: #ff2e88;
  --hot2: #ff8a3d;
  --cool: #35e6ff;
  --gold: #ffd447;
  --good: #52ffa8;
  --bad: #ff4d5e;
  --r: 14px;
  --shadow: 0 10px 30px rgba(0, 0, 0, .55);

  /* Voreinstellung, wird je Spiel überschrieben */
  --akzent: var(--hot);
  --akzent2: var(--gold);
}

/* Screens: beide Schaltklassen, damit jedes Spiel seinen bisherigen
   Umschalter behalten kann (.on in Card Chaos, .active in den anderen). */
.screen.on, .screen.active, .view.active { display: flex; }

/* ── Typo ─────────────────────────────────────────────────────────────── */
.muted { color: var(--muted); }
.small { font-size: 13px; }
.center { text-align: center; }
.spacer { flex: 1; }
.row { display: flex; align-items: center; }
.row.gap { gap: 10px; flex-wrap: wrap; justify-content: center; }

.logo {
  font-size: clamp(38px, 8vw, 76px); font-weight: 900;
  letter-spacing: -.03em; line-height: .92; text-align: center;
  background: linear-gradient(100deg, #fff 10%, var(--akzent) 45%, var(--akzent2) 95%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 4px 24px rgba(255, 46, 136, .35));
}
.logo span {
  display: block;
  background: linear-gradient(100deg, var(--cool), #a06bff);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.logo.sm { font-size: 20px; line-height: 1; }
.logo.sm span { display: inline; }
.tag {
  color: var(--muted); margin-top: 10px; font-size: 15px;
  letter-spacing: .12em; text-transform: uppercase; text-align: center;
}

/* ── Panels ───────────────────────────────────────────────────────────── */
.panel {
  background: var(--panel); border: 1px solid var(--line); border-radius: 20px;
  padding: 24px; backdrop-filter: blur(14px); box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: 12px; width: 100%;
}
.panel.narrow { max-width: 380px; }
.panel.wide { max-width: 700px; }

/* ── Formulare ────────────────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: 6px; }
.field span {
  font-size: 12px; text-transform: uppercase;
  letter-spacing: .12em; color: var(--muted);
}
input, select {
  background: rgba(0, 0, 0, .35); border: 1px solid var(--line); color: var(--ink);
  border-radius: 12px; padding: 13px 15px; font-family: inherit; width: 100%;
  /* 16px ist Pflicht: darunter zoomt iOS Safari beim Fokus in das Feld hinein. */
  font-size: 16px;
  transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus {
  outline: none; border-color: var(--akzent);
  box-shadow: 0 0 0 3px rgba(255, 46, 136, .18);
}

/* ── Buttons ──────────────────────────────────────────────────────────── */
.btn {
  border: 1px solid var(--line); background: rgba(255, 255, 255, .06); color: var(--ink);
  border-radius: 12px; padding: 13px 18px; font-size: 15px; font-weight: 700;
  font-family: inherit; cursor: pointer; user-select: none;
  transition: transform .12s, filter .15s, background .15s;
}
.btn:hover { background: rgba(255, 255, 255, .12); }
.btn:active { transform: scale(.96); }
.btn.big { padding: 16px 26px; font-size: 17px; }
/* .sm und .small sind dasselbe – die vier Spiele hatten je eine der beiden
   Schreibweisen, beide bleiben gültig, damit kein Markup umgeschrieben wird. */
.btn.sm, .btn.small { padding: 8px 12px; font-size: 13px; width: auto; }
.btn.ghost { background: transparent; }
.btn.primary {
  background: linear-gradient(100deg, var(--akzent), var(--akzent2));
  border-color: transparent; color: #180a12;
  box-shadow: 0 6px 22px rgba(255, 46, 136, .3);
}
.btn.primary:hover { filter: brightness(1.12); }
.btn.on { background: linear-gradient(100deg, #1ec98a, var(--good)); color: #04220f; border-color: transparent; }
.btn:disabled { opacity: .35; cursor: not-allowed; transform: none; }

/* ── Trenner „oder beitreten" ─────────────────────────────────────────── */
.or { display: flex; align-items: center; gap: 12px; color: var(--muted); font-size: 13px; }
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* ── Einstellungszeile: Beschriftung links, Schalter rechts ───────────── */
.setting { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.setting-label {
  font-size: 12px; color: var(--muted);
  text-transform: uppercase; letter-spacing: .12em;
}

/* ── Sichtbarkeit: Öffentlich | Privat ────────────────────────────────── */
.segmented {
  display: flex; gap: 4px; padding: 4px;
  background: rgba(0, 0, 0, .35); border: 1px solid var(--line); border-radius: 12px;
}
.seg {
  flex: 1; border: 0; background: transparent; color: var(--muted);
  font: 700 14px/1 inherit; font-family: inherit; padding: 10px 8px;
  border-radius: 9px; cursor: pointer; transition: background .15s, color .15s;
}
.seg.sel { background: rgba(255, 255, 255, .1); color: var(--ink); }

/* ── Raumcode + Teilen ────────────────────────────────────────────────── */
.codebox {
  text-align: center; background: var(--panel);
  border: 2px dashed var(--line); border-radius: var(--r); padding: 16px;
}
.codebox-label {
  display: block; font-size: 11px; letter-spacing: .18em;
  color: var(--muted); text-transform: uppercase;
}
.codebox strong {
  display: block; font-size: clamp(34px, 11vw, 46px); font-weight: 900;
  letter-spacing: .22em; color: var(--gold); margin: 4px 0 10px;
  /* Der Code wird abgetippt und vorgelesen – Ziffern gleich breit. */
  font-variant-numeric: tabular-nums;
}
.codebox-vis { display: block; font-size: 12px; color: var(--muted); margin-bottom: 10px; }
.codebox .btn { margin: 0 auto; }

.joinrow { display: flex; gap: 10px; }
.joinrow input { text-align: center; letter-spacing: .3em; font-weight: 800; }
.joinrow .btn { width: auto; flex: 0 0 auto; }

/* ── Offene Räume ─────────────────────────────────────────────────────── */
.rooms-head {
  font-size: 13px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
}
.rooms-head span { color: var(--cool); }
.roomlist { display: flex; flex-direction: column; gap: 8px; }
.rooms-empty {
  font-size: 13px; color: var(--muted); line-height: 1.45;
  padding: 12px 14px; border: 2px dashed var(--line); border-radius: var(--r);
}
.roomrow {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center; gap: 10px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r); padding: 12px 14px;
  cursor: pointer; text-align: left; color: inherit;
  font-family: inherit; font-size: 15px;
  transition: transform .14s, border-color .15s, background .15s;
}
.roomrow:hover { transform: translateY(-2px); border-color: var(--akzent); background: rgba(255, 46, 136, .1); }
.roomrow:active { transform: scale(.98); }
.roomrow-name { font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.roomrow-meta { font-size: 12px; color: var(--muted); }
.roomrow-code { font-weight: 900; letter-spacing: .12em; color: var(--gold); font-variant-numeric: tabular-nums; }
.roomrow-count { font-weight: 900; color: var(--gold); font-variant-numeric: tabular-nums; }

.pill {
  font-size: 11px; padding: 3px 9px; border-radius: 99px;
  background: rgba(255, 255, 255, .1); letter-spacing: .06em;
  text-transform: uppercase; white-space: nowrap;
}
.pill.live { background: rgba(255, 46, 136, .22); color: var(--hot); }
.pill.open { background: rgba(82, 255, 168, .18); color: var(--good); }

/* ── Warteraum: Sitze ─────────────────────────────────────────────────── */
/* 110px, nicht 140: bei 360px Displaybreite bleiben nach Screen- und
   Panel-Polsterung nur ~276px übrig – mit 140px stünden die Sitze
   untereinander und der Warteraum wäre doppelt so hoch. */
.seats { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 12px; margin: 8px 0 4px; }
.seat {
  border: 1px solid var(--line); border-radius: 16px; padding: 16px 12px;
  text-align: center; background: rgba(0, 0, 0, .28);
  transition: border-color .2s, box-shadow .2s;
}
.seat.ready { border-color: var(--good); box-shadow: 0 0 0 3px rgba(82, 255, 168, .12); }
.seat.off { opacity: .45; }
.seat .av { font-size: 30px; }
.seat .nm { font-weight: 800; margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.seat .st { font-size: 12px; color: var(--muted); margin-top: 3px; }
.seat.ready .st { color: var(--good); }
.seat .host { font-size: 11px; color: var(--gold); letter-spacing: .1em; }
.seat.empty { border-style: dashed; opacity: .4; }

/* ── Tippen statt Zoomen ─────────────────────────────────────────────────
   `user-scalable=no` im Viewport steht in jedem Spiel – und iOS Safari hält
   sich seit Version 10 nicht mehr daran. Der Doppeltipp-Zoom bleibt damit an,
   und mit ihm die Wartezeit: der Browser hält jeden Tipp erst zurück, um zu
   sehen, ob ein zweiter folgt. Wer schnell hintereinander tippt – und genau
   das tut man in einem Spiel –, dessen zweiter Tipp verschwindet dann im
   Zoomversuch. „Am Handy geht es manchmal nicht, Karten lassen sich nicht
   anklicken" (Bugreport 13).

   `manipulation` schaltet genau diese Gesten ab und lässt Scrollen und
   Aufziehen in Ruhe. */
html, body, button, .btn, .seat, .roomrow, .seg { touch-action: manipulation; }

/* ── Der Weg zurück ──────────────────────────────────────────────────────
   Jeder Bildschirm braucht einen sichtbaren Ausgang: von der Startseite eines
   Spiels zur Übersicht, aus Runde und Endstand aus dem Raum. Vorher hatten nur
   die fünf Spiele ohne Lobby einen solchen Link, und aus dem Spielbildschirm
   führte für alle ausser dem Host gar nichts heraus – Bugreport 10. */
.zurueckzeile { text-align: center; margin-top: 12px; }
.zurueck {
  display: inline-block; padding: 6px 4px;
  color: var(--muted); font-size: 13px; text-decoration: none;
}
.zurueck:hover { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .btn, .roomrow, .seat { transition: none; }
  /* Auch Einblend-Animationen aus: sie starten bei opacity 0, und wer
     Bewegung abgeschaltet hat, soll den Inhalt sofort sehen – nicht erst
     nach der Animation. Nebenbei trifft so auch der Layout-Screenshot
     nicht mehr Frame 0. */
  .screen, .screen.on { animation: none !important; }
}


/* --- Sprachwahl ---------------------------------------------------------- */
/* Der Umschalter wird von sprache.js gefuellt und bleibt ohne JavaScript leer
   – deshalb :empty, sonst stuende dort ein leerer Kasten. Er steht auf dem
   Startbildschirm: gewaehlt wird vor dem Spielen, und die Wahl gilt
   geraeteweit fuer alle Spiele. */
.sprachwahl {
  display: flex;
  gap: 2px;
  padding: 2px;
  margin: 10px auto 0;
  width: fit-content;
  border: 1px solid var(--linie, rgba(255, 255, 255, .14));
  border-radius: 999px;
  background: rgba(255, 255, 255, .04);
}
.sprachwahl:empty { display: none; }

.sprachknopf {
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .08em;
  padding: 5px 11px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--leise, #9c8fc2);
  cursor: pointer;
  transition: color .18s ease, background .18s ease;
}
.sprachknopf:hover { color: #fff; }
.sprachknopf.sel { background: rgba(255, 255, 255, .12); color: #fff; }
.sprachknopf:focus-visible { outline: 2px solid var(--akzent, #52ffa8); outline-offset: 2px; }

/* ══════════════ Gemeinsame Lobby-Basis ══════════════ Ende ═════════════════ */

/* Keep: eigener Akzent + Altnamen, die der Spielteil weiterbenutzt. */
:root {
  --akzent: var(--hot2);
  --akzent2: var(--gold);
  --text: var(--ink);
  --panel2: #262b52;
  --primary: var(--hot2);
  --primary2: var(--gold);
  --green: var(--good);
  --red: var(--bad);
  --radius: var(--r);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; height: 100%; }

body {
  background:
    radial-gradient(120% 90% at 50% -10%, #241041 0%, var(--bg) 60%),
    var(--bg);
  color: var(--ink);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  overscroll-behavior: none;
}

#app { min-height: 100%; }

/* -------- Screens -------- */
.screen { display: none; animation: fade .25s ease; }
/* display gehört hierher, nicht nur in die Basis: die Regel darüber kommt
   später als der gemeinsame Block und würde sonst display:none gewinnen. */
.screen.active {
  display: flex; flex-direction: column; align-items: center;
  /* „safe center": mittig, solange es passt – sonst nach oben statt oben UND
     unten abgeschnitten. */
  justify-content: safe center;
  gap: 20px; min-height: 100dvh;
  padding: clamp(18px, 5vw, 40px) 18px;
  padding-bottom: max(clamp(18px, 5vw, 40px), env(safe-area-inset-bottom));
}
@keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.hero { text-align: center; }
h2 { font-size: 26px; font-weight: 800; letter-spacing: -.02em; }

.hint { color: var(--muted); font-size: 14px; margin: 0 0 16px; }

/* Karten-Container des Spielteils */
.card.wide { text-align: left; margin-top: 3vh; }

/* -------- Listen: Zwischenstand, Bestenliste -------- */
.players, .standings { list-style: none; padding: 0; margin: 14px 0; width: 100%; }
.standings li {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px; border: 1px solid var(--line);
  border-radius: 12px; margin-bottom: 8px; background: rgba(0, 0, 0, .28);
}
.standings li .rank { font-weight: 700; color: var(--muted); width: 28px; }
.standings li .nm { flex: 1; margin-left: 8px; }
.standings li .pts { font-weight: 700; }
.standings li .delta { color: var(--good); font-size: 13px; margin-left: 10px; }
.standings li:first-child { border-color: var(--gold); }

/* -------- Bestenliste --------
   Gleicher Aufbau wie in Card Chaos, damit die beiden Spiele sich gleich
   anfuehlen: jede Zeile eine eigene Karte, Platz links, Name mit Unterzeile,
   Punkte rechts. Die Farben sind Keeps eigene - Akzent ist hier Orange, nicht
   Pink. Die Unterzeile darf umbrechen: "3 Partien" ist der halbe Grund, warum
   eine Person nur eine Zeile bekommt - abgeschnitten nuetzt das nichts. */
.lb { display: flex; flex-direction: column; gap: 7px; width: 100%; margin: 4px 0 12px; }
.res {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 12px;
  background: rgba(0, 0, 0, .28); border: 1px solid var(--line); text-align: left;
  animation: slidein .4s backwards;
}
@keyframes slidein { from { opacity: 0; transform: translateX(-16px); } }
.res .pl { font-size: 15px; font-weight: 900; width: 36px; text-align: center; color: var(--muted); }
.res.p1 .pl, .res.p2 .pl, .res.p3 .pl { color: var(--gold); font-size: 19px; }
.res .nm { flex: 1; font-weight: 700; min-width: 0; }
.res .sub { font-size: 11px; color: var(--muted); font-weight: 600; line-height: 1.35; }
.res .sc { font-weight: 900; font-size: 19px; font-variant-numeric: tabular-nums; }
.res.p1 { border-color: var(--gold); background: linear-gradient(90deg, rgba(255, 212, 71, .16), rgba(0, 0, 0, .28)); }
.res.p1 .sc { color: var(--gold); }
.res.me { box-shadow: inset 0 0 0 1px var(--cool); }

/* Kopfzeile der Bestenliste: Weg zurueck links, Titel rechts. */
.bar {
  display: flex; align-items: center; gap: 10px;
  width: 100%; max-width: 700px; padding-bottom: 4px;
}
/* Nur die gewaehlte Ansicht traegt den Akzent - sie entscheidet, was
   darunter steht. */
#screen-leaderboard .segmented { width: 100%; }
#screen-leaderboard .seg { font-size: 13px; padding: 10px 4px; }
#screen-leaderboard .seg.sel {
  color: #170221;
  background: linear-gradient(100deg, var(--akzent), var(--akzent2));
}

/* Kurzmeldung unten – Keep schaltet sie über .show. */
#toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: max(20px, env(safe-area-inset-bottom));
  background: rgba(20, 11, 35, .96); border: 1px solid var(--line);
  border-radius: 99px; padding: 11px 20px; font-size: 14px; font-weight: 600;
  z-index: 90; pointer-events: none; opacity: 0; transition: opacity .2s;
}
#toast.show { opacity: 1; }

/* -------- Spielfeld-Layout --------
   Der Spiel-Screen ist eine Column-Flexbox mit align-items:center. Ohne
   eigene Breite werden die Kinder darin auf ihre Inhaltsbreite geschrumpft
   (Timerbalken -> ein Strich) oder auf die volle Fensterbreite gezogen
   (Walzen -> halber Bildschirm). Also: feste Brettbreite fuer alle Kinder.

   --reel-h haengt an der Fensterhoehe, damit Walzen UND Kombi-Liste
   zusammen auf den Schirm passen - das ist der Sinn des Screens. */
#screen-game { --reel-h: clamp(70px, 19dvh, 150px); --board: 560px; }
#screen-game.active {
  /* Die Elemente bringen ihre eigenen Abstaende mit, der 20px-Screen-Gap
     kaeme oben drauf und kostet ueber sechs Kinder gut 120px Hoehe. */
  gap: 0;
  justify-content: flex-start;
  padding-block: clamp(10px, 2.2vh, 22px);
}
#screen-game > * { width: 100%; max-width: var(--board); }
/* Aus der Walzenhoehe zurueckgerechnet: 5 Kacheln im Verhaeltnis 3:4 plus
   4 Luecken. So bleibt die Kachel quadratisch-hoch statt verzerrt. */
#screen-game > .reels { max-width: min(var(--board), calc(var(--reel-h) * .75 * 5 + 32px)); }
#screen-game .card-title { font-size: 15px; margin: 12px 0 8px; }

/* -------- Game head -------- */
.game-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin: 6px 0 14px;
}
.pill {
  background: var(--panel2); border: 1px solid var(--line);
  padding: 8px 14px; border-radius: 999px; font-weight: 600; font-size: 14px;
}
.pill.score { color: var(--gold); font-variant-numeric: tabular-nums; }
.pill.mult { color: var(--green); }
.pill.mult.hot { color: #ff8a3c; }
/* Als Animation, nicht als bleibender transform: die Klasse setzt app.js nur
   einmal und nimmt sie nie wieder weg - der Pill blieb sonst dauerhaft um
   35% aufgeblasen und schob sich ueber den Runden-Pill. */
.pill.mult.bump, .pill.score.bump { animation: pillbump .3s ease; }
@keyframes pillbump { 50% { transform: scale(1.35); } }
/* Timer als Balken */
.timerbar {
  height: 14px; background: var(--bg2); border: 1px solid var(--line);
  border-radius: 999px; overflow: hidden; margin: 0 0 6px;
}
.timerbar-fill {
  height: 100%; width: 100%;
  background: linear-gradient(90deg, var(--green), var(--primary));
  transition: width .2s linear;
}
.timerbar-fill.low {
  background: linear-gradient(90deg, #ff8a3c, var(--red));
  animation: barpulse .6s infinite alternate;
}
@keyframes barpulse { to { opacity: .6; } }

/* Glut als zweiter, duennerer Balken direkt unter der Uhr. Er laeuft staendig
   ab; jede gewertete Kombination laedt ihn auf, seltene staerker. */
.glutbar {
  height: 8px; background: var(--bg2); border: 1px solid var(--line);
  border-radius: 999px; overflow: hidden; margin: 0 0 2px;
}
.glutbar-fill {
  height: 100%; width: 0;
  background: linear-gradient(90deg, var(--gold), #ff8a3c);
  transition: width .2s linear;
}
.glutbar-fill.hot {
  background: linear-gradient(90deg, #ff8a3c, var(--red));
  box-shadow: 0 0 10px rgba(255, 120, 60, .55);
}

/* -------- Reels -------- */
.reels {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; margin: 8px 0 14px;
  position: relative;
}
/* Ein Stups aufs ganze Feld, wenn drei oder mehr Gleiche liegen. Nur
   `transform` - es verschiebt sich nichts, es wackelt nur kurz. */
.reels.stups { animation: feldstups .38s cubic-bezier(.3, 1.6, .4, 1); }
@keyframes feldstups {
  0%, 100% { transform: none; }
  35% { transform: scale(1.035) translateY(-3px); }
  70% { transform: scale(.995); }
}
/* Licht hinter dem Feld, sobald die Glut traegt. Es liegt HINTER den Walzen
   (z-index: -1) und ist unscharf - es faerbt, es verdeckt nicht. */
.reels::before {
  content: ""; position: absolute; inset: -10px; z-index: -1; border-radius: 22px;
  background: radial-gradient(60% 120% at 50% 50%, rgba(255, 138, 60, .55), rgba(255, 138, 60, 0) 70%);
  opacity: 0; filter: blur(10px); transition: opacity .4s ease;
}
.reels.heiss::before { opacity: .55; animation: feldlicht 1.6s ease-in-out infinite alternate; }
.reels.sehrheiss::before {
  opacity: .9;
  background: radial-gradient(60% 120% at 50% 50%, rgba(255, 77, 94, .6), rgba(255, 212, 71, .25) 45%, rgba(255, 138, 60, 0) 75%);
  animation-duration: .9s;
}
@keyframes feldlicht { from { opacity: .35; } to { opacity: .95; } }
.reel {
  aspect-ratio: 3/4; background: var(--bg2); border: 2px solid var(--line);
  border-radius: 14px; display: flex; align-items: center; justify-content: center;
  cursor: pointer; position: relative; transition: border-color .12s, transform .12s;
  overflow: hidden;
}
.reel svg { width: 58%; height: 58%; }
.reel .reel-ic { display: flex; width: 100%; height: 100%; align-items: center; justify-content: center; }
.reel.empty { color: var(--line); }
.reel.held { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(245,197,66,.25) inset; }
.reel.held::after {
  content: "HALT"; position: absolute; bottom: 4px; font-size: 9px; font-weight: 800;
  letter-spacing: .1em; color: var(--gold);
}
.reel.halt-an { animation: haltpop .22s ease; }
@keyframes haltpop { 40% { transform: scale(1.09); } }

/* Einfliegen. Das Symbol steht in dem Moment fest, in dem es gezogen wird,
   und es steht auch sofort da - die Animation laeuft ueber ein bereits
   lesbares Feld. Ein Automat, der erst eine Sekunde rollt, ist woanders
   schoen; hier laeuft die Uhr, und die Glut faellt waehrenddessen weiter. */
.reel.spin .reel-ic { animation: walzeein .4s cubic-bezier(.2, 1.2, .35, 1); }
@keyframes walzeein {
  0%   { transform: translateY(-115%) scale(1, 1.2); opacity: 0; }
  60%  { transform: translateY(5%) scale(1.06, .92); opacity: 1; }
  100% { transform: none; }
}
/* Der Rahmen blitzt einmal mit - das ist das Licht, das den Blick aufs neue
   Symbol zieht, ohne dass irgendetwas darauf wartet. */
.reel.spin { animation: walzeblitz .4s ease-out; }
@keyframes walzeblitz {
  0%   { border-color: rgba(255, 212, 71, .85); box-shadow: 0 0 14px rgba(255, 212, 71, .35); }
  100% { border-color: var(--line); box-shadow: none; }
}
/* Gewinnlinie: was zusammengehoert, leuchtet kurz auf. */
.reel.gewinn { border-color: var(--gold); }
.reel.gewinn-gross { border-color: var(--gold); animation: reelgewinn .45s ease-in-out 3; }
@keyframes reelgewinn {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 212, 71, .2); }
  50% { box-shadow: 0 0 22px 3px rgba(255, 212, 71, .8); transform: scale(1.05); }
}

/* Draw-Buttons */
.draws { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.btn.draw { margin-top: 0; position: relative; overflow: hidden; }
/* Ueber den Knopf, der dran ist, laeuft ein Licht. Er ist der einzige, der
   gerade etwas tut - und man findet ihn, ohne hinzusehen. */
.btn.draw.primary::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 35%, rgba(255, 255, 255, .45) 50%, transparent 65%);
  transform: translateX(-100%); animation: drawglanz 2s ease-in-out infinite;
}
@keyframes drawglanz { 0%, 55% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }
.btn.draw.used { background: var(--bg2); color: var(--muted); opacity: .45; }
.btn.draw:disabled { opacity: .4; cursor: not-allowed; }
.draw-hint { text-align: center; color: var(--muted); font-size: 13px; margin: 10px 0 2px; }

/* -------- Scorecard -------- */
/* auto-fit statt fester Spaltenzahl: 12 Kombinationen einspaltig sind auf
   dem Handy dreimal so hoch wie der Schirm. So legt die Breite die Spalten
   fest - zwei auf dem Handy, drei auf dem Spielbrett am Rechner. */
.scorecard { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; }
.cat {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--bg2); border: 1px solid var(--line); border-radius: 12px;
  padding: 11px 13px; cursor: pointer; transition: border-color .12s, background .12s;
}
.cat .cat-name { display: flex; align-items: center; gap: 7px; font-size: 14px; }
.cat .cat-name svg { width: 18px; height: 18px; }
.cat .cat-pts { font-weight: 700; font-variant-numeric: tabular-nums; font-size: 13px; }

/* Muster-Anzeige (qqq+kk usw.) */
.pat { display: inline-flex; align-items: center; gap: 3px; }
.pat-ic { width: 17px; height: 17px; display: inline-flex; }
.pat-ic svg { width: 100%; height: 100%; }
.pat-plus { color: var(--muted); font-weight: 800; margin: 0 2px; font-size: 15px; }
.cat.available { border-color: var(--green); }
.cat.available .cat-pts { color: var(--green); }
/* Neu dazugekommen: die Kachel blitzt einmal auf. Das fuehrt den Blick durch
   die zwoelf Felder, ohne dass man Zahlen vergleichen muss - und es ist nach
   einer halben Sekunde vorbei. */
.cat.available.neu { animation: kachelneu .5s ease-out; }
@keyframes kachelneu {
  0%   { border-color: var(--good); box-shadow: 0 0 0 0 rgba(82, 255, 168, .55); transform: scale(1); }
  35%  { box-shadow: 0 0 14px 2px rgba(82, 255, 168, .5); transform: scale(1.025); }
  100% { box-shadow: 0 0 0 0 rgba(82, 255, 168, 0); transform: scale(1); }
}
.cat.available.gross.neu { animation-name: kachelneugross; }
@keyframes kachelneugross {
  0%   { box-shadow: 0 0 0 0 rgba(255, 212, 71, .6); transform: scale(1); }
  35%  { box-shadow: 0 0 20px 4px rgba(255, 212, 71, .6); transform: scale(1.04); }
  100% { box-shadow: 0 0 0 0 rgba(255, 212, 71, 0); transform: scale(1); }
}
/* Ab 90.000 ist es kein gewoehnlicher Treffer mehr: die Kachel wird golden
   und ein Licht laeuft einmal je Sekunde darueber. */
.cat.available.gross {
  border-color: var(--gold); position: relative; overflow: hidden;
  background: linear-gradient(100deg, rgba(255, 212, 71, .16), rgba(255, 212, 71, 0) 65%), var(--bg2);
}
.cat.available.gross .cat-pts { color: var(--gold); }
.cat.available.gross::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 35%, rgba(255, 255, 255, .28) 50%, transparent 65%);
  transform: translateX(-100%); animation: kachelglanz 1.6s ease-in-out infinite;
}
@keyframes kachelglanz { 0%, 45% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }
.cat.zero .cat-pts { color: var(--muted); }
.cat.done { opacity: .55; cursor: default; }
.cat.done .cat-pts { color: var(--gold); }
.cat.done .cat-name::before { content: "✓ "; color: var(--gold); }

/* -------- Misc -------- */
.spinner {
  width: 42px; height: 42px; margin: 0 auto 16px; border-radius: 50%;
  border: 4px solid var(--line); border-top-color: var(--primary);
  animation: rot 1s linear infinite;
}
@keyframes rot { to { transform: rotate(360deg); } }

/* -------- Jubel --------
   Er haengt oben am Rand, nicht in der Bildmitte: dort lag er ueber den
   Walzen und verdeckte waehrend eines guten Laufs genau das, was man als
   Naechstes antippen wollte. Mehrere Meldungen stapeln sich untereinander,
   statt sich gegenseitig zu ueberschreiben. */
.celebrate {
  position: relative; height: 44px; margin: 2px 0 4px;
  pointer-events: none; z-index: 3;
}
/* Die Meldungen liegen absolut in ihrer Zeile: zwei kurz hintereinander
   schieben dann nichts auseinander. */
.celebrate .burst {
  /* Die Mitte steht hier und nicht erst in den Keyframes: sonst haengt die
     Meldung schief, sobald die Animation aus ist (Systemeinstellung). */
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  font-size: clamp(16px, 4.4vw, 23px); font-weight: 900; letter-spacing: .01em;
  padding: 7px 20px; border-radius: 999px; white-space: nowrap;
  background: rgba(10, 6, 18, .82); border: 1px solid rgba(255, 212, 71, .45);
  color: var(--gold); text-shadow: 0 0 18px rgba(255, 212, 71, .45);
  animation: burstauf 1.25s cubic-bezier(.2, .9, .25, 1) forwards;
}
.celebrate .burst.gross {
  font-size: clamp(18px, 5vw, 26px); color: #ffb765;
  border-color: rgba(255, 138, 60, .7); box-shadow: 0 0 28px rgba(255, 138, 60, .35);
}
.celebrate .burst.jackpot {
  font-size: clamp(20px, 5.8vw, 30px);
  background: linear-gradient(100deg, rgba(255, 46, 136, .28), rgba(255, 212, 71, .28));
  border-color: var(--gold); box-shadow: 0 0 40px rgba(255, 212, 71, .5);
  color: #fff; animation-duration: 1.9s;
}
.celebrate .burst.schlecht {
  color: #ff9aa6; border-color: rgba(255, 77, 94, .5); text-shadow: none;
  font-size: clamp(15px, 4vw, 21px);
}
/* Das translate(-50%, -50%) steckt in jedem Schritt: es ist hier nicht
   Bewegung, sondern die Mitte der Zeile. */
@keyframes burstauf {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(.8); }
  14%  { opacity: 1; transform: translate(-50%, -50%) scale(1.07); }
  24%  { transform: translate(-50%, -50%) scale(1); }
  76%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(.94); }
}

/* Farbschleier ueber der Seite - kurz, und ohne etwas zu verdecken. */
.flash { animation: flashbg .5s ease; }
.flash-gross { animation: flashgross .55s ease; }
.flash-jackpot { animation: flashjackpot .85s ease; }
.flash-schlecht { animation: flashschlecht .5s ease; }
@keyframes flashbg { 0%,100% { background-color: transparent; } 40% { background-color: rgba(245,197,66,.12); } }
@keyframes flashgross { 0%,100% { background-color: transparent; } 35% { background-color: rgba(255,138,60,.2); } }
@keyframes flashjackpot {
  0%, 100% { background-color: transparent; }
  20% { background-color: rgba(255, 212, 71, .3); }
  50% { background-color: rgba(255, 46, 136, .22); }
  75% { background-color: rgba(255, 212, 71, .18); }
}
@keyframes flashschlecht { 0%,100% { background-color: transparent; } 40% { background-color: rgba(255,77,94,.16); } }

.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%) translateY(20px);
  background: #000; color: #fff; padding: 12px 20px; border-radius: 999px;
  opacity: 0; pointer-events: none; transition: .25s; font-size: 14px; z-index: 50;
}
.toast.show { opacity: .95; transform: translateX(-50%) translateY(0); }

@media (max-width: 420px) {
  /* Zwei Spalten bleiben - dafuer werden die Kacheln schmaler gebaut,
     damit Muster und Punktzahl nebeneinander Platz haben. */
  .cat { padding: 8px 10px; }
  .cat .cat-pts { font-size: 12px; }
  .pat-ic { width: 14px; height: 14px; }
  .pat { gap: 2px; }
  .logo { font-size: 44px; }
}

/* ══════════════════════════ Effekte ═══════════════════════════════════════
   Alles, was fliegt, funkelt oder regnet, liegt in einer eigenen Ebene ueber
   der Seite. Zwei Regeln gelten fuer jede Zeile hier unten:

     1. `pointer-events: none` - kein Effekt nimmt je einen Klick weg.
     2. Nichts davon liegt ueber den Walzen oder der Kombi-Tafel. Der Jubel
        haengt oben am Rand, die Zahlen steigen aus der Kachel heraus nach
        oben weg, der Muenzregen faellt am Bildrand entlang.

   Wer `prefers-reduced-motion` gesetzt hat, sieht am Ende der Datei: die
   Zahlen und Farben bleiben, die Partikel fallen weg. */

#fx-lage {
  position: fixed; inset: 0; overflow: hidden;
  pointer-events: none; z-index: 65;
}

/* -------- Fliegende Zahl an einer Kachel -------- */
.fx-zahl {
  position: fixed; transform: translate(-50%, -50%);
  font-weight: 900; font-size: 20px; white-space: nowrap;
  color: var(--gold); text-shadow: 0 2px 14px rgba(0, 0, 0, .8);
  font-variant-numeric: tabular-nums;
  animation: zahlhoch 1.05s ease-out forwards;
}
.fx-zahl.gross { font-size: 28px; color: #ff8a3c; }
@keyframes zahlhoch {
  0%   { opacity: 0; transform: translate(-50%, -30%) scale(.7); }
  15%  { opacity: 1; transform: translate(-50%, -60%) scale(1.12); }
  100% { opacity: 0; transform: translate(-50%, -200%) scale(1); }
}

/* -------- Druckwelle -------- */
/* Kein Kreis quer ueber die Tafel, sondern die Kachel selbst, die einmal
   aufgeht: gleiche Groesse, gleiche Ecken, und danach ist sie weg. */
.fx-welle {
  position: fixed; transform: translate(-50%, -50%);
  border: 2px solid rgba(255, 212, 71, .8); border-radius: 12px;
  animation: welle .5s ease-out forwards;
}
.fx-welle.gold { border-width: 3px; box-shadow: 0 0 18px rgba(255, 212, 71, .45); }
@keyframes welle {
  from { opacity: .95; transform: translate(-50%, -50%) scale(1); }
  to   { opacity: 0;  transform: translate(-50%, -50%) scale(1.35); }
}

/* -------- Funken aus dem Glutbalken -------- */
.fx-funke {
  position: fixed; width: 4px; height: 4px; border-radius: 50%;
  background: #ffb14a; box-shadow: 0 0 8px 2px rgba(255, 138, 60, .8);
  animation: funke 1s ease-out forwards;
}
@keyframes funke {
  from { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  to   { opacity: 0; transform: translate(-50%, -50%) translateY(-46px) scale(.3); }
}

/* -------- Muenzregen und Konfetti -------- */
.fx-muenze {
  position: fixed; top: -40px; line-height: 1;
  animation: muenzefaellt 2.2s cubic-bezier(.35, .1, .8, 1) forwards;
}
@keyframes muenzefaellt {
  from { transform: translateY(0) rotate(0deg); opacity: 1; }
  85%  { opacity: 1; }
  to   { transform: translateY(102vh) rotate(540deg); opacity: 0; }
}
.fx-konfetti {
  position: fixed; top: -20px; border-radius: 2px;
  animation: konfettifaellt 3s linear forwards;
}
@keyframes konfettifaellt {
  from { transform: translateY(0) rotate(0deg); opacity: 1; }
  80%  { opacity: 1; }
  to   { transform: translateY(105vh) rotate(900deg); opacity: 0; }
}

/* -------- Zittern -------- */
.wackel { animation: wackeln .5s ease; }
@keyframes wackeln {
  0%, 100% { transform: none; }
  15% { transform: translateX(-8px); }
  32% { transform: translateX(8px); }
  50% { transform: translateX(-5px); }
  68% { transform: translateX(5px); }
  85% { transform: translateX(-2px); }
}
.wackel-klein { animation: wackelnklein .28s ease; }
@keyframes wackelnklein {
  0%, 100% { transform: none; }
  30% { transform: translateX(-4px); }
  70% { transform: translateX(4px); }
}

/* -------- Die letzten fuenf Sekunden --------
   Nur der Rand glimmt rot. In der Mitte wird gespielt, und eine Warnung, die
   das Spielfeld einfaerbt, hilft niemandem beim Suchen der letzten Kachel. */
body.eilig::after {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 40;
  box-shadow: inset 0 0 70px rgba(255, 77, 94, .38);
  animation: eilig .75s ease-in-out infinite alternate;
}
@keyframes eilig { from { opacity: .35; } to { opacity: 1; } }

/* -------- Glut, wenn sie heiss ist --------
   Ueber den Balken laufen Streifen, solange der Multiplikator ueber x1,25
   steht. Das ist die Ruecklaufsperre eines Automaten: man sieht, dass es
   gerade laeuft, ohne eine Zahl zu lesen. */
.glutbar-fill.hot {
  background-image:
    repeating-linear-gradient(115deg, rgba(255,255,255,.22) 0 8px, rgba(255,255,255,0) 8px 18px),
    linear-gradient(90deg, #ff8a3c, var(--red));
  background-size: 36px 100%, 100% 100%;
  animation: glutlauf .55s linear infinite;
}
@keyframes glutlauf { to { background-position: 36px 0, 0 0; } }

/* -------- Das Logo auf der Startseite --------
   Ein Licht laeuft alle paar Sekunden ueber die Schrift. Der Verlauf steht in
   der gemeinsamen Lobby-Basis; hier wird er nur breiter gemacht und bewegt. */
#screen-start .logo {
  background-size: 220% 100%;
  animation: logoschimmer 5s ease-in-out infinite;
}
@keyframes logoschimmer {
  0%, 65%, 100% { background-position: 100% 0; }
  85% { background-position: 0 0; }
}

/* -------- Ruhiger, wenn das System darum bittet -------- */
@media (prefers-reduced-motion: reduce) {
  /* Was blinkt, schleift oder pulst, hoert auf. Was etwas *sagt* - der
     Jubel oben, die fliegende Zahl - bleibt: sonst verschwaende die
     Einstellung dem Spiel seine Rueckmeldung. */
  .reel.gewinn-gross, .cat.available.gross::after, .cat.available.neu,
  .glutbar-fill.hot, #screen-start .logo, body.eilig::after,
  .timerbar-fill.low, .reel.halt-an, .reels.stups, .reels.heiss::before,
  .btn.draw.primary::after {
    animation-duration: .01ms; animation-iteration-count: 1;
  }
  .wackel, .wackel-klein { animation: none; }
}
