/* Quiz – mobil zuerst. */

:root {
    color-scheme: light dark;
    --bg: #f4f5f9;
    --card: #ffffff;
    --fg: #16181d;
    --muted: #666e7a;
    --line: #e2e5ea;
    --brand: #4f46e5;
    --brand-fg: #ffffff;
    --ok: #12874a;
    --ok-bg: #e4f5eb;
    --bad: #c62f26;
    --bad-bg: #fce9e8;
    --warn: #8a5a00;
    --radius: 14px;
    --safe-b: env(safe-area-inset-bottom, 0px);
}

/* Dunkel, wenn das System es will – aber nicht, wenn hell erzwungen ist. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --bg: #101319;
        --card: #191d25;
        --fg: #e9ecf1;
        --muted: #98a1b0;
        --line: #2a303a;
        --brand: #7c73f0;
        --ok: #4ade80;
        --ok-bg: #14311f;
        --bad: #f87171;
        --bad-bg: #3a1a19;
        --warn: #f0c168;
    }
}

/* Dunkel, weil in den Einstellungen so gewählt – auch auf einem hellen Gerät.
   Die Werte stehen doppelt: eine Medienabfrage lässt sich nicht von außen
   erzwingen, und ohne Bauschritt gibt es keine Möglichkeit, den Block
   wiederzuverwenden. Änderungen also immer an beiden Stellen. */
:root[data-theme="dark"] {
    color-scheme: dark;
    --bg: #101319;
    --card: #191d25;
    --fg: #e9ecf1;
    --muted: #98a1b0;
    --line: #2a303a;
    --brand: #7c73f0;
    --ok: #4ade80;
    --ok-bg: #14311f;
    --bad: #f87171;
    --bad-bg: #3a1a19;
    --warn: #f0c168;
}

:root[data-theme="light"] { color-scheme: light; }

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* Muss vor allen display-Regeln stehen: .boot/.topbar/.tabbar setzen display
   per Klasse und würden das hidden-Attribut sonst überstimmen – das
   Lade-Rädchen bliebe als fixierte Ebene über der fertigen App liegen. */
[hidden] { display: none !important; }

html, body { margin: 0; padding: 0; }

body {
    background: var(--bg);
    color: var(--fg);
    font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    padding-bottom: calc(64px + var(--safe-b));
    overscroll-behavior-y: contain;
    /* Ein einzelnes langes Wort darf die Seite nicht breiter machen. Bei
       200 Prozent Systemschrift schob "Kategoriemeister" die Statistik auf
       399 statt 375 Pixel - und damit die Fussleiste zur Haelfte hinaus.
       break-word bricht nur, wenn das Wort allein nicht in die Zeile passt. */
    overflow-wrap: break-word;
}

.boot { position: fixed; inset: 0; display: grid; place-items: center; background: var(--bg); z-index: 50; }
.spinner {
    width: 34px; height: 34px; border-radius: 50%;
    border: 3px solid var(--line); border-top-color: var(--brand);
    animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- Kopfzeile ---------- */

.topbar {
    position: sticky; top: 0; z-index: 20;
    display: flex; align-items: center; gap: .5rem;
    padding: max(env(safe-area-inset-top, 0px), .5rem) .75rem .5rem;
    background: var(--card);
    border-bottom: 1px solid var(--line);
}
/* min-width: 0 und Ellipse: ohne das schiebt ein langer Titel die
   Kopfleiste breiter als den Bildschirm - bei 200 Prozent Systemschrift
   waren es 408 statt 375 Pixel, und die Fussleiste rutschte mit hinaus.
   Ein Flex-Kind schrumpft von sich aus nicht unter seinen Inhalt. */
.topbar h1 {
    flex: 1; min-width: 0; margin: 0; font-size: 1.05rem; font-weight: 650;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 44 x 44 ist die kleinste Flaeche, die sich mit dem Daumen zuverlaessig
   treffen laesst (Apple HIG, WCAG 2.5.5). Der Pfeil war 25 x 32. */
.icon-btn {
    border: 0; background: transparent; color: var(--fg);
    font-size: 1.4rem; line-height: 1; cursor: pointer; border-radius: 10px;
    min-width: 44px; min-height: 44px;
    display: inline-grid; place-items: center; padding: 0 .3rem;
}
.icon-btn:active { background: var(--line); }

.view { padding: 1rem .9rem 2rem; max-width: 44rem; margin: 0 auto; }

/* ---------- Bausteine ---------- */

.card {
    background: var(--card); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 1rem; margin-bottom: .8rem;
}
.card.tight { padding: .7rem .9rem; }
h2 { font-size: 1rem; margin: 1.4rem 0 .6rem; }
h2:first-child { margin-top: 0; }
.muted { color: var(--muted); }
.small { font-size: .85rem; }
.up   { color: var(--ok); font-weight: 600; }
.down { color: var(--bad); font-weight: 600; }
.center { text-align: center; }
/* Umbrechen statt hinausschieben: eine Reihe mit drei Schaltflaechen (etwa
   in der Cron-Karte) war auf einem 360 Pixel breiten Handy 546 Pixel breit
   und riss die ganze Seite mit. Gebrochen wird erst, wenn es anders nicht
   geht - Zeilen mit .grow schrumpfen vorher. */
.row { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; }
.row.between { justify-content: space-between; }
.grow { flex: 1; min-width: 0; }
.stack { display: grid; gap: .6rem; }
.ellip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

button, .btn {
    font: inherit; font-weight: 600;
    padding: .8rem 1rem; border-radius: 11px; border: 1px solid transparent;
    background: var(--brand); color: var(--brand-fg);
    cursor: pointer; text-decoration: none; display: inline-block; text-align: center;
}
button:disabled { opacity: .5; cursor: default; }
.btn-2 { background: transparent; color: var(--brand); border-color: var(--line); }
.btn-danger { background: var(--bad); }
.btn-block { display: block; width: 100%; }
.btn-sm {
    padding: .45rem .7rem; font-size: .85rem; border-radius: 9px;
    min-height: 44px; min-width: 44px;   /* war 36,8 x 36 - zu wenig zum Treffen */
}

input, select, textarea {
    font: inherit; width: 100%;
    padding: .7rem .8rem; border: 1px solid var(--line); border-radius: 11px;
    background: var(--bg); color: var(--fg);
}
label { display: block; font-size: .85rem; color: var(--muted); margin-bottom: .25rem; }

.msg { padding: .7rem .9rem; border-radius: 11px; margin-bottom: .8rem; font-size: .92rem; }
.msg.bad { background: var(--bad-bg); color: var(--bad); }
.msg.ok  { background: var(--ok-bg); color: var(--ok); }
.msg.info { background: var(--line); color: var(--fg); }

.badge {
    display: inline-block; font-size: .72rem; font-weight: 700;
    padding: .15rem .5rem; border-radius: 999px; background: var(--line); color: var(--muted);
}
.badge.turn { background: var(--brand); color: var(--brand-fg); }
.badge.win  { background: var(--ok-bg); color: var(--ok); }
.badge.loss { background: var(--bad-bg); color: var(--bad); }

/* ---------- Tabs ---------- */

.tabbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
    display: grid; grid-template-columns: repeat(5, 1fr);
    background: var(--card); border-top: 1px solid var(--line);
    padding-bottom: var(--safe-b);
}
.tabbar a {
    display: grid; gap: 2px; justify-items: center; align-content: center;
    padding: .45rem .15rem; font-size: .72rem; text-decoration: none; color: var(--muted);
    min-height: 52px; min-width: 0;
}
/* Auf sehr schmalen Geraeten lieber kleiner als abgeschnitten. */
.tabbar a > :last-child { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tabbar a span { font-size: 1.25rem; line-height: 1.1; }
.tabbar a.active { color: var(--brand); }

/* ---------- Partieliste ---------- */

.game { display: flex; align-items: center; gap: .8rem; }
.avatar {
    width: 42px; height: 42px; border-radius: 50%; flex: none;
    display: grid; place-items: center; font-weight: 700; color: #fff;
    background: var(--brand); font-size: 1rem;
}
.score { font-variant-numeric: tabular-nums; font-weight: 700; }

/* ---------- Spielbrett ---------- */

/* Je Runde eine Zeile: links die drei Felder des Spielers, rechts die des
   Gegners, dazwischen Rundenzahl und Kategorie. Die Seitenspalten sind gleich
   breit, damit die Felder untereinander fluchten. */
.board { display: grid; gap: .3rem; margin: .4rem 0 1rem; }
.brow {
    display: grid; grid-template-columns: 1fr minmax(6.5rem, 1.35fr) 1fr;
    align-items: center; gap: .5rem;
    background: var(--card); border: 1px solid var(--line);
    border-radius: var(--radius); padding: .5rem .55rem;
}
.brow.open-able { cursor: pointer; }
.brow.now { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand) inset; }
/* Noch nicht begonnene Runden nehmen sich zurück. */
.brow.leer { opacity: .6; padding: .4rem .55rem; }
.brow.leer .bcell { height: 20px; }
.brow.open-able:hover { border-color: var(--brand); }
.brow.open { border-color: var(--brand); border-bottom-left-radius: 0; border-bottom-right-radius: 0; }

.bside { display: grid; grid-template-columns: repeat(3, 1fr); gap: .22rem; }
.bcell { display: block; height: 26px; border-radius: 6px; background: var(--line); }
.bcell.hit  { background: var(--ok); }
.bcell.miss { background: var(--bad); }
/* Gespielt, aber noch nicht aufgedeckt. */
.bcell.veil {
    background: repeating-linear-gradient(45deg,
        var(--muted), var(--muted) 3px, var(--line) 3px, var(--line) 7px);
    opacity: .55;
}

.blabel { text-align: center; display: grid; gap: 1px; min-width: 0; }
.blabel b { font-size: .8rem; letter-spacing: .02em; }
.blabel span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.blabel .now { color: var(--brand); font-weight: 600; }

/* Auflösung, die unter der Zeile aufklappt. */
.bdetail:not([hidden]) {
    background: var(--card); border: 1px solid var(--brand); border-top: 0;
    border-radius: 0 0 var(--radius) var(--radius);
    padding: .1rem .8rem .6rem; margin-top: -.3rem;
}

/* ---------- Frage ---------- */

.qwrap { display: grid; gap: .8rem; }
/* Im Hochformat sind die beiden Haelften unsichtbar: display: contents laesst
   ihre Kinder unmittelbar im Raster der Frage liegen, alles stapelt wie
   bisher. Erst im Querformat werden sie zu echten Spalten (siehe unten). */
.qleft, .qright { display: contents; }

/* Die Uhr bleibt stehen. Auf dem iPhone SE muss man bei einer Bildfrage
   381 Pixel scrollen, um alle Antworten zu sehen - der Zeitbalken stand
   danach bei y = -271, also ausserhalb des Bildschirms. Man waehlte die
   Antwort, ohne zu sehen, wie viel Zeit noch bleibt. */
.qmeta, .timer {
    position: sticky; z-index: 6;
    background: var(--bg);
    padding-top: .25rem;
}
.qmeta { top: 52px; }
.timer { top: calc(52px + 1.7rem); }
.qmeta { display: flex; align-items: center; gap: .5rem; font-size: .85rem; color: var(--muted); }
.qtext { font-size: 1.15rem; font-weight: 600; line-height: 1.35; }
/* 42vh schob auf dem Handy die vierte Antwort unter die Falz. */
.qimg { width: 100%; border-radius: var(--radius); background: var(--line); display: block; max-height: 32vh; object-fit: contain; }
/* Auf kurzen Bildschirmen (iPhone SE) lagen drei von vier Antworten unter
   der Falz. Lieber ein kleineres Bild als blindes Scrollen, waehrend die
   Uhr laeuft. */
@media (max-height: 700px) { .qimg { max-height: 22vh; } }

.qcredit { font-size: .7rem; color: var(--muted); }

.timer { height: 6px; background: var(--line); border-radius: 99px; overflow: hidden; }
.timer > i { display: block; height: 100%; background: var(--brand); transition: width .1s linear; }
.timer.low > i { background: var(--bad); }
/* Uhr steht, solange die vorherige Lösung offen ist */
.timer.paused > i { background: var(--muted); opacity: .5; }

.answers { display: grid; gap: .5rem; }
.answer {
    text-align: left; background: var(--card); color: var(--fg);
    border: 1px solid var(--line); padding: .85rem .9rem; font-weight: 500;
    display: flex; align-items: center; gap: .6rem;
}
.answer .key {
    width: 26px; height: 26px; border-radius: 50%; flex: none;
    display: grid; place-items: center; font-size: .78rem; font-weight: 700;
    background: var(--line); color: var(--muted);
}
.answer.correct { background: var(--ok-bg); border-color: var(--ok); color: var(--ok); }
.answer.correct .key { background: var(--ok); color: #fff; }
.answer.wrong { background: var(--bad-bg); border-color: var(--bad); color: var(--bad); }
.answer.wrong .key { background: var(--bad); color: #fff; }
.answer.dimmed { opacity: .35; }

/* Wahl des Gegners: seine Anfangsbuchstaben auf der Antwort, die er
   geklickt hat. Erscheint erst, wenn beide diese Frage gespielt haben. */
.oppmark {
    margin-left: auto; flex: none;
    width: 24px; height: 24px; border-radius: 50%;
    display: grid; place-items: center;
    font-size: .68rem; font-weight: 700;
    background: var(--line); color: var(--muted);
    border: 2px solid var(--card);
    box-shadow: 0 0 0 1px var(--line);
}
.oppmark.hit  { background: var(--ok-bg);  color: var(--ok);  box-shadow: 0 0 0 1px var(--ok); }
.oppmark.miss { background: var(--bad-bg); color: var(--bad); box-shadow: 0 0 0 1px var(--bad); }

/* Publikumsjoker: Balken hinter der Antwort, Zahl rechts daneben.
   Der Balken ist ein eigenes Element und vom "position: relative" für die
   übrigen Kinder ausgenommen - lag er als ::before an der Zahl, wurde er an
   dieser statt an der Schaltfläche ausgerichtet und war ein paar Pixel breit. */
.answer { position: relative; overflow: hidden; }
.answer > *:not(.votebar) { position: relative; z-index: 1; }
.votebar {
    position: absolute; left: 0; top: 0; bottom: 0; z-index: 0;
    width: var(--pct, 0%); background: var(--brand); opacity: .16;
}
.vote { margin-left: auto; font-size: .75rem; font-weight: 700; color: var(--muted); flex: none; }

/* Querformat: gemessen war dort keine einzige Antwort ohne Scrollen zu
   sehen - nur Bild und Frage, der Spieler haelt die Seite fuer kaputt.
   Zwei Spalten: links Bild und Frage, rechts die vier Antworten.

   Der Block steht *hinter* den .answer-Regeln, nicht davor: gleiche
   Spezifitaet, und die spaetere Regel gewinnt. Weiter oben stehend war das
   Verkleinern der Antworten wirkungslos - gemessen 55 statt 37 Pixel je
   Antwort, und die vierte lag damit hinter der Fussleiste. */
@media (orientation: landscape) and (max-height: 520px) {
    .qwrap { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); column-gap: .9rem; gap: .5rem; }
    .qmeta, .timer { grid-column: 1 / -1; }
    .qleft, .qright { display: grid; gap: .45rem; align-content: start; }
    .qimg { max-height: 30vh; }
    .qtext { font-size: 1rem; }
    /* Vier Antworten muessen zwischen Kopf- und Fussleiste passen: beim
       iPhone SE quer sind das 375 - 122 - 57 = 196 Pixel, also hoechstens
       44 je Antwort samt Abstand - und 44 ist zugleich die kleinste Flaeche,
       die sich zuverlaessig treffen laesst. */
    .answers { gap: .35rem; }
    .answer { padding: .35rem .6rem; font-size: .9rem; min-height: 44px; }
    .answer .key { width: 22px; height: 22px; font-size: .72rem; }
    .qmeta { font-size: .78rem; }
    .jokers .btn-sm { min-height: 38px; padding: .3rem .6rem; }
}


.jokers { display: flex; gap: .5rem; flex-wrap: wrap; }

/* Ausgabe des Cron und des Fehlerprotokolls */
.log {
    background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
    padding: .6rem .7rem; margin: .7rem 0 0; font-size: .78rem; line-height: 1.5;
    white-space: pre-wrap; word-break: break-word; overflow-x: auto;
}

/* ---------- Auflösung ---------- */

.solution { border-left: 3px solid var(--line); padding-left: .8rem; margin: .6rem 0; }
.solution.hit { border-left-color: var(--ok); }
.solution.miss { border-left-color: var(--bad); }
/* Hinweistext, der auffallen soll, ohne eine ganze Meldung zu sein. */
.warn { color: var(--warn); }

.pill { font-size: .78rem; padding: .1rem .45rem; border-radius: 6px; background: var(--line); }
.pill.hit { background: var(--ok-bg); color: var(--ok); }
.pill.miss { background: var(--bad-bg); color: var(--bad); }

/* ---------- Kategorien ---------- */

.cats { display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: .5rem; }
.cat {
    background: var(--card); border: 1px solid var(--line); color: var(--fg);
    padding: .8rem .6rem; display: grid; gap: .2rem; justify-items: center; font-size: .85rem;
}
.cat b { font-size: 1.5rem; font-weight: 400; }

/* ---------- Statistik ---------- */

.bar { height: 8px; background: var(--line); border-radius: 99px; position: relative; }
/* Eigener Radius statt overflow: hidden am Balken - sonst wird der Strich
   für den Schnitt mit abgeschnitten und liegt flach im Balken drin. */
.bar > i { display: block; height: 100%; max-width: 100%; background: var(--brand); border-radius: 99px; }
/* Der Strich muss über dem blauen Balken genauso zu sehen sein wie über dem
   grauen Rest. Grau auf Blau verschwand. Deshalb: Farbe des Textes, heller
   Saum in der Farbe der Karte, und oben wie unten übersteht er. */
.bar > s {
    position: absolute; top: -4px; bottom: -4px; width: 2px;
    margin-left: -1px;
    background: var(--fg);
    box-shadow: 0 0 0 1.5px var(--card);
    border-radius: 2px;
}

/* Tabellen scrollen in ihrer Karte, nicht die ganze Seite. Ohne das riss die
   Liste der stillgelegten Fragen den Adminbereich auf 884 Pixel Breite - bei
   einem 360 Pixel breiten Handy lagen damit drei von fünf Reitern der unteren
   Leiste außerhalb des Bildschirms. display:block macht die Tabelle zu einem
   Kasten, der scrollen kann; die Zeilen darin bleiben eine Tabelle. */
table.list {
    display: block; overflow-x: auto; -webkit-overflow-scrolling: touch;
    max-width: 100%; border-collapse: collapse; font-size: .9rem;
}
table.list td, table.list th { padding: .5rem .4rem; border-bottom: 1px solid var(--line); text-align: left; }
table.list th { color: var(--muted); font-weight: 600; font-size: .78rem; }
table.list td.num { text-align: right; font-variant-numeric: tabular-nums; }
/* Auswahlfelder in Tabellen: schmal, aber hoch genug zum Antippen. */
.sel-sm { padding: .5rem .4rem; min-height: 44px; font-size: .85rem; }

/* Kaestchen mit Beschriftung: das Kaestchen selbst war 13 x 13 Pixel. Die
   ganze Zeile ist zwar klickbar, aber wer das Kaestchen anpeilt, soll es
   auch treffen. */
label.row { min-height: 44px; }
/* !important, weil input eine Breite von 100 % erbt (Formularregel oben) und
   die Kaestchen sie vorher mit style="width:auto" einzeln ueberschrieben. */
label.row input[type="checkbox"] { width: 22px !important; height: 22px; flex: none; }

/* Karten und ihre Kinder dürfen nicht breiter werden als der Bildschirm.
   Ohne min-width:0 wächst ein Flex- oder Grid-Kind an seinem Inhalt und
   schiebt den Rest hinaus. Knöpfe sind ausgenommen: die Regel hat ihnen die
   44 Pixel wieder weggenommen, das ✕ in der Partienliste war damit 36 breit
   und wieder zu schmal zum Treffen. Ein Knopf ist ohnehin kurz, er schiebt
   nichts hinaus. */
.card, .card > * { min-width: 0; }
.card > button, .card button.btn-sm, .card .icon-btn { min-width: 44px; }

/* ---------- Chat ---------- */

.chat { display: grid; gap: .4rem; max-height: 42vh; overflow-y: auto; }
/* anywhere statt break-word: in der Blase darf auch mitten im Wort
   umgebrochen werden, sonst sprengt eine hingeschriebene URL die Breite. */
.bubble { padding: .45rem .7rem; border-radius: 12px; background: var(--line); max-width: 80%; font-size: .9rem;
          overflow-wrap: anywhere; }
.bubble.mine { background: var(--brand); color: var(--brand-fg); margin-left: auto; }

/* ---------- Toast ---------- */

.toast {
    position: fixed; left: 50%; transform: translateX(-50%);
    bottom: calc(76px + var(--safe-b)); z-index: 40;
    background: #000c; color: #fff; padding: .6rem 1rem; border-radius: 11px;
    font-size: .88rem; max-width: 90vw; text-align: center;
}

/* Nachfrage nach Mitteilungen, sitzt über der Tableiste */
/* Der Streifen liegt ueber dem Inhalt. Damit der letzte Listeneintrag nicht
   dauerhaft darunter verschwindet, bekommt die Seite zusaetzlichen Fussraum,
   solange er sichtbar ist (siehe body:has). */
.pushask {
    position: fixed; left: 0; right: 0; z-index: 45;
    bottom: calc(64px + var(--safe-b));
    padding: 0 .8rem;
}
body:has(#pushask:not([hidden])) .view { padding-bottom: 12rem; }
.pushask-in {
    display: grid; gap: .7rem;
    max-width: 34rem; margin: 0 auto;
    background: var(--card); border: 1px solid var(--line);
    border-radius: 14px; padding: .9rem;
    box-shadow: 0 8px 24px #0003;
}
.pushask-in .row { justify-content: flex-end; gap: .5rem; }
.pushask button { padding: .5rem .9rem; font-size: .85rem; }

@media (min-width: 40rem) {
    .tabbar { grid-template-columns: repeat(5, minmax(0, 8rem)); justify-content: center; }
}
