/* Challenge Accepted -- Grundlayout und Spielbrett.

   Alle Groessen haengen an CSS-Variablen. Die spaetere Handy-Fassung aendert
   deshalb nur diese Werte und braucht kein zweites Markup. */

:root {
    color-scheme: dark;

    --ton-grund: #10241c;
    --ton-brett: #16412f;
    --ton-brett-hell: #1d5540;
    --ton-rahmen: #0b1a14;
    --ton-schrift: #eef5f1;
    --ton-schrift-leise: #9db5aa;
    --ton-akzent: #f2b544;
    --ton-akzent-schwach: rgba(242, 181, 68, 0.22);
    --ton-gueltig: #57d98a;
    --ton-rot: #c62828;
    --ton-schwarz: #16212b;

    /* Ein zweites Rot, und zwar ein helles: --ton-rot gehoert den Kartenfarben
       und sitzt auf weissem Grund. Auf dem dunklen Brett ist es kaum zu lesen
       -- gegen den Brettton kommt es auf ein Kontrastverhaeltnis von 1,6. Dies
       hier ist der Ton, in dem schon die Minenwarnung leuchtet. */
    --ton-daneben: #ff7b7b;

    /* Was innerhalb der Buehne oberhalb des Bretts noch Platz braucht --
       Hinweiszeilen, Gradwahl im Uebungsmodus. Die Kopfzeile, die Leiste und
       die Fusszeile stehen seit der Umstellung auf Schiene und Seitentafel
       nicht mehr darueber, deshalb ist der Wert klein.

       Vorher standen hier 344 Pixel, gemessen und trotzdem geraten: er musste
       fuer jede Seite passen, und jede hatte eine andere Zahl von Zeilen ueber
       dem Brett. Jetzt rechnen die Bretter gegen 100cqh -- die Hoehe der
       Buehne -- und dieser Rest deckt nur noch, was wirklich in der Buehne
       darueber liegt. */
    --brett-umgebung: 2.5rem;

    /* Der Versatz gestapelter Karten wird je Spalte aus ihrer Laenge berechnet.
       Die Grundmasse dazu stehen in .brett -- sie haengen an der Spaltenzahl
       der jeweiligen Spielart. */
    --versatz-min: 15px;

    /* Der Versatz, mit dem die Breitenformel je gestapelter Karte rechnet.
       Fest statt anteilig, weil die Kartenbreite sonst von sich selbst
       abhinge: Versatz haengt an der Kartenhoehe, die Hoehe an der Breite.
       26px sind das anteilige Mass (0.27 der Kartenhoehe) bei rund 63
       Bildpunkten Kartenbreite -- der Groessenordnung der Telefonbretter, wo
       diese Formel ueberhaupt greift. */
    --versatz-lesbar: 26px;

    --spalt: clamp(4px, 0.8vw, 12px);
}

* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}

body {
    background: radial-gradient(ellipse at 50% 0%, var(--ton-brett) 0%, var(--ton-grund) 70%);
    color: var(--ton-schrift);
    font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
    overscroll-behavior: none;

    /* Kein Markieren. Das hier ist ein Spiel und kein Textdokument: wer eine
       Karte ein Stueck weit zieht und wieder loslaesst, hatte bis eben eine
       blau hinterlegte Ueberschrift. Einzeln stand das schon auf Karten,
       Steinen und Feldern -- hier gilt es fuer alles. */
    user-select: none;
    -webkit-user-select: none;
}

/* Wo wirklich getippt wird, bleibt das Markieren. Ohne diese Ausnahme liesse
   sich in einem Feld nicht einmal ein Tippfehler ueberschreiben. */
input,
textarea,
[contenteditable="true"] {
    user-select: text;
    -webkit-user-select: text;
}

/* Der Fokusrahmen nur fuer die Tastatur.

   Der Rahmen um "Challenge Accepted" kam davon, dass ein Klick den Fokus
   setzt und der Browser ihn dann anzeigt -- auch auf einer Ueberschrift, mit
   der man nichts tun kann. Wer mit der Maus klickt, hat gesehen, wo er
   hingeklickt hat.

   Bewusst nicht "outline: none" fuer alles: wer sich mit Tab durch die Seite
   bewegt, ist darauf angewiesen zu sehen, wo er steht. :focus-visible trennt
   genau diese beiden Faelle. */
:focus:not(:focus-visible) {
    outline: none;
}

/* Der Rahmen um die Ueberschrift kam von hier: Blazors FocusOnNavigate setzt
   nach jedem Seitenwechsel den Fokus auf das <h1> und haengt ihm dafuer ein
   tabindex="-1" an. Gedacht ist das fuer Vorleseprogramme -- sie landen so auf
   der Ueberschrift statt am Seitenanfang --, und deshalb bleibt es auch. Nur
   sichtbar muss es nicht sein: Chrome behandelt diesen gesetzten Fokus als
   "mit der Tastatur gekommen" und zeichnet den Rahmen, obwohl niemand
   getabbt hat.

   Mit tabindex="-1" ist das Element ohnehin nicht mit Tab erreichbar; den
   Rahmen zu verstecken kostet also keinen Tastaturnutzer etwas. */
[tabindex="-1"]:focus {
    outline: none;
}

h1, h2 {
    font-weight: 600;
    letter-spacing: -0.01em;
}

/* --- Ladeanzeige ------------------------------------------------------- */

.ladeanzeige {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
}

.ladeanzeige__titel {
    font-size: 1.6rem;
    font-weight: 600;
}

.ladeanzeige__text {
    color: var(--ton-schrift-leise);
}

/* --- Rahmen: Kopf und Fuss --------------------------------------------- */

/* --- Rahmen: Schiene, Seitentafel, Buehne ------------------------------- */

/* Feste Fensterhoehe statt mitwachsender Seite.
 *
 * Das ist die eigentliche Umstellung. Vorher war die Seite so hoch wie ihr
 * Inhalt, und jedes Brett musste schaetzen, wie viel oben und unten schon
 * verbraucht war -- daher die Konstante --brett-umgebung, die zwischen 336 und
 * 449 Pixeln schwankte, je nachdem welche Seite gerade eine Zeile mehr hatte.
 *
 * Jetzt hat die Buehne eine bekannte Hoehe, und die Bretter darin rechnen mit
 * Containereinheiten gegen genau diese Flaeche. Geschaetzt wird nichts mehr.
 */
/* Der Rahmen war einmal ein Dreispalter aus Schiene, Seitentafel und Buehne.
   Beides ist weg -- die Halle ist die Navigation, und waehrend einer Partie
   gibt es keine. Das Raster bringen jetzt die Modifikatoren mit, weiter unten
   bei "Halle und Partie". */
.rahmen {
    height: 100dvh;
    overflow: hidden;
}

.rahmen--tafel-auf {
    grid-template-columns: var(--schiene-breite) var(--tafel-breite) 1fr;
}

/* --- Schiene ------------------------------------------------------------ */

/* Alles, was waehrend einer Partie zur Hand sein muss, in einer Spalte: Marke,
   Menue, Werte, Knoepfe, Konto. Links kostet es keine Hoehe -- und Hoehe ist
   bei einem Kartenspiel immer das, was fehlt. */
/* Die Spalten ausdruecklich zuweisen, nicht der automatischen Platzierung
   ueberlassen. Auf schmalen Schirmen loest sich die Tafel als Ueberlagerung aus
   dem Raster; ohne diese Angabe rueckt die Buehne dann in die leere zweite
   Spalte nach und ist sechzehn Pixel breit. */
.schiene {
    grid-column: 1;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    padding: 0.6rem 0.45rem;
    background: rgba(0, 0, 0, 0.3);
    border-right: 1px solid rgba(255, 255, 255, 0.07);
    overflow-y: auto;
    overflow-x: hidden;
}

.schiene__marke,
.schiene__knopf {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.2rem;
    padding: 0.45rem 0.2rem;
    border: 0;
    border-radius: 12px;
    background: transparent;
    color: var(--ton-schrift-leise);
    font-family: inherit;
    font-size: 0.62rem;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}

.schiene__marke:hover,
.schiene__knopf:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--ton-schrift);
}

.schiene__knopf--aktiv {
    background: rgba(255, 255, 255, 0.1);
    color: var(--ton-schrift);
}

.schiene__zeichen {
    display: grid;
    place-items: center;
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 10px;
    background: var(--ton-akzent);
    color: #2a1c00;
    font-size: 0.85rem;
    font-weight: 800;
}

.schiene__symbol {
    display: grid;
    place-items: center;
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.07);
    font-size: 1rem;
    line-height: 1;
}

.schiene__wort {
    letter-spacing: 0.02em;
}

.schiene__werte,
.schiene__taten {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.schiene__werte {
    margin-top: 0.3rem;
}

.schiene__taten {
    margin-top: 0.5rem;
}

/* Konto und Klang ganz unten -- sie gehoeren zur Anwendung, nicht zur Partie. */
.schiene__fuss {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    padding-top: 0.6rem;
}

/* Die Anzeigen der Partie werden in der Schiene zu Kacheln: Wert gross,
   Bezeichnung klein darunter. Dieselbe Auszeichnung wie vorher in der Leiste --
   nur der Ort ist ein anderer. */
.schiene .anzeige {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.1rem;
    padding: 0.4rem 0.25rem;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.05);
}

.schiene .anzeige__wert {
    font-size: 0.95rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
    text-align: center;
    overflow-wrap: anywhere;
}

/* Ein negativer Wert ist keine verratene Minenposition -- er zaehlt nur die
   eigenen Flaggen. Deshalb darf er auffallen: er ist der einzige Hinweis
   darauf, dass eine Markierung auf einem freien Feld liegt und die Partie
   deswegen nicht zuklappt. */
.anzeige__wert--warnung {
    color: #ff7b7b;
}

.schiene .anzeige__name {
    font-size: 0.56rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ton-schrift-leise);
    text-align: center;

    /* „RUECKNAHMEN" ist laenger als die Schiene breit. Umbrechen statt
       abschneiden -- in der Senkrechten ist Platz, in der Waagerechten nicht. */
    line-height: 1.15;
    overflow-wrap: anywhere;
    hyphens: auto;
}

/* Knoepfe der Partie fuellen die Schiene aus. Eingabefelder -- die Dealnummer
   im Uebungsmodus -- ebenso. */
/* Deutsche Woerter sind laenger als die Schiene breit: „Rueckgaengig",
   „Bestenliste", „Neues Spiel". Sie duerfen deshalb umbrechen und notfalls
   trennen, statt am Rand abgeschnitten zu werden.

   Kuerzere Beschriftungen waeren die andere Loesung -- „Zurueck", „Liste" --,
   aber ein Knopf soll sagen, was er tut, und nicht, was gerade passt. */
.schiene .knopf,
.schiene .feld {
    width: 100%;
    padding: 0.45rem 0.25rem;
    font-size: 0.72rem;
    line-height: 1.2;
    text-align: center;
    white-space: normal;
    overflow-wrap: anywhere;
    hyphens: auto;
}

/* Die Pfeilchen eines Zahlenfeldes kosten fuenfzehn Pixel von siebzig -- in
   der Schiene ist das ein Fuenftel. Getippt wird die Dealnummer ohnehin,
   hochgeklickt hat sie noch nie jemand. */
.schiene .feld::-webkit-outer-spin-button,
.schiene .feld::-webkit-inner-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

/* Mit Praefix UND ohne: die kurze Schreibweise allein reicht in Chrome fuer
   ein Zahlenfeld noch nicht -- nachgemessen. */
.schiene .feld[type="number"] {
    -webkit-appearance: textfield;
    appearance: textfield;
}

/* --- Seitentafel -------------------------------------------------------- */

.tafel {
    grid-column: 2;
    display: flex;
    flex-direction: column;
    min-width: 0;
    background: rgba(0, 0, 0, 0.14);
    border-right: 1px solid rgba(255, 255, 255, 0.07);
    overflow: hidden;
}

.tafel__kopf {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.85rem 1rem 0.6rem;
}

.tafel__titel {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tafel__schliessen {
    appearance: none;
    margin-left: auto;
    border: 0;
    background: transparent;
    color: var(--ton-schrift-leise);
    font-size: 0.95rem;
    line-height: 1;
    padding: 0.3rem 0.4rem;
    border-radius: 7px;
    cursor: pointer;
}

.tafel__schliessen:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--ton-schrift);
}

.tafel__tag {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    margin: 0 1rem 0.8rem;
    padding: 0.45rem 0.6rem;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.04);
}

.tafel__versuch {
    font-size: 0.72rem;
    color: var(--ton-schrift-leise);
}

.tafel__inhalt {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 0 1rem 0.8rem;
}

.tafel__fuss {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.7rem 1rem 0.9rem;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
    font-size: 0.76rem;
}

.tafel__fuss a {
    color: var(--ton-schrift-leise);
}

.tafel__fuss a:hover {
    color: var(--ton-schrift);
}

.tafel__notiz {
    color: var(--ton-schrift-leise);
    font-size: 0.7rem;
}

/* In der Tafel steht die Spielauswahl untereinander statt nebeneinander --
   dafuer ist sie da. */
/* Untereinander statt nebeneinander: in der schmalen Tafel bleibt fuer eine
   Reihe kein Platz. Der Abstand ist grosszuegiger als in der waagerechten
   Fassung -- nebeneinander trennt schon die Luecke zwischen zwei Pillen, 
   untereinander liegen sie sonst wie ein Block aufeinander. */
.tafel .spielwahl {
    flex-direction: column;
    align-items: stretch;
    gap: 0.45rem;
    margin: 0 0 1.1rem;
}

.tafel .spielwahl__eintrag {
    text-align: left;
    border-radius: 10px;
    padding: 0.5rem 1rem;
}

/* --- Buehne ------------------------------------------------------------- */

.buehne {
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
}

/* Eine Zeile, mehr nicht. Vorher standen hier Ueberschrift, Spielreihe und
   Leiste uebereinander. */
.buehne__kopf {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    padding: 0.5rem clamp(0.6rem, 1.5vw, 1.2rem);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    white-space: nowrap;
}

.buehne__titel {
    font-size: 0.98rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
}

.buehne__beitext {
    font-size: 0.8rem;
    color: var(--ton-schrift-leise);
}

.buehne__notiz {
    margin-left: auto;
    font-size: 0.8rem;
    color: var(--ton-schrift-leise);
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Die Spielflaeche. Sie ist ein Groessen-Container: die Bretter darin rechnen
   ihre Karten-, Stein- und Feldgroessen gegen 100cqw und 100cqh aus, also
   gegen genau diese Flaeche -- und nicht mehr gegen das Fenster abzueglich
   einer geschaetzten Konstante. */
.buehne__flaeche {
    flex: 1;
    min-height: 0;
    overflow: auto;
    padding: clamp(0.5rem, 1.5vw, 1.1rem);
    container-type: size;
    container-name: buehne;
}

/* Auf schmalen Schirmen passen Schiene, Tafel und Buehne nicht nebeneinander.
   Die Tafel legt sich dann ueber die Buehne, statt sie zu verdraengen -- und
   sie ist dort standardmaessig zu, siehe MainLayout. */
@media (max-width: 1080px) {
    .rahmen,
    .rahmen--tafel-auf {
        --schiene-breite: 4.4rem;
        grid-template-columns: var(--schiene-breite) 0 1fr;
    }

    /* Als Spalte im Raster durfte die Tafel eine blosse Tuenche sein: sie lag
       auf dem Seitengrund, und die vierzehn Prozent Schwarz gaben ihr nur etwas
       mehr Tiefe als der Buehne daneben.

       Hier ist sie kein Nachbar mehr, sondern eine Schublade UEBER der Buehne
       -- und dieselbe Tuenche liess die Kacheln mitten durch die Spieleliste
       hindurchscheinen. Eine Schublade braucht einen eigenen, deckenden Grund. */
    .rahmen--tafel-auf .tafel {
        position: fixed;
        top: 0;
        bottom: 0;
        left: var(--schiene-breite);
        z-index: 700;
        width: min(var(--tafel-breite), calc(100vw - var(--schiene-breite)));
        background: var(--ton-grund);
        box-shadow: 0 0 40px rgba(0, 0, 0, 0.6);
    }

    /* Und dahinter die Verdunklung: sie sagt, was gerade gilt, und faengt den
       Tipp daneben ab. Ohne sie muesste man den Weg zurueck zum Menueknopf
       finden, um wieder an das Brett zu kommen. */
    .rahmen--tafel-auf .tafelschatten {
        position: fixed;
        inset: 0;
        z-index: 690;
        border: 0;
        padding: 0;
        background: rgba(3, 12, 9, 0.55);
        backdrop-filter: blur(2px);
        cursor: pointer;
    }

    .schiene__wort {
        display: none;
    }
}

/* Auf breiten Schirmen steht die Tafel neben der Buehne und nimmt ihr nichts
   weg -- dort gibt es nichts zu verdunkeln und nichts abzufangen. */
.tafelschatten {
    display: none;
}

@media (max-width: 1080px) {
    .rahmen--tafel-auf .tafelschatten {
        display: block;
    }
}

.tagchip {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    padding: 0.35rem 0.7rem;
    border-radius: 999px;
    background: rgba(242, 181, 68, 0.13);
    border: 1px solid rgba(242, 181, 68, 0.3);
    white-space: nowrap;
}

.tagchip__name {
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--ton-akzent);
}

.tagchip__wert {
    font-size: 0.88rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* --- Benutzerchip ------------------------------------------------------ */

.benutzer {
    position: relative;
}

.benutzer__knopf,
.benutzer--offen {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.3rem 0.6rem 0.3rem 0.35rem;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    background: rgba(255, 255, 255, 0.05);
    color: var(--ton-schrift);
    font-family: inherit;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.12s ease;
}

.benutzer__knopf:hover,
.benutzer--offen:hover {
    background: rgba(255, 255, 255, 0.1);
}

.benutzer__zeichen {
    display: grid;
    place-items: center;
    width: 1.85rem;
    height: 1.85rem;
    border-radius: 50%;
    background: var(--ton-gueltig);
    color: #06281a;
    font-weight: 800;
    font-size: 0.85rem;
}

.benutzer__zeichen--leer {
    background: rgba(255, 255, 255, 0.16);
    color: var(--ton-schrift-leise);
}

.benutzer__namen {
    display: flex;
    flex-direction: column;
    line-height: 1.15;
    text-align: left;
}

.benutzer__name {
    font-size: 0.86rem;
    font-weight: 600;
    white-space: nowrap;
}

.benutzer__lage {
    font-size: 0.64rem;
    color: var(--ton-schrift-leise);
    white-space: nowrap;
}

.benutzer__pfeil {
    color: var(--ton-schrift-leise);
    font-size: 0.7rem;
}

/* Die Klappe haengt nicht mehr im Layout, sondern in der obersten Ebene des
   Browsers -- siehe klappe.js und das "popover" im Benutzerchip.

   WARUM. Sie sass absolut gesetzt in der Schiene, und die traegt
   "overflow-x: hidden"; der Rahmen darum "overflow: hidden". Gemessen kamen
   von dreihundertzwanzig Bildpunkten Breite genau achtundachtzig an, der Rest
   war abgeschnitten. Der erste Anlauf war ein z-index von achthundert -- der
   konnte nicht helfen: z-index entscheidet, was vor was liegt, nicht, was
   ueberhaupt gezeichnet wird.

   Ort und Groesse setzt klappe.js, weil ein Popover nicht mehr weiss, wo sein
   Knopf sitzt. Bis das geschehen ist, bleibt sie unsichtbar -- sonst blitzte
   sie fuer ein Bild an der falschen Stelle auf. */
.benutzer__klappe {
    position: fixed;
    inset: auto;
    margin: 0;
    z-index: 800;
    width: min(20rem, calc(100vw - 2rem));
    padding: 0.9rem 1rem;
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    background: #16302a;
    color: var(--ton-schrift);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
}

.benutzer__klappe--unfertig {
    opacity: 0;
}

.benutzer__hinweis {
    margin: 0 0 0.6rem;
    font-size: 0.84rem;
    color: var(--ton-schrift-leise);
}

/* Der Benutzerchip in der Schiene: nur Kreis und Name, gestapelt. Fuer den
   Zusatz "angemeldet" ist dort kein Platz, und er sagt neben einem Namen auch
   wenig. */
.schiene .benutzer__knopf,
.schiene .benutzer--offen {
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.4rem 0.2rem;
    border: 0;
    background: transparent;
    width: 100%;
}

.schiene .benutzer__lage,
.schiene .benutzer__pfeil {
    display: none;
}

.schiene .benutzer__name {
    font-size: 0.62rem;
    font-weight: 600;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

.schiene .benutzer__zeichen {
    width: 2.2rem;
    height: 2.2rem;
}

/* Die Klappe oeffnet zur Seite und nach oben -- unter der Schiene ist nichts
   mehr, und rechts ist die ganze Buehne. */
.schiene .benutzer__klappe {
    right: auto;
    left: calc(100% + 0.4rem);
    top: auto;
    bottom: 0;
}

/* --- Bedienleiste ------------------------------------------------------ */

.leiste {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.1rem;
    margin-bottom: clamp(0.6rem, 1.6vw, 1.2rem);
}

.anzeige {
    display: flex;
    flex-direction: column;
    line-height: 1.15;
}

.anzeige__wert {
    font-size: 1.35rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.anzeige__name {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ton-schrift-leise);
}

.knopf {
    appearance: none;
    border: 1px solid rgba(255, 255, 255, 0.16);
    background: rgba(255, 255, 255, 0.06);
    color: var(--ton-schrift);
    border-radius: 7px;
    padding: 0.45rem 0.9rem;
    font-size: 0.9rem;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease;
}

.knopf:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.12);
}

.knopf:disabled {
    opacity: 0.38;
    cursor: default;
}

.knopf--wichtig {
    background: var(--ton-akzent);
    border-color: var(--ton-akzent);
    color: #2a1c00;
    font-weight: 600;
}

.knopf--wichtig:hover:not(:disabled) {
    background: #ffc65c;
}

/* Fuer einen Knopf, der etwas endgueltig wegwirft.

   Nur der Rand und die Schrift sind rot, nicht die Flaeche: ein voll
   ausgemalter Knopf zieht das Auge an wie eine Empfehlung, und das ist das
   Loeschen nicht. Erst unter dem Zeiger fuellt er sich -- da hat man ihn schon
   gesucht. Er erscheint ohnehin nur hinter einer Rueckfrage. */
.knopf--gefahr {
    border-color: var(--ton-daneben);
    color: var(--ton-daneben);
    font-weight: 600;
}

.knopf--gefahr:hover:not(:disabled) {
    background: rgba(255, 123, 123, 0.16);
}

.feld {
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 7px;
    color: var(--ton-schrift);
    font-family: inherit;
    font-size: 0.9rem;
    padding: 0.45rem 0.6rem;
    width: 7.5rem;
}

/* --- Brett ------------------------------------------------------------- */

/* Die abgeleiteten Masse stehen hier und nicht auf :root -- und das ist kein
   Geschmack, sondern eine Regel von CSS: ein Custom Property mit var() darin
   wird dort aufgeloest, wo es DEKLARIERT ist, nicht dort, wo es benutzt wird.
   Auf :root abgeleitet, blieben sie an der dortigen Kartenbreite haengen. Ein
   Brett mit eigener Breite (Spider) bekaeme dann die Hoehe des Standardmasses,
   die Karte waere zu hoch fuer ihre Breite, und die Grafik saesse mit weissen
   Streifen darin.

   Das Verhaeltnis 1 : 1.5202 ist das der Kartengrafiken; jede andere Zahl
   wuerde sie verzerren. */
.brett {
    /* Wie viele Spalten das Tableau hat. Die Zahl steht hier und nicht in der
       Auszeichnung, weil die Kartenbreite sich daraus ergibt. */
    --spaltenzahl: 8;
    --karte-min: 44px;
    --karte-max: 128px;

    /* Der Abstand zwischen Ablagenreihe und Tableau. Er hat einen Namen, weil
       die Spaltenhoehe ihn abziehen muss -- stand dort ersatzweise --spalt,
       fehlten dem Brett zwoelf Pixel, und die Seite rollte um vier. */
    --brett-spalt: clamp(0.7rem, 2vw, 1.4rem);

    /* Die Breite kommt aus dem vorhandenen Platz, nicht aus einer festen Zahl:
       das Fenster, geteilt durch die Spalten, abzueglich der Luecken.

       Vorher stand hier 6.9vw. Das nutzte auf einem iPad kaum die halbe Breite
       -- acht Spalten zu 6.9vw sind 55% des Fensters, der Rest blieb leer --
       und von der Hoehe wusste es gar nichts. Im Querformat lief das Brett
       deshalb gleichzeitig unten heraus und liess seitlich Platz liegen.

       Der zweite Wert ist die Gegenkraft: senkrecht muss neben der Karte selbst
       noch die Spalte darunter Platz haben, und zwar mit lesbarem Versatz. Aus
       Ablagenreihe (eine Kartenhoehe) + Spalte (eine Kartenhoehe + sechs
       Versaetze) folgt die Schranke -- ohne sie werden die Karten zwar gross,
       die Stapel aber zu weissen Streifen. Der kleinere der beiden Werte
       gewinnt. */
    /* Der Zoom sitzt AUSSEN um die Schranken herum und nicht darin.

       Innen hiesse: Bei kleinen Stufen faengt die Untergrenze --karte-min die
       Verkleinerung ab, und der Zoom wirkte genau dann nicht mehr, wenn er
       gebraucht wird -- auf einem engen Schirm im Querformat. Aussen gilt die
       Rechnung wie bisher, und ihr Ergebnis wird danach gestaucht oder
       gedehnt.

       Dass die Spaltenhoehe darunter NICHT mitskaliert, ist der Sinn der
       Sache: Der Platz bleibt, die Karten werden kleiner, und dadurch passen
       mehr davon uebereinander. Genau das ist im Querformat der Engpass. */
    --karte-breite: calc(clamp(
        var(--karte-min),
        min(
            (100cqw - (var(--spaltenzahl) - 1) * var(--spalt)) / var(--spaltenzahl),
            (100cqh - var(--brett-umgebung) - var(--brett-spalt)
                - var(--versatz-lesbar) * 6) / (2 * 1.5202)),
        var(--karte-max)) * var(--zoom, 1));

    --karte-hoehe: calc(var(--karte-breite) * 1.5202);
    --karte-radius: calc(var(--karte-breite) * 0.07);

    /* Der Platz, der einer Spalte hoechstens zusteht: was nach der
       Ablagenreihe uebrig bleibt. Vorher waren es feste 56vh -- die passten auf
       einem Bildschirm und liefen auf dem naechsten unten heraus, weil sie von
       der Ablagenreihe darueber nichts wussten.

       Die untere Schranke haelt eine Spalte auch dann noch lesbar, wenn gar
       kein Platz da ist: eine Karte plus sechs Versaetze. Dann rollt die Seite
       lieber, als dass die Karten aufeinanderliegen. */
    --spalten-hoehe: clamp(
        calc(var(--karte-hoehe) + var(--versatz-min) * 6),
        calc(100cqh - var(--brett-umgebung) - var(--karte-hoehe) - var(--brett-spalt)),
        500px);

    /* Anteilig an der Kartenhoehe -- auf jeder Geraetegroesse dasselbe
       Verhaeltnis. Hier stand eine Untergrenze von 26px, eingefuehrt fuer
       einen aufgedruckten Wertstreifen, den es nicht mehr gibt; auf dem Handy
       machte sie den sichtbaren Streifen zu 0.36 der Kartenhoehe, waehrend er
       am Rechner 0.27 misst. Genau diesen Unterschied hat Hendrik am
       27.08.2026 als falsch benannt: das Handy zeigt jetzt dieselben
       Proportionen wie der Rechner. */
    --versatz-max: calc(var(--karte-hoehe) * 0.27);

    display: flex;
    flex-direction: column;
    gap: var(--brett-spalt);

    /* Dasselbe fuer das ganze Brett und nicht nur fuer die Karten: auch ein
       Wisch, der auf einem leeren Platz oder in einer Luecke beginnt, soll die
       Seite nicht bewegen. "touch-action" wird ohnehin ueber die Vorfahren
       hinweg verschnitten -- diese Zeile allein wuerde genuegen; die auf der
       Karte steht daneben, damit man dort nicht das Falsche liest. */
    touch-action: none;
}

/* Freizellen und Fundamente teilen sich eine Reihe. Auf schmalen Geraeten ist
   das der wichtigste Platzgewinn -- zwei Reihen kosten rund 70 Pixel Hoehe. */
.ablagen {
    display: grid;
    grid-template-columns: repeat(8, var(--karte-breite));
    gap: var(--spalt);
    justify-content: center;
}

.spalten {
    display: grid;
    grid-template-columns: repeat(8, var(--karte-breite));
    gap: var(--spalt);
    justify-content: center;
    align-items: start;
}

/* Klondike hat sieben Spalten und oben eine Lücke zwischen Stapel und
   Fundamenten -- daher eigene Rasterbreiten.

   Die Lücke ist genau eine Kartenbreite und keine dehnbare Spalte. Sonst zieht
   sich die Ablagenreihe über die ganze Fensterbreite, während die Spalten
   darunter zentriert stehen: auf einem grossen Bildschirm klebt der Stapel dann
   am linken Rand, meterweit vom Spielfeld entfernt. So ist die obere Reihe
   genau so breit wie die untere, beide sind zentriert, und der Stapel steht
   dort, wo man ihn sucht -- über der ersten Spalte. */
.ablagen--klondike {
    grid-template-columns: repeat(7, var(--karte-breite));
}

.spalten--klondike {
    grid-template-columns: repeat(7, var(--karte-breite));
}

/* Klondike hat sieben Spalten, Spider zehn. Mehr steht hier nicht: die Breite
   rechnet .brett daraus selbst aus.

   Bei Spider duerfen die Karten zusaetzlich schmaler und weniger breit werden
   als sonst -- zehn Spalten sind eng, und eine Spalte traegt hier doppelt so
   viele Karten, die Laenge ist also wichtiger als die Breite. */
.brett--klondike {
    --spaltenzahl: 7;
}

.brett--spider {
    --spaltenzahl: 10;
    --karte-min: 38px;
    --karte-max: 104px;
}

/* Stapel, eine Kartenbreite Lücke, acht Plätze für die fertigen Folgen --
   zusammen genau die zehn Spalten des Tableaus. Siehe .ablagen--klondike. */
.ablagen--spider {
    grid-template-columns: repeat(10, var(--karte-breite));
}

.spalten--spider {
    grid-template-columns: repeat(10, var(--karte-breite));
}

/* Ein leerer Platzhalter, der die Rasterspalte zwischen Stapel und Ablagen
   belegt. Er ist bewusst nichts weiter -- die Breite kommt vom Raster. */
.ablagen__luecke {
    min-width: 0;
}

.platz--stock {
    cursor: pointer;
}

/* Der Stock bleibt sichtbar, wenn nicht ausgeteilt werden darf -- er wird nur
   gedaempft. Ihn zu verstecken waere schlechter: der Spieler soll sehen, dass
   noch Karten da sind, und erfahren, warum sie nicht kommen. */
.platz--gesperrt {
    opacity: 0.45;
}

.platz__zaehler {
    position: absolute;
    right: calc(var(--karte-breite) * -0.06);
    bottom: calc(var(--karte-breite) * -0.06);
    /* Mit Schranken statt rein anteilig.

       Anteilig allein ging nur so lange gut, wie die Karten klein waren: seit
       sie den Platz ausnutzen, wuchs die Zahl mit und sass als dicke Blase auf
       dem Stapel. Sie ist eine Nebenangabe und soll nie so laut werden wie die
       Karte selbst. Nach unten hin bleibt die Schranke, damit sie auf einem
       Handy lesbar bleibt. */
    min-width: clamp(16px, calc(var(--karte-breite) * 0.26), 25px);
    padding: 0.1em 0.35em;
    border-radius: 999px;
    background: var(--ton-rahmen);
    border: 1px solid rgba(255, 255, 255, 0.22);
    color: var(--ton-schrift);
    font-size: clamp(9px, calc(var(--karte-breite) * 0.145), 14px);
    font-variant-numeric: tabular-nums;
    text-align: center;
    pointer-events: none;
}

.platz {
    position: relative;
    width: var(--karte-breite);
    height: var(--karte-hoehe);
    border-radius: var(--karte-radius);
    border: 2px dashed rgba(255, 255, 255, 0.16);
    background: rgba(0, 0, 0, 0.16);
    cursor: pointer;
}

.platz__marke {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: calc(var(--karte-breite) * 0.42);
    color: rgba(255, 255, 255, 0.14);
    pointer-events: none;
}

/* Ein fertiger Stapel: kurz aufleuchten, einmal atmen, fertig.

   Bewusst nur der Zielplatz und nicht die verschwundenen Karten -- die sind aus
   dem Zustand raus, sobald der Zug durch ist. Sie fuer eine Animation
   weiterzufuehren hiesse, dem Spielstand ein zweites, rein optisches Leben zu
   geben; der Aufwand steht in keinem Verhaeltnis zu einer halben Sekunde Glanz.

   prefers-reduced-motion wird geachtet: wer Bewegung abbestellt hat, bekommt
   nur das Aufleuchten. */
.platz--aufgeloest {
    animation: aufgeloest 0.7s ease-out;
    z-index: 30;
}

@keyframes aufgeloest {
    0% {
        transform: scale(1);
        box-shadow: 0 0 0 0 rgba(242, 181, 68, 0.7);
    }

    35% {
        transform: scale(1.11);
        box-shadow: 0 0 0 10px rgba(242, 181, 68, 0.35);
    }

    100% {
        transform: scale(1);
        box-shadow: 0 0 0 22px rgba(242, 181, 68, 0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .platz--aufgeloest {
        animation: aufgeloest-ruhig 0.7s ease-out;
    }

    @keyframes aufgeloest-ruhig {
        0% { box-shadow: 0 0 0 0 rgba(242, 181, 68, 0.7); }
        100% { box-shadow: 0 0 0 22px rgba(242, 181, 68, 0); }
    }
}

.platz--ziel {
    border-color: var(--ton-gueltig);
    border-style: solid;
    box-shadow: 0 0 0 3px rgba(87, 217, 138, 0.25);
}

/* Eine Spalte ist so hoch wie ihr Inhalt, aber nie hoeher als --spalten-hoehe.
   Der Versatz schrumpft mit wachsender Kartenzahl, damit keine Spalte aus dem
   Bild laeuft -- das ist der Kniff, mit dem FreeCell spaeter auch auf ein Handy
   passt. Das Markup setzt --stapel (Karten minus eins) und --teiler (dasselbe,
   aber mindestens eins, damit nicht durch null geteilt wird). */
.spalte {
    position: relative;
    width: var(--karte-breite);
    min-height: var(--karte-hoehe);
    --versatz: clamp(
        var(--versatz-min),
        calc((var(--spalten-hoehe) - var(--karte-hoehe)) / var(--teiler, 1)),
        var(--versatz-max));
    height: calc(var(--karte-hoehe) + var(--versatz) * var(--stapel, 0));
}

.spalte--leer {
    height: var(--karte-hoehe);
}

/* --- Karte ------------------------------------------------------------- */

.karte {
    position: absolute;
    left: 0;
    width: var(--karte-breite);
    height: var(--karte-hoehe);
    border-radius: var(--karte-radius);
    background: linear-gradient(180deg, #ffffff 0%, #f2f4f6 100%);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.45), inset 0 0 0 1px rgba(0, 0, 0, 0.16);
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;

    /* KEIN WISCHEN AUF EINER KARTE. Vorher stand hier "manipulation" -- das
       verbietet nur den Doppeltipp-Zoom und erlaubt das Schieben der Seite
       weiter. Auf einem iPad hiess das: wer eine Karte ziehen will, verschiebt
       den ganzen Bildschirm. Ziehen selbst kommt dabei nicht zustande, denn
       HTML5-Drag-und-Drop gibt es fuer Finger unter iOS nicht.

       Zu verlieren ist dabei nichts: die drei Kartenbretter rollen nicht.
       Gemessen am 22.08.2026 auf 375 x 812 -- Solitaer, FreeCell und Spider
       passen vollstaendig ins Bild, es gibt keine Flaeche, die ein Wisch
       verschieben koennte. */
    touch-action: none;
    transition: transform 0.08s ease, box-shadow 0.12s ease;
}

.karte--ablage {
    position: relative;
}

.karte--rot { color: var(--ton-rot); }
.karte--schwarz { color: var(--ton-schwarz); }

.karte__bild {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: inherit;
    pointer-events: none;
    user-select: none;
    -webkit-user-drag: none;
}

.karte--gewaehlt {
    transform: translateX(calc(var(--karte-breite) * 0.10));
    box-shadow: 0 0 0 3px var(--ton-akzent), 0 6px 14px rgba(0, 0, 0, 0.5);
    z-index: 40;
}

.karte--ziel {
    box-shadow: 0 0 0 3px var(--ton-gueltig), 0 4px 10px rgba(0, 0, 0, 0.45);
}

/* Eine blockierte Karte nimmt gar keine Zeigerereignisse an -- dadurch landen
   Klicks auf dem Platz darunter. Ohne das würde sie den Klick abfangen und
   verschlucken, weil die Karte die Weitergabe an den Platz unterbindet. */
.karte--blockiert {
    cursor: default;
    pointer-events: none;
}

.karte:focus-visible {
    outline: 3px solid var(--ton-akzent);
    outline-offset: 2px;
}

/* --- Meldungen und Protokoll ------------------------------------------- */

.meldung {
    margin-top: 1rem;
    padding: 0.6rem 0.9rem;
    border-radius: 8px;
    background: rgba(198, 40, 40, 0.16);
    border: 1px solid rgba(198, 40, 40, 0.45);
    font-size: 0.9rem;
}

.protokoll {
    margin-top: 1.4rem;
    font-size: 0.85rem;
    color: var(--ton-schrift-leise);
}

.protokoll summary {
    cursor: pointer;
}

.protokoll pre {
    max-height: 15rem;
    overflow: auto;
    background: rgba(0, 0, 0, 0.34);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 8px;
    padding: 0.7rem 0.9rem;
    font-size: 0.8rem;
    line-height: 1.45;
}

.hinweis {
    color: var(--ton-schrift-leise);
    font-size: 0.85rem;
    margin: 0.4rem 0 0;
}

/* Ein Hinweis, der von einem Fehlschlag berichtet. Dieselbe Groesse, andere
   Farbe -- er steht an derselben Stelle wie der ruhige Text und soll nicht
   erst gesucht werden muessen. */
.hinweis--fehler {
    color: var(--ton-daneben);
}

/* Der Fuss der Hiscoretafel: durch eine Linie abgesetzt, damit der Knopf zum
   Wegwerfen nicht wie die naechste Tabellenzeile aussieht. */
.tafelfuss {
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    margin-top: 1rem;
    padding-top: 0.8rem;
}

.tafelfuss__knoepfe {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.6rem;
}

/* --- Pause ------------------------------------------------------------- */

/* Das Brett wird unkenntlich gemacht, damit die Pause keine Denkpause wird.
   Gegen die Entwicklerkonsole hilft das nicht -- es richtet sich gegen die
   bequeme Versuchung, nicht gegen Entschlossenheit. */
.verdeckt {
    filter: blur(18px) saturate(0.4);
    opacity: 0.5;
    pointer-events: none;
    user-select: none;
    transition: filter 0.2s ease;
}

.pausenschirm {
    margin: 1.2rem 0;
    padding: 1.2rem 1.4rem;
    border-radius: 12px;
    background: rgba(242, 181, 68, 0.12);
    border: 1px solid rgba(242, 181, 68, 0.5);
    max-width: 34rem;
}

.pausenschirm__titel {
    margin: 0 0 0.4rem;
    font-size: 1.3rem;
    font-weight: 700;
}

.pausenschirm p {
    margin: 0 0 0.6rem;
}

.pausenschirm__rest {
    color: var(--ton-schrift-leise);
    font-size: 0.88rem;
    font-variant-numeric: tabular-nums;
}

/* --- Spielwahl --------------------------------------------------------- */

.spielwahl {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0 0 1rem;
}

.spielwahl__eintrag {
    padding: 0.4rem 1rem;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    background: rgba(255, 255, 255, 0.05);
    color: var(--ton-schrift-leise);
    text-decoration: none;
    font-size: 0.9rem;
    transition: background 0.12s ease, color 0.12s ease;
}

.spielwahl__eintrag:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--ton-schrift);
}

.spielwahl__eintrag--aktiv {
    background: var(--ton-akzent);
    border-color: var(--ton-akzent);
    color: #2a1c00;
    font-weight: 600;
}

/* --- Anmeldung --------------------------------------------------------- */

.anmeldung {
    margin: 0 0 1.4rem;
    max-width: 40rem;
}

.anmeldung__zeile {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
    margin: 0.5rem 0;
}

.feld--breit {
    width: 16rem;
    max-width: 100%;
}

.hinweiskasten {
    margin: 1rem 0;
    padding: 0.9rem 1.1rem;
    border-radius: 10px;
    background: rgba(242, 181, 68, 0.12);
    border: 1px solid rgba(242, 181, 68, 0.45);
}

.hinweiskasten p {
    margin: 0 0 0.5rem;
}

.code {
    font-family: "Cascadia Mono", Consolas, monospace;
    font-size: 1.35rem;
    letter-spacing: 0.12em;
    color: var(--ton-akzent);
    user-select: all;
}

/* --- Tabelle ----------------------------------------------------------- */

.tabellenrahmen {
    overflow-x: auto;
    max-width: 52rem;
}

.tabelle {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.94rem;
}

.tabelle th,
.tabelle td {
    padding: 0.5rem 0.8rem;
    text-align: left;
    border-bottom: 1px solid rgba(255, 255, 255, 0.09);
    white-space: nowrap;
}

.tabelle th {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ton-schrift-leise);
    font-weight: 600;
}

.tabelle__zahl {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.tabelle__ich {
    background: var(--ton-akzent-schwach);
    font-weight: 600;
}

/* Knöpfe, die in Wahrheit Verweise sind, sollen nicht unterstrichen sein. */
a.knopf {
    text-decoration: none;
    display: inline-block;
}

/* --- Startseite -------------------------------------------------------- */

/* Volle Buehnenhoehe, damit nur die Kacheln rollen und die Begruessung stehen
   bleibt. Ohne die feste Hoehe waere die Seite so hoch wie ihr Inhalt, und dann
   rollte alles gemeinsam weg -- auch der Gruss, den niemand sucht. */
.start {
    max-width: 78rem;
    margin: 0 auto;
    height: 100%;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.start__kopf {
    flex: none;
    max-width: 44rem;
    margin-bottom: clamp(0.8rem, 2vw, 1.3rem);
}

/* Der einzige rollende Teil der Startseite. */
.start__flaeche {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding-bottom: 0.4rem;
}

.start__titel {
    margin: 0 0 0.45rem;
    font-size: clamp(1.4rem, 2.6vw, 2rem);
    letter-spacing: -0.02em;
}

.start__titel span {
    color: var(--ton-akzent);
}

.start__text {
    margin: 0;
    color: var(--ton-schrift-leise);
    font-size: 0.9rem;
    line-height: 1.5;
}

/* Schmalere Spalten, engere Abstaende. Auf einem iPad passten die alten
   Kacheln nicht mehr auf den Schirm -- und eine Uebersicht, fuer die man
   scrollen muss, ist keine. */
.kachelreihe {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12.5rem, 1fr));
    gap: 0.6rem;
    margin-top: 0.6rem;
}

/* Die zweite Reihe traegt weniger Gewicht: kleinere Kacheln, damit die vier
   Spiele oben die Seite bestimmen. */
.kachelreihe--klein {
    grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr));
    max-width: 44rem;
}

.kachel {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    padding: 0.75rem 0.85rem 0.85rem;
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.035);
    color: var(--ton-schrift);
    text-decoration: none;
    transition: background 0.14s ease, transform 0.14s ease, border-color 0.14s ease;
}

a.kachel:hover {
    background: rgba(255, 255, 255, 0.075);
    border-color: rgba(255, 255, 255, 0.2);
    transform: translateY(-2px);
}

.kachel__kopf {
    display: flex;
    align-items: center;
    margin-bottom: 0.55rem;
}

.kachel__zeichen {
    display: grid;
    place-items: center;
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.08);
    font-size: 1.2rem;
    line-height: 1;
}

/* Gross und blass in der unteren Ecke. Es soll die Kachel faerben, nicht
   gelesen werden -- deshalb liegt es hinter dem Text und faengt keine Klicks.

   Ohne negativen Ueberstand: die Kartenfarben und das chinesische Zeichen sitzen
   sehr unterschiedlich in ihrem Schriftkasten. Angeschnitten war vom Karo nur
   noch ein Zipfel zu sehen, waehrend das Zeichen voll dastand. Ein festes
   Kaestchen mit zentriertem Zeichen macht alle vier gleich gross. */
.kachel__wasserzeichen {
    position: absolute;
    right: 0.35rem;
    bottom: 0.35rem;
    display: grid;
    place-items: center;
    width: 4.2rem;
    height: 4.2rem;
    font-size: 3.6rem;
    line-height: 1;
    opacity: 0.085;
    pointer-events: none;
    user-select: none;
}

/* Nur die Schriftfarbe zaehlt fuer beide; die Flaechenfarbe gilt dem Abzeichen. */
.kachel__zeichen--rot   { color: #ff8a80; }
.kachel__zeichen--gold  { color: var(--ton-akzent); }
.kachel__zeichen--gruen { color: var(--ton-gueltig); }
.kachel__zeichen--stein { color: #ff6b5e; }

.kachel__kopf .kachel__zeichen--rot   { background: rgba(198, 40, 40, 0.2); }
.kachel__kopf .kachel__zeichen--gold  { background: rgba(242, 181, 68, 0.2); }
.kachel__kopf .kachel__zeichen--gruen { background: rgba(87, 217, 138, 0.18); }
.kachel__kopf .kachel__zeichen--stein { background: rgba(255, 255, 255, 0.94); }

.kachel__marke {
    margin-left: auto;
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.11em;
    color: var(--ton-schrift-leise);
}

.kachel__titel {
    font-size: 0.98rem;
    font-weight: 700;
    margin: 0 0 0.3rem;
}

.kachel__text {
    margin: 0;
    font-size: 0.79rem;
    line-height: 1.42;
    color: var(--ton-schrift-leise);
}

/* Schiebt sich an den unteren Rand, damit die Kacheln einer Reihe ihre
   Aufforderung auf derselben Hoehe tragen -- auch bei ungleich langem Text. */
.kachel__weg {
    margin-top: auto;
    padding-top: 0.6rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--ton-akzent);
}

.kachel--bald {
    opacity: 0.42;
    pointer-events: none;
}

/* --- Mahjong ------------------------------------------------------------

   Die Auslage ist ein Koordinatenfeld, kein Raster: die Steine liegen in
   halben Steinbreiten versetzt und ueberlappen einander. Jeder Stein bekommt
   seine Stelle ueber --x und --y (in halben Breiten) und seine Ebene ueber --e.

   Die dritte Dimension entsteht aus zwei Kniffen: hoehere Ebenen werden ein
   Stueck nach links oben gerueckt, und jeder Stein traegt eine rechte und
   untere Kante in seiner eigenen Farbe. Zusammen sieht es aus, als lege ein
   Stein auf dem anderen -- ohne eine einzige 3D-Transformation, die auf
   schwachen Geraeten teuer waere. */

.mahjongbrett {
    --stein-min: 28px;
    --stein-max: 110px;

    /* Anders als bei den Kartenspielen stehen die Ausmasse der Auslage fest --
       in halben Steinbreiten, aus dem Aufbau. Die Steingroesse laesst sich
       deshalb ausrechnen statt schaetzen: einmal aus der Breite, einmal aus der
       Hoehe, der kleinere Wert gewinnt. Genau dafuer stehen --spalten und
       --zeilen jetzt an diesem Kasten und nicht mehr an der Auslage darin.

       Die Faktoren kommen aus den Massen weiter unten:
         Breite = --spalten / 2 * b  +  0.1b (Kante)
         Hoehe  = --zeilen / 2 * 1.32b  +  0.1b  +  0.55b + 0.594b (Polster)
                = b * (0.66 * --zeilen + 1.244)

       Vorher stand hier 4.4vw. Im Hochformat blieb damit ein Drittel der Breite
       ungenutzt, im Querformat lief das Brett gleichzeitig um 100 Pixel unten
       heraus -- eine reine Breitenangabe kann beides nicht auseinanderhalten. */
    /* Zoom aussen um die Schranken -- die Begruendung steht bei --karte-breite. */
    --stein-breite: calc(clamp(
        var(--stein-min),
        min(
            100cqw / (var(--spalten) * 0.5 + 0.1),
            (100cqh - var(--brett-umgebung)) / (var(--zeilen) * 0.66 + 1.244)),
        var(--stein-max)) * var(--zoom, 1));

    --stein-hoehe: calc(var(--stein-breite) * 1.32);

    /* Der Versatz je Ebene. Zu wenig wirkt flach, zu viel laesst die oberen
       Ebenen von der Grundflaeche rutschen. */
    --ebenen-versatz: calc(var(--stein-breite) * 0.11);

    /* Die sichtbare Dicke eines Steins. */
    --stein-kante: calc(var(--stein-breite) * 0.1);

    display: flex;
    justify-content: center;

    /* Waagerecht rollen, wenn die Auslage breiter ist als das Fenster.

       Achtung, CSS-Falle: sobald eine Achse nicht mehr "visible" ist, macht der
       Browser aus der anderen automatisch "auto". Dieser Kasten rollt also auch
       senkrecht, ob man will oder nicht -- und zeigte prompt eine Bildlaufleiste,
       obwohl reichlich Platz war. Verursacher war nicht das Spielfeld, sondern
       der Schein darunter (siehe .auslage::before): er ragte unten hinaus und
       schuf 49 Pixel Ueberlauf aus dem Nichts.

       Deshalb ragt jetzt nichts mehr nach unten hinaus, und dieses Polster
       haelt den Abstand, den vorher der Schein gefuellt hat. */
    padding: calc(var(--ebenen-versatz) * 5) 0 calc(var(--stein-hoehe) * 0.45) 0;
    overflow-x: auto;
}

.auslage {
    position: relative;

    /* Ausdehnung in halben Steinbreiten, aus dem Aufbau gerechnet. */
    width: calc(var(--spalten) * var(--stein-breite) / 2 + var(--stein-kante));
    height: calc(var(--zeilen) * var(--stein-hoehe) / 2 + var(--stein-kante));
    flex: none;
}

/* Ein weicher Schein unter der Auslage. Ohne ihn schwebt die Schildkroete vor
   dem Hintergrund; mit ihm liegt sie auf einem Tisch. */
/* Nach unten ragt der Schein bewusst nicht hinaus: ein absolut positioniertes
   Kind erweitert den rollbaren Bereich seines Kastens nach unten und rechts
   (nach oben und links wird es abgeschnitten). Ein Ueberstand von acht Prozent
   erzeugte deshalb eine senkrechte Bildlaufleiste. Der Schwerpunkt des Scheins
   liegt stattdessen tiefer, das sieht genauso aus. */
.auslage::before {
    content: "";
    position: absolute;
    /* Nach oben darf er hinausragen, seitlich und nach unten nicht: nur dort
       vergroessert ein Kind die rollbare Flaeche. Solange die Auslage schmal
       war, fielen die seitlichen 3% nicht auf -- seit sie die volle Breite
       nutzt, waren es prompt 22 Pixel Ueberlauf und eine Bildlaufleiste.
       Sichtbar aendert das kaum etwas, der Verlauf ist am Rand ohnehin
       durchsichtig. */
    inset: -6% 0 0 0;
    border-radius: 50% / 22%;
    background: radial-gradient(ellipse at 50% 68%,
        rgba(0, 0, 0, 0.32) 0%, rgba(0, 0, 0, 0.16) 55%, transparent 80%);
    pointer-events: none;
}

.stein {
    position: absolute;
    left: calc(var(--x) * var(--stein-breite) / 2 - var(--e) * var(--ebenen-versatz));
    top: calc(var(--y) * var(--stein-hoehe) / 2 - var(--e) * var(--ebenen-versatz));
    width: var(--stein-breite);
    height: var(--stein-hoehe);
    border-radius: calc(var(--stein-breite) * 0.14);
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    touch-action: manipulation;

    /* Rechts und unten die Dicke, dazu ein Schatten auf das, was darunter
       liegt. Das ist die ganze Raeumlichkeit -- ohne 3D-Transformation, die auf
       schwachen Geraeten teuer waere.

       Der Schatten waechst mit der Ebene: ein Stein weiter oben wirft weiter.
       Genau das laesst den Stapel als Stapel lesen und nicht als Muster. */
    background: var(--stein-kantenton, #b8ac93);
    box-shadow:
        calc(var(--stein-kante) * 0.5)
        calc(var(--stein-kante) * 0.7)
        calc(var(--stein-kante) * (1.4 + var(--e) * 0.5))
        rgba(0, 0, 0, calc(0.32 + var(--e) * 0.05));
    transition: transform 0.08s ease, filter 0.12s ease;
}

.stein__flaeche {
    position: absolute;
    inset: 0 var(--stein-kante) var(--stein-kante) 0;
    border-radius: calc(var(--stein-breite) * 0.12);
    /* Warmes Elfenbein, kein Weiss. Weisse Steine auf gruenem Grund flimmern,
       und die Schriftfarben stehen auf Elfenbein ruhiger. */
    background: linear-gradient(158deg, #fdfaf0 0%, #f7f1e0 48%, #ece4cf 100%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    overflow: hidden;

    /* Lichtkante oben links, Trennlinie zur Dicke -- und ein Rahmen, den die
       Auswahl setzt. Alle drei in einer Eigenschaft, weil box-shadow sich sonst
       gegenseitig ueberschreibt. */
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.95),
        inset 1px 0 0 rgba(255, 255, 255, 0.7),
        inset 0 0 0 var(--rand-breite, 0px) var(--rand-farbe, transparent);
}

.stein__zeichen {
    font-size: calc(var(--stein-breite) * 0.56);
    line-height: 1;
    font-weight: 600;

    /* Eine Schrift mit chinesischen Zeichen. Ohne diese Kette faellt Windows
       auf eine Ersatzschrift zurueck, in der die Zeichen unterschiedlich gross
       wirken. */
    font-family: "Yu Gothic UI", "Microsoft YaHei", "PingFang SC",
                 "Noto Sans CJK SC", "Segoe UI", sans-serif;
}

.stein__marke {
    font-size: calc(var(--stein-breite) * 0.2);
    line-height: 1;
    margin-top: calc(var(--stein-breite) * 0.08);
    opacity: 0.5;
    font-family: "Yu Gothic UI", "Microsoft YaHei", "PingFang SC",
                 "Noto Sans CJK SC", "Segoe UI", sans-serif;
}

/* Die Farben der Steinarten. Sie sind das schnellste Erkennungsmerkmal --
   schneller als das Zeichen, gerade wenn die Steine klein sind. */
.stein--zeichen  { --stein-farbton: #b3261e; --stein-kantenton: #c4b79c; }
.stein--bambus   { --stein-farbton: #1f6f43; --stein-kantenton: #b6c0a8; }
.stein--kreis    { --stein-farbton: #1a4f8a; --stein-kantenton: #aab6c4; }
/* Die Winde blau, nicht schwarz. Schwarz auf Elfenbein liest sich zwar am
   besten, sitzt aber optisch neben den roten Zahlzeichen -- und dann sind es
   wieder zwei Sorten Schriftzeichen, die sich nur am Zeichen unterscheiden. */
.stein--wind     { --stein-farbton: #2f5a8f; --stein-kantenton: #b3bcc8; }

.stein--drache-rot   { --stein-farbton: #c1121f; --stein-kantenton: #c9b4a4; }
.stein--drache-gruen { --stein-farbton: #12704a; --stein-kantenton: #aec2b2; }
.stein--drache-weiss { --stein-farbton: #5d6470; --stein-kantenton: #bcc0c6; }

.stein--jahreszeit { --stein-farbton: #a06a12; --stein-kantenton: #c9bb9a; }
.stein--blume      { --stein-farbton: #9b3f8c; --stein-kantenton: #c3b0c0; }

.stein__zeichen { color: var(--stein-farbton, #33302b); }
.stein__marke   { color: var(--stein-farbton, #33302b); }

/* --- Staebe, Punkte und der leere Rahmen -------------------------------- */

/* Der eigentliche Unterschied zwischen den drei Zahlfarben ist nicht die Farbe,
   sondern die Form: Zahlzeichen, Staebe oder Punkte. Das erkennt das Auge im
   Vorbeisehen, ohne zu lesen. */
.stein__bild {
    width: calc(var(--stein-breite) * 0.78);
    height: calc(var(--stein-breite) * 0.78);
    display: block;
}

.pip--stab {
    fill: var(--stein-farbton, #1f6f43);
}

/* Die Kreise wechseln die Farbe wie bei echten Steinen. Welcher Punkt welche
   bekommt, haengt allein an seiner Position -- zwei Steine desselben Werts
   sehen deshalb immer gleich aus, und nur so lassen sie sich als Paar
   erkennen. */
.pip--blau { fill: #1a4f8a; }
.pip--rot  { fill: #b3261e; }

.pip--rahmen {
    fill: none;
    stroke: var(--stein-farbton, #5d6470);
    stroke-width: 7;
}

/* Verdeckt: nur zurueckgenommen, nicht ausgeblendet.

   Am Anfang liegen 109 der 144 Steine verdeckt. Wuerden die alle kraeftig
   abgedunkelt, saehe das Brett aus wie ein Haufen grauer Kiesel mit ein paar
   bunten Tupfern -- und der schoenste Teil des Spiels, die Auslage selbst,
   waere dahin. Ein leiser Unterschied reicht: er sagt, was frei ist, ohne den
   Rest zu toeten. */
.stein--verdeckt {
    cursor: default;
    filter: brightness(0.87) saturate(0.8);
}

.stein--gewaehlt {
    transform: translateY(calc(var(--stein-breite) * -0.07));
    --rand-breite: calc(var(--stein-breite) * 0.07);
    --rand-farbe: var(--ton-akzent);
}

/* Passende Steine bekommen nur einen leisen Rahmen. Ein kraeftiger waere ein
   Loesungshinweis; hier geht es darum, den zweiten Tipp nicht ins Leere laufen
   zu lassen. */
.stein--partner {
    --rand-breite: calc(var(--stein-breite) * 0.05);
    --rand-farbe: var(--ton-gueltig);
}

@media (hover: hover) {
    .stein:not(.stein--verdeckt):hover {
        transform: translateY(calc(var(--stein-breite) * -0.04));
    }
}

/* --- Eingeblendete Meldungen ------------------------------------------- */

/* Fest am unteren rechten Rand, ueber allem. Der entscheidende Punkt ist, dass
   diese Zettel im Layout NICHT vorkommen: sie erscheinen und verschwinden, ohne
   dass sich das Spielfeld einen Pixel bewegt. Vorher standen sie im Fluss, und
   jede Meldung schob das Brett weg -- mitten im Spiel, wo man gerade zielt. */
.meldungen {
    position: fixed;
    right: clamp(0.6rem, 2vw, 1.6rem);
    bottom: clamp(0.6rem, 2vw, 1.6rem);
    z-index: 900;

    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    align-items: flex-end;
    max-width: min(26rem, calc(100vw - 2rem));

    /* Der Behaelter selbst faengt keine Klicks ab. Sonst laege eine unsichtbare
       Flaeche ueber dem Brett, und der Tipp auf eine Karte ginge ins Leere. */
    pointer-events: none;
}

.meldungen__zettel {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.6rem 0.7rem 0.6rem 0.9rem;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    background: #1b3a31;
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
    font-size: 0.9rem;
    line-height: 1.4;

    animation: meldung-herein 0.16s ease-out;
}

@keyframes meldung-herein {
    from { opacity: 0; transform: translateY(0.4rem); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .meldungen__zettel { animation: none; }
}

/* Ein farbiger Streifen links statt eines eingefaerbten Kastens: die Meldung
   soll auffallen, aber nicht schreien. */
.meldungen__zettel--hinweis { border-left: 4px solid var(--ton-akzent); }
.meldungen__zettel--fehler  { border-left: 4px solid var(--ton-rot); }
.meldungen__zettel--erfolg  { border-left: 4px solid var(--ton-gueltig); }

.meldungen__text {
    flex: 1;
}

.meldungen__schliessen {
    appearance: none;
    flex: none;
    border: 0;
    background: transparent;
    color: var(--ton-schrift-leise);
    font-size: 0.85rem;
    line-height: 1;
    padding: 0.25rem 0.3rem;
    border-radius: 6px;
    cursor: pointer;
}

.meldungen__schliessen:hover {
    background: rgba(255, 255, 255, 0.12);
    color: var(--ton-schrift);
}

/* --- Anleitung --------------------------------------------------------- */

/* Ein <dialog> statt eines Absatzes unter dem Brett. Der Browser bringt Fokus,
   Escape und den Hintergrund mit; hier steht nur, wie es aussieht. */
.anleitung {
    /* Fest positioniert, weil der Knopf und damit der Dialog in der Leiste
       stehen -- und die ist ein Flex-Container. Als Flex-Element wird der
       Dialog auf die Breite zusammengedrueckt, die zwischen den Knoepfen uebrig
       bleibt: zwei Pixel. Fest positioniert nimmt ihn aus dem Flexfluss heraus,
       und "inset: 0" mit "margin: auto" zentriert ihn im Fenster. */
    position: fixed;
    inset: 0;
    height: fit-content;

    width: min(36rem, calc(100vw - 2rem));
    max-height: min(80vh, 44rem);
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 14px;
    background: #16302a;
    color: var(--ton-schrift);
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6);
    overflow: hidden;

    /* Sonst steht der Dialog oben am Rand statt in der Mitte. */
    margin: auto;
}

/* Breiter fuer Inhalte, die keine Fliesstexte sind. Die Hiscoretabelle hat
   acht Spalten; in den sechsunddreissig Rem einer Anleitung muesste sie
   seitlich rollen, und die Kennzahlen darueber staenden untereinander. */
.anleitung--breit {
    width: min(56rem, calc(100vw - 2rem));
}

.anleitung::backdrop {
    background: rgba(3, 12, 9, 0.66);
    backdrop-filter: blur(3px);
}

.anleitung__kopf {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1rem 1.3rem 0.8rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.09);
}

.anleitung__titel {
    margin: 0;
    font-size: 1.15rem;
}

.anleitung__schliessen {
    appearance: none;
    margin-left: auto;
    border: 0;
    background: transparent;
    color: var(--ton-schrift-leise);
    font-size: 1.1rem;
    line-height: 1;
    padding: 0.3rem 0.4rem;
    border-radius: 7px;
    cursor: pointer;
}

.anleitung__schliessen:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--ton-schrift);
}

/* Der Inhalt scrollt, Kopf und Fuss bleiben stehen. */
.anleitung__inhalt {
    padding: 0.2rem 1.3rem 0.6rem;
    overflow-y: auto;
    max-height: calc(min(80vh, 44rem) - 8.5rem);
    font-size: 0.94rem;
    line-height: 1.55;
}

.anleitung__inhalt h3 {
    margin: 1.1rem 0 0.4rem;
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--ton-akzent);
}

.anleitung__inhalt h3:first-child {
    margin-top: 0.9rem;
}

.anleitung__inhalt p {
    margin: 0 0 0.7rem;
    color: #dbe7e0;
}

.anleitung__fuss {
    display: flex;
    justify-content: flex-end;
    padding: 0.8rem 1.3rem 1.1rem;
    border-top: 1px solid rgba(255, 255, 255, 0.09);
}

/* Ein Hinweis, der nicht nur einordnet, sondern etwas meldet. Bewusst kein
   Ueberlagerungsfenster: er gehoert zum Brett und bleibt stehen, solange der
   Zustand anhaelt -- ein Dialog waere hier ein Klick, der nichts entscheidet. */
.hinweis--warnung {
    color: var(--ton-schrift);
    border-left: 3px solid var(--ton-rot);
    padding-left: 0.7rem;
}

/* --- Minesweeper -------------------------------------------------------- */

/* Die Feldgroesse aus dem Platz gerechnet, wie bei den anderen Brettern: einmal
   aus der Breite, einmal aus der Hoehe, der kleinere Wert gewinnt. Anders als
   dort stehen Spalten- und Zeilenzahl nicht fest -- es gibt drei Grade, und das
   Profibrett ist fast doppelt so breit wie hoch. Deshalb kommen beide Zahlen
   aus der Auszeichnung. */
.minenfeld {
    --feld-min: 18px;
    --feld-max: 54px;

    --spalt-feld: 2px;

    /* Über der allgemeinen Brettumgebung liegt hier noch eine Zeile: die
       Gradwahl im Übungsmodus. Gemessen sind 394px statt 344; der Aufschlag ist
       etwas grosszuegiger, damit auch die Herausforderungsseite mit ihrer
       Hinweiszeile hineinpasst. */
    --minen-umgebung: calc(var(--brett-umgebung) + 2.5rem);

    /* Die Luecken zaehlen mit. Bei sechzehn Zeilen sind es dreissig Pixel --
       genug, um ein Brett, das rechnerisch passt, doch ueberlaufen zu lassen. */
    /* Zoom aussen um die Schranken -- die Begruendung steht bei --karte-breite. */
    --feld: calc(clamp(
        var(--feld-min),
        min(
            (100cqw - (var(--spalten) - 1) * var(--spalt-feld)) / var(--spalten),
            (100cqh - var(--minen-umgebung) - (var(--zeilen) - 1) * var(--spalt-feld))
                / var(--zeilen)),
        var(--feld-max)) * var(--zoom, 1));

    display: grid;
    grid-template-columns: repeat(var(--spalten), var(--feld));
    grid-auto-rows: var(--feld);
    gap: var(--spalt-feld);
    justify-content: center;

    /* Waagerecht rollen, wenn das Profibrett auf einem Handy wirklich nicht
       mehr passt. Siehe die Falle beim Mahjongbrett: sobald eine Achse nicht
       mehr "visible" ist, macht der Browser aus der anderen "auto" -- deshalb
       darf hier nichts nach unten oder zur Seite hinausragen. */
    overflow-x: auto;
    padding-bottom: 0.4rem;
}

.minenfeld__feld {
    appearance: none;
    padding: 0;
    border: 0;
    border-radius: max(2px, calc(var(--feld) * 0.12));
    font-family: inherit;
    font-weight: 800;
    font-size: calc(var(--feld) * 0.56);
    line-height: 1;
    cursor: pointer;
    user-select: none;

    /* Ohne das faengt ein langes Druecken auf dem Handy die Textauswahl und die
       Lupe ein, statt einfach nur ein Feld aufzudecken. */
    -webkit-touch-callout: none;
    touch-action: manipulation;
}

.minenfeld__feld:disabled {
    cursor: default;
}

.minenfeld__feld--verdeckt {
    background: linear-gradient(180deg, #2c6a50 0%, #235943 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 1px 2px rgba(0, 0, 0, 0.4);
    color: transparent;
}

.minenfeld__feld--verdeckt:hover:not(:disabled) {
    background: linear-gradient(180deg, #35785b 0%, #2a664c 100%);
}

.minenfeld__feld--offen {
    background: rgba(0, 0, 0, 0.26);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}

.minenfeld__feld--markiert {
    background: linear-gradient(180deg, #2c6a50 0%, #235943 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 1px 2px rgba(0, 0, 0, 0.4);
    color: var(--ton-akzent);
}

.minenfeld__feld--mine {
    background: var(--ton-rot);
    color: #ffffff;
}

/* Die Mine, auf die getreten wurde -- damit sichtbar ist, woran es lag. */
.minenfeld__feld--ausgeloest {
    background: #ff5252;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.6);
}

/* Eine Markierung, unter der keine Mine lag. Erst nach dem Ende zu sehen. */
.minenfeld__feld--daneben {
    color: var(--ton-rot);
    text-decoration: line-through;
}

/* Die klassischen Farben. Sie sind kein Schmuck: bei zweihundert Feldern
   erkennt man die Zahl schneller an der Farbe als an ihrer Form. */
.minenfeld__feld--zahl1 { color: #6ab7ff; }
.minenfeld__feld--zahl2 { color: #5fd98a; }
.minenfeld__feld--zahl3 { color: #ff7b7b; }
.minenfeld__feld--zahl4 { color: #b79bff; }
.minenfeld__feld--zahl5 { color: #ffb04d; }
.minenfeld__feld--zahl6 { color: #4fd8d8; }
.minenfeld__feld--zahl7 { color: #e8e8e8; }
.minenfeld__feld--zahl8 { color: #9db5aa; }

/* --- Memory ------------------------------------------------------------- */

/* Wie beim Minenfeld: die Kartengroesse aus dem Platz gerechnet, aus beiden
   Richtungen, der kleinere Wert gewinnt. Die Karten sind hochkant wie
   Spielkarten -- daher der Faktor beim Hoehenanteil. */
/* Eine Kachel, die keinen Verweis oeffnet, sondern einen Dialog. Sie muss
   deshalb ein <button> sein und bekommt hier zurueckgenommen, was ein Browser
   Knoepfen von sich aus mitgibt. */
.kachel--knopf {
    appearance: none;
    font: inherit;
    text-align: left;
    width: 100%;
}

/* --- Schnellstart-Anleitung ---------------------------------------------- */

.schnellstart__spiel {
    margin: 1rem 0 0.3rem;
    font-weight: 700;
    color: var(--ton-akzent);
}

.schnellstart__liste {
    display: grid;
    gap: 0.3rem;
}

.schnellstart__zeile {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* Die Adresse darf umbrechen: sie ist laenger als der Dialog breit, und ein
   waagerechter Rollbalken mitten in einer Anleitung ist eine Zumutung. */
.schnellstart__weg {
    flex: 1;
    min-width: 12rem;
    font-family: "Cascadia Mono", Consolas, monospace;
    font-size: 0.82rem;
    overflow-wrap: anywhere;
    color: var(--ton-gueltig);
}

.schnellstart__zeile .knopf {
    padding: 0.25rem 0.6rem;
    font-size: 0.78rem;
}

/* --- Tagesuebersicht ---------------------------------------------------- */

/* Eine Zeile je Spielart, drei Spalten: Name, eigener Wert, Einordnung. Ein
   Raster und keine Tabelle -- die Spalten sollen untereinander fluchten, aber
   es sind keine Daten mit Kopfzeile. */
.heute {
    margin: 0 0 1rem;
    padding: 0.7rem 0.9rem;
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.07);
}

.heute__kopf {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.6rem;
    margin-bottom: 0.5rem;
    flex-wrap: wrap;
}

.heute__titel {
    margin: 0;
    font-size: 0.92rem;
    color: var(--ton-schrift-leise);
}

.heute__titel strong { color: var(--ton-schrift); }

.heute__serie {
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    background: rgba(242, 181, 68, 0.16);
    border: 1px solid rgba(242, 181, 68, 0.35);
    color: var(--ton-akzent);
    font-size: 0.72rem;
    font-weight: 700;
    white-space: nowrap;
}

/* Zwei Spalten, wo Platz ist: acht Zeilen untereinander kosten die Startseite
   ihre Rollfreiheit, und die war teuer erkaempft. Nebeneinander sind es vier. */
.heute__liste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
    gap: 0.1rem 1.4rem;
}

.heute__zeile {
    display: grid;
    grid-template-columns: minmax(6rem, 1fr) auto minmax(0, 1.4fr);
    align-items: baseline;
    gap: 0.7rem;
    padding: 0.22rem 0;
    font-size: 0.85rem;
}

.heute__name {
    color: var(--ton-schrift);
    text-decoration: none;
    font-weight: 600;
}

.heute__name:hover { color: var(--ton-akzent); }

.heute__wert {
    font-variant-numeric: tabular-nums;
    color: var(--ton-gueltig);
    font-weight: 700;
    white-space: nowrap;
}

/* Offen heisst: da wartet noch etwas. Leise, aber nicht unsichtbar. */
.heute__wert--offen {
    color: var(--ton-schrift-leise);
    font-weight: 500;
}

.heute__platz {
    color: var(--ton-schrift-leise);
    font-size: 0.78rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Erledigt: die Zeile tritt zurueck, ohne zu verschwinden -- man will ja auch
   sehen, wie man dasteht. */
.heute__zeile--fertig .heute__name { color: var(--ton-schrift-leise); }

@media (max-width: 600px) {
    .heute__zeile {
        grid-template-columns: 1fr auto;
    }

    /* Die Einordnung rutscht unter den Namen: nebeneinander bliebe von ihr
       nichts als drei Punkte. */
    .heute__platz {
        grid-column: 1 / -1;
        margin-top: -0.15rem;
    }
}

/* --- Enge Spiele auf dem Telefon ---------------------------------------- */

/* Auf allem, was breiter ist als ein Telefon, gibt es hier nichts zu sagen:
   der Vermerk bleibt unsichtbar und die Reihenfolge unveraendert. */
.engvermerk {
    display: none;
}

@media (max-width: 600px) {
    /* Sichtbar, aber leise. Es ist ein Hinweis und keine Warnung -- gespielt
       werden darf trotzdem, und wer unterwegs nur sein Telefon hat, soll nicht
       das Gefuehl bekommen, etwas Verbotenes zu tun. */
    .engvermerk {
        display: inline-block;
        margin-left: 0.4rem;
        padding: 0.05rem 0.4rem;
        border-radius: 999px;
        background: rgba(242, 181, 68, 0.16);
        border: 1px solid rgba(242, 181, 68, 0.35);
        color: var(--ton-akzent);
        font-size: 0.62rem;
        font-weight: 600;
        letter-spacing: 0.02em;
        white-space: nowrap;
        vertical-align: middle;
    }

    /* Ans Ende, aber untereinander in der gewohnten Reihenfolge: wer Mahjong
       sucht, soll es finden -- nur eben nicht als erstes. */
    .kachel.eng,
    .spielwahl__eintrag.eng {
        order: 10;
    }

    /* Die Spielwahl ist sonst keine Flaeche mit Reihenfolge. Ohne das griffe
       "order" nicht. */
    .spielwahl {
        display: flex;
        flex-direction: column;
    }
}

/* --- Purer Spielverweis ------------------------------------------------- */

/* Nur das Spiel. Dieselbe Aufteilung wie die Buehne -- Flaeche oben, schmale
   Leiste unten --, nur ohne alles daneben. Die Container-Abfrage muss sein:
   die Bretter rechnen ihre Groesse gegen 100cqw und 100cqh, und ohne einen
   Container waeren beide bedeutungslos. */
.pur {
    display: grid;
    grid-template-rows: 1fr auto;
    height: 100dvh;
    overflow: hidden;
    background: var(--ton-grund);
}

.pur__flaeche {
    container-type: size;
    min-height: 0;
    padding: 0.6rem;
    display: grid;
    place-items: center;
    overflow: auto;
}

/* --- Ein Brett, das waechst, haengt oben ---

   DIE KARTENSPIELE WERDEN NICHT SENKRECHT ZENTRIERT. Ihre Spalten werden
   laenger, sobald eine Karte angelegt wird -- und eine zentrierte Auslage
   rueckt bei jedem solchen Zug um einen halben Versatz nach oben. Das ganze
   Bild springt, obwohl sich nur unten etwas geaendert hat, und das Auge sucht
   die Karte, die es gerade noch im Blick hatte.

   Oben verankert waechst die Auslage nur nach unten, so wie sie es auf dem
   Tisch auch taete. Waagerecht bleibt sie mittig.

   Es trifft genau die drei Kartenspiele: ".brett" tragen FreeCell, Solitaer und
   Spider und sonst niemand. Deshalb steht die Bedingung hier und nicht als
   Liste von Spielarten -- ein neues Brett, das nach unten waechst, bekommt die
   Regel mit, sobald es diese Klasse traegt.

   Kennt ein Browser ":has" nicht, greift die Regel nicht und es bleibt beim
   Zentrieren -- also beim alten Verhalten und nicht bei einem kaputten. */
.pur__flaeche:has(.brett) {
    align-items: start;
    justify-items: center;
}

/* Die Leiste traegt wenige Knoepfe und soll so wenig Hoehe kosten wie moeglich
   -- jeder Millimeter hier fehlt dem Brett. */
.pur__leiste {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.5rem 0.7rem;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(0, 0, 0, 0.22);
}

/* Auf einem Telefon im Hochformat brach diese Leiste am 22.08.2026 auf drei
   Zeilen um und wurde 136 Bildpunkte hoch -- ein Sechstel des Schirms, und
   zwar genau das Sechstel, das dem Brett fehlt. Seit die Kacheln hierher
   fuehren, traegt sie neun Knoepfe: zurueck, die Knoepfe des Spiels, Neu
   starten, Neues Spiel, Grad, Hiscores, Anleitung, Vollbild.

   Eine Zeile mit Schiebebalken statt drei Zeilen. Dieselbe Entscheidung wie
   bei der Partieleiste und aus demselben Grund: bei einem Brett, das
   quadratisch ist, ist die Hoehe der Engpass, und ein Schiebebalken kostet
   keine. */
@media (max-width: 34rem) {
    .pur__leiste {
        flex-wrap: nowrap;
        justify-content: flex-start;
        overflow-x: auto;
        overflow-y: hidden;
        gap: 0.4rem;
        padding: 0.4rem 0.5rem;

        /* Damit die Knoepfe nicht zusammengequetscht werden, sondern
           herausragen und geschoben werden koennen. */
        scrollbar-width: none;
    }

    .pur__leiste::-webkit-scrollbar { display: none; }

    .pur__leiste > * {
        flex: 0 0 auto;
    }
}

/* --- Sudoku ------------------------------------------------------------- */

/* Gitter und Ziffernblock nebeneinander, aus demselben Grund wie bei der
   Wortsuche: das Gitter ist quadratisch, daneben ist Platz, darunter kostet es
   Hoehe. */
.sudoku {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: center;
    gap: clamp(0.6rem, 1.6vw, 1.4rem);
    width: 100%;
    height: 100%;
}

.sudoku__gitter {
    --blockbreite: 9.5rem;

    /* Was das Gitter neben den Feldern selbst braucht: acht Fugen zu einem
       Pixel und der zwei Pixel starke Rand auf beiden Seiten. Ohne diesen
       Abzug ist das Gitter zwoelf Pixel breiter als gerechnet -- auf einem
       breiten Schirm faellt das nicht auf, auf einem Telefon rollt es quer. */
    --gitterrahmen: 12px;

    /* Zoom aussen um die Schranken -- die Begruendung steht bei --karte-breite. */
    --sudokufeld: calc(clamp(
        22px,
        min((100cqw - var(--blockbreite) - var(--gitterrahmen)) / 9,
            (100cqh - var(--brett-umgebung) - var(--gitterrahmen)) / 9),
        58px) * var(--zoom, 1));

    display: grid;
    grid-template-columns: repeat(9, var(--sudokufeld));
    grid-auto-rows: var(--sudokufeld);
    background: rgba(255, 255, 255, 0.14);
    border: 2px solid rgba(255, 255, 255, 0.3);
    gap: 1px;
}

.sudoku__feld {
    appearance: none;
    padding: 0;
    border: 0;
    background: var(--ton-brett);
    color: var(--ton-gueltig);
    font-family: inherit;
    font-size: calc(var(--sudokufeld) * 0.56);
    font-weight: 600;
    line-height: 1;
    display: grid;
    place-items: center;
    cursor: pointer;
    user-select: none;
    -webkit-touch-callout: none;
}

.sudoku__feld:disabled { cursor: default; }

/* Die dickeren Linien zwischen den Bloecken -- ohne sie waere es ein Gitter aus
   einundachtzig Feldern und kein Sudoku. */
.sudoku__feld--blocklinks { box-shadow: inset 2px 0 0 rgba(255, 255, 255, 0.3); }
.sudoku__feld--blockoben { box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.3); }

.sudoku__feld--blocklinks.sudoku__feld--blockoben {
    box-shadow: inset 2px 0 0 rgba(255, 255, 255, 0.3),
                inset 0 2px 0 rgba(255, 255, 255, 0.3);
}

/* Vorgegebene Ziffern in Schriftfarbe, eigene in Gruen: so sieht man auf einen
   Blick, was man selbst verantwortet. */
.sudoku__feld--vorgabe {
    color: var(--ton-schrift);
    font-weight: 800;
    background: rgba(0, 0, 0, 0.22);
}

.sudoku__feld--gleich { background: rgba(87, 217, 138, 0.14); }

.sudoku__feld--gewaehlt {
    background: var(--ton-akzent-schwach);
    outline: 2px solid var(--ton-akzent);
    outline-offset: -2px;
    z-index: 1;
}

/* Der Widerspruch. Keine verratene Loesung -- nur dieselbe Ziffer zweimal in
   einer Einheit, was jeder selbst nachsehen koennte. */
.sudoku__feld--widerspruch {
    background: rgba(198, 40, 40, 0.3);
    color: #ff9f9f;
}

/* Die Notizen: drei mal drei winzige Ziffern an ihrem jeweiligen Platz. Die
   Stelle sagt mit, welche Ziffer gemeint ist -- eine Sieben steht immer unten
   links, ob sie notiert ist oder nicht. */
.sudoku__notizen {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    width: 100%;
    height: 100%;
    place-items: center;
    font-size: calc(var(--sudokufeld) * 0.24);
    font-weight: 500;
    color: var(--ton-schrift-leise);
    line-height: 1;
}

.ziffernblock {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.35rem;
    width: var(--blockbreite, 9.5rem);
}

.ziffernblock__taste {
    appearance: none;
    padding: 0.55rem 0;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 8px;
    background: var(--ton-brett);
    color: var(--ton-schrift);
    font-family: inherit;
    font-size: 1.3rem;
    font-weight: 700;
    cursor: pointer;
}

.ziffernblock__taste:disabled {
    opacity: 0.4;
    cursor: default;
}

/* Eine Ziffer, die schon neunmal steht, ist erledigt. Blass statt weg: der
   Platz soll nicht wandern, waehrend man tippt. */
.ziffernblock__taste--fertig {
    opacity: 0.35;
    text-decoration: line-through;
}

.ziffernblock__taste--weit {
    grid-column: 1 / -1;
    font-size: 0.9rem;
    font-weight: 600;
}

/* --- Wortsuche ---------------------------------------------------------- */

/* Gitter und Wortliste nebeneinander. Die Liste ist schmal und hoch, das Gitter
   quadratisch -- untereinander kostete das Hoehe, und Hoehe ist bei einem
   Brettspiel immer das, was fehlt. Erst wenn es wirklich zu schmal wird,
   rutscht die Liste darunter. */
.wortsuche {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: center;
    gap: clamp(0.6rem, 1.6vw, 1.4rem);
    width: 100%;
    height: 100%;
}

/* Die Buchstabenfelder sind quadratisch, deshalb rechnet die Breite gegen
   dieselbe Groesse wie die Hoehe. Von der Breite geht ab, was die Wortliste
   daneben braucht -- sonst waere das Gitter breiter als der Platz, sobald die
   Liste danebensteht. */
.wortsuche__gitter {
    --spalt-feld: clamp(2px, 0.4vw, 6px);
    --feld-klein: 18px;
    --feld-gross: 46px;
    --listenbreite: 11rem;

    /* Zoom aussen um die Schranken -- die Begruendung steht bei --karte-breite. */
    --wortfeld: calc(clamp(
        var(--feld-klein),
        min(
            (100cqw - var(--listenbreite) - (var(--spalten) - 1) * var(--spalt-feld))
                / var(--spalten),
            (100cqh - var(--brett-umgebung) - (var(--zeilen) - 1) * var(--spalt-feld))
                / var(--zeilen)),
        var(--feld-gross)) * var(--zoom, 1));

    display: grid;
    grid-template-columns: repeat(var(--spalten), var(--wortfeld));
    grid-auto-rows: var(--wortfeld);
    gap: var(--spalt-feld);
    justify-content: center;
}

.wortsuche__feld {
    appearance: none;
    padding: 0;
    border: 0;
    border-radius: calc(var(--wortfeld) * 0.16);
    background: var(--ton-brett);
    color: var(--ton-schrift);
    font-family: inherit;
    font-size: calc(var(--wortfeld) * 0.56);
    font-weight: 600;
    line-height: 1;
    display: grid;
    place-items: center;
    cursor: pointer;
    user-select: none;
    -webkit-touch-callout: none;
    transition: background 0.12s ease, color 0.12s ease;
}

.wortsuche__feld:disabled {
    cursor: default;
}

.wortsuche__feld--gefunden {
    background: rgba(87, 217, 138, 0.22);
    color: var(--ton-gueltig);
    font-weight: 800;
}

/* Der erste angetippte Buchstabe. Kraeftig, weil er die einzige Erinnerung
   daran ist, wo man gerade angefangen hat. */
.wortsuche__feld--gewaehlt {
    background: var(--ton-akzent);
    color: #1b1405;
    font-weight: 800;
}

/* Die Wortliste. Mehrspaltig, damit sie bei sechzehn Woertern nicht laenger
   wird als das Gitter daneben hoch ist. */
.wortliste {
    list-style: none;
    margin: 0;
    padding: 0;
    width: var(--listenbreite, 11rem);
    max-height: 100%;
    columns: 2;
    column-gap: 0.8rem;
    font-size: 0.82rem;
    letter-spacing: 0.02em;
}

.wortliste__wort {
    padding: 0.1rem 0;
    break-inside: avoid;
    color: var(--ton-schrift);
}

/* Durchgestrichen und blass: gefunden ist erledigt, soll aber lesbar bleiben --
   wer nachzaehlen will, was noch fehlt, braucht beides nebeneinander. */
.wortliste__wort--gefunden {
    color: var(--ton-schrift-leise);
    text-decoration: line-through;
}

.memory {
    --karte-seite: 1.35;
    --spalt-karte: clamp(4px, 0.8vw, 10px);
    --karte-klein: 34px;
    --karte-gross: 106px;

    /* Zoom aussen um die Schranken -- die Begruendung steht bei --karte-breite. */
    --memory-karte: calc(clamp(
        var(--karte-klein),
        min(
            (100cqw - (var(--spalten) - 1) * var(--spalt-karte)) / var(--spalten),
            (100cqh - var(--brett-umgebung) - (var(--zeilen) - 1) * var(--spalt-karte))
                / var(--zeilen) / var(--karte-seite)),
        var(--karte-gross)) * var(--zoom, 1));

    display: grid;
    grid-template-columns: repeat(var(--spalten), var(--memory-karte));
    grid-auto-rows: calc(var(--memory-karte) * var(--karte-seite));
    gap: var(--spalt-karte);
    justify-content: center;

    overflow-x: auto;
    padding-bottom: 0.4rem;
}

.memory__karte {
    appearance: none;
    padding: 0;
    border: 0;
    border-radius: calc(var(--memory-karte) * 0.1);
    display: grid;
    place-items: center;
    font-family: inherit;
    cursor: pointer;
    user-select: none;
    -webkit-touch-callout: none;
    touch-action: manipulation;

    /* Der Wechsel zwischen Ruecken und Motiv. Kein Umklappen in 3D: das sieht
       auf einem Feld mit achtundvierzig Karten unruhig aus, und auf schwachen
       Geraeten ruckelt es. */
    transition: background 0.14s ease, transform 0.14s ease;
}

.memory__karte:disabled {
    cursor: default;
}

.memory__karte--verdeckt {
    background: linear-gradient(160deg, #2f6f54 0%, #1f503b 100%);
}

.memory__karte--verdeckt:hover:not(:disabled) {
    transform: translateY(-2px);
}

.memory__ruecken {
    font-size: calc(var(--memory-karte) * 0.3);
    font-weight: 800;
    letter-spacing: 0.04em;
    color: rgba(255, 255, 255, 0.28);
}

.memory__karte--offen {
    background: linear-gradient(180deg, #ffffff 0%, #f2f4f6 100%);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}

/* Das nicht passende Paar, solange es zum Ansehen liegen bleibt. */
.memory__karte--daneben {
    box-shadow: 0 0 0 2px var(--ton-rot), 0 1px 3px rgba(0, 0, 0, 0.45);
}

.memory__karte--gefunden {
    background: rgba(87, 217, 138, 0.16);
    box-shadow: inset 0 0 0 1px rgba(87, 217, 138, 0.5);
}

/* Bild oben, Name darunter. Bei den Flaggen ist der Name der lehrreiche Teil
   und darf deshalb nicht wegfallen, wenn es eng wird -- die Flagge gibt lieber
   Höhe ab. */
.memory__motiv {
    display: grid;
    grid-template-rows: 1fr auto;
    align-items: center;
    justify-items: center;
    gap: calc(var(--memory-karte) * 0.05);
    width: 100%;
    height: 100%;
    padding: calc(var(--memory-karte) * 0.08);
}

/* Ein Satz ohne Namen -- Formen etwa -- bekommt die Zeile darunter nicht als
   leeren Streifen vererbt, sondern die ganze Karte fuer das Bild. */
.memory__motiv--nurbild {
    grid-template-rows: 1fr;
}

/* Eine Form fuellt die Karte staerker aus als eine Flagge: sie hat keine
   Beschriftung neben sich und kein Seitenverhaeltnis, das sie mitbringt. */
.motivform {
    width: auto;
    height: 100%;
    max-width: 100%;
    aspect-ratio: 1;
}

.flagge {
    display: block;
    width: 100%;
    height: auto;
    max-height: 100%;
    border-radius: 2px;
}

/* Lange Namen -- Bangladesch, Niederlande -- muessen auf eine schmale Karte
   passen. Umbruch statt Abschneiden: der halbe Name hilft niemandem. */
.memory__name {
    font-size: max(8px, calc(var(--memory-karte) * 0.15));
    font-weight: 700;
    line-height: 1.1;
    text-align: center;
    color: var(--ton-schwarz);
    hyphens: auto;
    overflow-wrap: anywhere;
}

/* Ein gefundenes Paar liegt auf gruenem Grund statt auf Weiss. */
.memory__karte--gefunden .memory__name {
    color: var(--ton-schrift);
}

/* --- Ergebnis einer Partie --------------------------------------------- */

/* Derselbe Bau wie die Anleitung, deshalb dieselbe Begruendung fuer
   "position: fixed": der Dialog steht im Seitenfluss und wuerde sonst als
   Flex- oder Rasterelement zusammengedrueckt.

   Der Unterschied zur Anleitung ist der Anlass. Die oeffnet der Spieler, dieser
   hier oeffnet sich selbst -- und genau deshalb darf er unter keinen Umstaenden
   Platz im Fluss beanspruchen: er erscheint in dem Moment, in dem die letzte
   Karte faellt. Vorher stand hier ein Kasten unter dem Brett, der die ganze
   Seite nach oben schob. */
.schirm {
    position: fixed;
    inset: 0;
    height: fit-content;
    margin: auto;

    width: min(30rem, calc(100vw - 2rem));
    padding: 0;
    border: 1px solid rgba(87, 217, 138, 0.5);
    border-radius: 14px;
    background: #16302a;
    color: var(--ton-schrift);
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6);
    overflow: hidden;
}

/* Eine nicht gewertete Einreichung ist kein Erfolg und soll auch nicht so
   aussehen. */
.schirm--fehler {
    border-color: rgba(198, 40, 40, 0.75);
}

/* Eine Sackgasse oder eine getretene Mine ist beides nicht: nichts ist kaputt,
   es geht nur nicht vorwaerts. Das Bernstein der Hinweiskaesten sagt das schon
   ueberall sonst in der App. */
.schirm--hinweis {
    border-color: rgba(242, 181, 68, 0.6);
}

/* Waehrend etwas laeuft, gibt es nichts zu entscheiden -- der Schirm bleibt
   unauffaellig und geht von selbst wieder weg. */
.schirm--arbeit {
    border-color: rgba(255, 255, 255, 0.18);
}

.schirm::backdrop {
    background: rgba(3, 12, 9, 0.66);
    backdrop-filter: blur(3px);
}

.schirm__kopf {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1rem 1.3rem 0.8rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.09);
}

.schirm__titel {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 700;
}

.schirm__schliessen {
    appearance: none;
    margin-left: auto;
    border: 0;
    background: transparent;
    color: var(--ton-schrift-leise);
    font-size: 1.1rem;
    line-height: 1;
    padding: 0.3rem 0.4rem;
    border-radius: 7px;
    cursor: pointer;
}

.schirm__schliessen:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--ton-schrift);
}

.schirm__inhalt {
    padding: 0.9rem 1.3rem 1.2rem;
    line-height: 1.55;
}

.schirm__inhalt p {
    margin: 0 0 0.8rem;
}

.schirm__inhalt p:last-child {
    margin-bottom: 0;
}

/* --- Das Ergebnis im Schirm ---

   Die Knoepfe standen frueher als Fliesstext in einem Absatz: vier Stueck mit
   vier verschiedenen Wortlaengen brachen dann irgendwo um, und die zweite
   Zeile stand kuerzer da als die erste. Jetzt ein Raster aus gleich breiten
   Zellen -- vier nebeneinander, wo es passt, sonst zwei mal zwei, auf dem
   Telefon untereinander. Symmetrisch ist es in jeder dieser Formen. */
.schirm__knoepfe {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
    gap: 0.5rem;
    margin-top: 1rem;
}

.schirm__knoepfe .knopf {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 2.5rem;
    padding: 0.45rem 0.7rem;
    text-align: center;
}

/* Die Zahlen als Felder statt als Satz: Punkte, Zeit, Platz stehen
   nebeneinander und sind auf einen Blick zu finden. */
.ergebniswerte {
    display: grid;

    /* Schmal genug, dass auch drei Felder auf einem Telefon in eine Zeile
       passen. Bei sechs Zentimetern brachen sie dort zu zwei plus eins um --
       und ein einzelnes Feld unter zweien ist genau die Unsymmetrie, um die es
       hier geht. */
    grid-template-columns: repeat(auto-fit, minmax(4.6rem, 1fr));
    gap: 0.5rem;
}

.wertfeld {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
    min-height: 4.4rem;
    padding: 0.6rem 0.4rem;
    border: 1px solid rgba(255, 255, 255, 0.09);
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.04);
    text-align: center;
}

.wertfeld__zahl {
    font-size: 1.5rem;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -0.01em;

    /* Ziffern gleicher Breite: sonst stehen 08:09 und 11:11 verschieden weit
       aus der Mitte, und drei Felder nebeneinander wirken schief. */
    font-variant-numeric: tabular-nums;
}

/* Der Wert, nach dem gewertet wird, bekommt die Akzentfarbe. Bei Kniffel und
   Nadelstich sind das die Punkte, bei Mahjong die Zeit. */
.wertfeld--gut .wertfeld__zahl {
    color: var(--ton-akzent);
}

.wertfeld__wort {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ton-schrift-leise);
}

/* Was nach den Feldern noch zu sagen bleibt -- abgezogene Pause, ein Wort zum
   Duell. Leiser als die Zahlen, damit es sie nicht ueberdeckt. */
.schirm__notiz {
    margin: 0.8rem 0 0;
    font-size: 0.88rem;
    color: var(--ton-schrift-leise);
}

/* --- Fehlerleiste von Blazor ------------------------------------------- */

#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    padding: 0.7rem 1.2rem;
    background: #ffd88a;
    color: #2a1c00;
    box-shadow: 0 -1px 8px rgba(0, 0, 0, 0.4);
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.9rem;
    top: 0.6rem;
}

/* --- Bausteine der Seitentafel ----------------------------------------- */

.tafel__rubrik {
    margin: 0.9rem 0 0.4rem;
    font-size: 0.62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.11em;
    color: var(--ton-schrift-leise);
}

.tafel__rubrik:first-child {
    margin-top: 0;
}

.tafel__weg {
    display: inline-block;
    margin-top: 0.6rem;
    font-size: 0.82rem;
    color: var(--ton-akzent);
    text-decoration: none;
}

.tafel__weg:hover {
    text-decoration: underline;
}

/* Das Zeichen vor dem Spielnamen in der Tafel -- dasselbe wie auf der Kachel. */
.spielwahl__zeichen {
    display: inline-block;
    width: 1.1rem;
    margin-right: 0.45rem;
    text-align: center;
}

/* Wer heute vorn liegt. Drei Zeilen, mehr braucht es neben dem Brett nicht --
   die ganze Liste ist einen Klick entfernt. */
.spitzenliste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.spitzenliste__zeile {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    padding: 0.35rem 0.5rem;
    border-radius: 8px;
    font-size: 0.86rem;
}

.spitzenliste__zeile--ich {
    background: rgba(242, 181, 68, 0.14);
}

.spitzenliste__platz {
    width: 1rem;
    color: var(--ton-schrift-leise);
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
}

.spitzenliste__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.spitzenliste__wert {
    margin-left: auto;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--ton-akzent);
}

/* Die Tageswahl der Bestenliste: zwei Pfeile und das Datum dazwischen. */
.tagwahl {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.tagwahl__wert {
    flex: 1;
    text-align: center;
    font-size: 0.86rem;
    font-variant-numeric: tabular-nums;
}

.tagwahl .knopf {
    padding: 0.3rem 0.6rem;
}

/* Ein Knopf in der Tafel steht fuer sich, nicht in der Reihe der Auswahl. */
.tafel__knopf {
    margin: 0.9rem 0 0;
}

.tafel__hinweis {
    margin: 0.6rem 0 0;
    font-size: 0.76rem;
    line-height: 1.45;
    color: var(--ton-schrift-leise);
}

/* --- Duelle --------------------------------------------------------------

   Ein Duell ist eine Karte und keine Tabellenzeile: was darauf steht, ist je
   nach Stand voellig verschieden -- mal zwei Knoepfe, mal zwei Werte
   nebeneinander, mal ein Satz. Eine Tabelle mit lauter leeren Zellen waere
   dasselbe in unleserlich. */

.duelle {
    max-width: 60rem;
}

.duellreihe {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 0.7rem;
    margin-bottom: 0.4rem;
}

.duellkarte {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.7rem 0.8rem 0.8rem;
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.035);
}

/* Wer dran ist, sieht es an der Kante -- ohne den Text lesen zu muessen. */
.duellkarte--offen {
    border-color: var(--ton-akzent);
    background: var(--ton-akzent-schwach);
}

.duellkarte--verfallen,
.duellkarte--abgelehnt {
    opacity: 0.62;
}

.duellkarte__kopf {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
}

.duellkarte__gegner {
    font-weight: 700;
}

.duellkarte__marke {
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ton-schrift-leise);
}

.duellkarte__spiel {
    margin: 0;
    font-size: 0.86rem;
}

.duellkarte__grad,
.duellkopf__grad {
    margin-left: 0.4rem;
    font-size: 0.74rem;
    color: var(--ton-schrift-leise);
}

.duellkarte__lage {
    margin: 0;
    font-size: 0.78rem;
    line-height: 1.4;
    color: var(--ton-schrift-leise);
}

/* --- Kniffel --------------------------------------------------------------

   Zwei Dinge mit verschiedener Aufgabe und deshalb mit verschiedenem Aussehen:
   der Block ist Papier, der Wuerfeltisch ist Tisch. Beim echten Spiel liegen
   Zettel und Becher auch nebeneinander und sind nicht dasselbe -- und man
   verwechselt sie keine Sekunde.

   Die Zahlen im Block stehen in einer Schreibschrift, so wie man sie
   hineinschreiben wuerde. Aus dem System und nicht nachgeladen: eine
   Schriftdatei waere ein Netzabruf, eine Lizenzfrage und ein Grund, warum die
   Seite ohne Verbindung anders aussieht. Wo es keine Schreibschrift gibt,
   nimmt der Browser die naechste -- lesbar bleibt es immer. */

/* KNIFFEL ZOOMT ANDERS ALS DIE UEBRIGEN BRETTER, und zwar aus einem Grund.

   Die anderen rechnen ihre Stueckgroesse aus der Buehne aus; dort geht der
   Zoom als Faktor in die Rechnung ein, und das Brett baut sich neu auf. Der
   Kniffelblock ist dagegen ein Schriftstueck: eine Tabelle mit Zeilenhoehen
   und Schriftgroessen in rem, die nichts von der Buehne wissen. Ihn ueber die
   Schriftgroesse zu skalieren hiesse, jede dieser Angaben auf em umzustellen
   -- viel Arbeit fuer ein Blatt, das ohnehin eine feste Gestalt hat.

   "zoom" ist genau dafuer gemacht: Es skaliert ein Stueck Dokument samt
   Umbruch, statt ein fertiges Bild zu dehnen. Der Block bleibt scharf, und
   verkleinert passt mehr davon ins Querformat -- was hier gebraucht wird. */
.kniffel {
    zoom: var(--zoom, 1);

    --papier: #f2e9d5;
    --papier-linie: rgba(120, 95, 60, 0.09);
    --papier-schrift: #1f3b2c;
    --tinte: #2a4a94;
    --rotstift: #b8442c;

    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    padding: 0.3rem 0.3rem 0.8rem;
    width: 100%;

    /* Schreibschrift, wo es eine gibt. Die Reihenfolge geht von der besten
       zur haeufigsten: Windows, Apple, dann was uebrig bleibt. */
    --hand: "Segoe Script", "Bradley Hand", "Snell Roundhand", "Apple Chancery",
            "Comic Sans MS", cursive;
}

/* --- Der Block ---------------------------------------------------------- */

.kniffelblock {
    width: 100%;
    max-width: 62rem;
    padding: 1.1rem 1.4rem 1.3rem;
    border-radius: 6px;
    color: var(--papier-schrift);

    /* Papier: warmer Grundton mit sehr feinen senkrechten Fasern und einem
       Schatten, der es vom dunklen Grund abhebt. */
    background:
        repeating-linear-gradient(90deg,
            transparent 0 3px,
            var(--papier-linie) 3px 4px),
        linear-gradient(160deg, #f6eeda 0%, var(--papier) 45%, #ebe0c8 100%);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35), 0 2px 0 rgba(0, 0, 0, 0.2);
}

.kniffelblock__kopf {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1rem;
}

.kniffelblock__titel {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    white-space: nowrap;
}

.kniffelblock__untertitel {
    margin: 0.1rem 0 0;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(31, 59, 44, 0.55);
}

/* Das Rundenschild bleibt, wie es ist. Ohne "nowrap" brach "Runde 10 / 13" auf
   dem Telefon in zwei Zeilen um -- das Schild wurde hoeher, der Blockkopf mit
   ihm, und der ganze Block sprang beim Uebergang von der neunten zur zehnten
   Runde um eine Zeilenhoehe nach unten. Die feste Breite der Zahl haelt
   zusaetzlich den Zeitpunkt fest, an dem aus einer Ziffer zwei werden. */
.kniffelblock__runde {
    display: flex;
    flex: none;
    align-items: center;
    gap: 0.7rem;
    padding: 0.35rem 0.9rem;
    border: 1px solid rgba(31, 59, 44, 0.28);
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.4);
    white-space: nowrap;
}

.kniffelblock__rundenwort {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: rgba(31, 59, 44, 0.6);
}

.kniffelblock__rundenzahl {
    display: inline-block;
    min-width: 3.4em;
    text-align: right;
    font-family: var(--hand);
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--tinte);
    white-space: nowrap;
}

.kniffelblock__rundenstrich {
    color: rgba(31, 59, 44, 0.4);
}

/* Zwei Spalten, solange zwanzig Zentimeter hineinpassen -- sonst eine.

   Das "min(...)" ist noetig und keine Vorsicht: minmax(20rem, 1fr) schrumpft
   nie unter zwanzig Zentimeter, und auf einem schmalen Schirm stand die Spalte
   dann breiter da als der Block, in dem sie liegt. */
.kniffelblock__spalten {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
    gap: 0.4rem 3rem;
}

/* Die Rubrik mit einer Linie, die den Rest der Spalte ausfuellt -- so wie eine
   Ueberschrift auf einem Formular. */
.kniffelblock__rubrik {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    margin: 0.2rem 0 0.5rem;
    font-size: 0.66rem;
    font-weight: 800;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--rotstift);
}

.kniffelblock__rubrik::after {
    content: "";
    flex: 1;
    height: 1px;
    background: rgba(184, 68, 44, 0.3);
}

/* --- Eine Zeile --------------------------------------------------------- */

/* Nur fuer Vorlesegeraete: was ein Zeichen bedeutet, das man nur sehen kann. */
.nurvorleser {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Feste Zeilenhoehe. Der Kasten am Ende wechselt zwischen Knopf, Zahl, Kreuz
   und leerem Feld -- ohne diese Hoehe waechst und schrumpft die Zeile dabei,
   und der ganze Block darunter rutscht. */
.kniffelzeile {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.34rem 0;
    min-height: 2.6rem;
}

.kniffelzeile__name {
    font-size: 1rem;
    font-weight: 700;
    white-space: nowrap;
}

.kniffelzeile__name--kniffel {
    color: var(--rotstift);
}

.kniffelzeile__bedingung {
    font-size: 0.72rem;
    color: rgba(31, 59, 44, 0.5);
    white-space: nowrap;
}

/* Die Fuehrungslinie zwischen Name und Kasten. Kein Zierrat: sie fuehrt das
   Auge ueber die Luecke, auf einem Papierblock steht sie aus demselben Grund. */
.kniffelzeile__linie {
    flex: 1;
    min-width: 1rem;
    height: 0;
    align-self: center;
    border-bottom: 1px dotted rgba(31, 59, 44, 0.32);
}

.kniffelzeile--belegt .kniffelzeile__name,
.kniffelzeile--belegt .kniffelzeile__bedingung {
    opacity: 0.55;
}

/* --- Der Kasten am Zeilenende ------------------------------------------- */

/* Ein Kasten, vier Zustaende, eine Groesse. Der Rahmen ist immer da -- wo
   keiner zu sehen sein soll, ist er durchsichtig statt weg, sonst waere die
   Zeile einen Pixel niedriger. */
.kniffelfeld {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: 3.5rem;
    height: 1.9rem;
    padding: 0 0.3rem;
    border: 1px solid transparent;
    border-radius: 3px;
    font-family: var(--hand);
    font-size: 1.2rem;
    font-weight: 700;
    text-align: center;
    line-height: 1;
}

/* Ein freies Feld ist ein Knopf: gestrichelt, weil dort noch nichts steht. */
.kniffelfeld--frei {
    border-style: dashed;
    border-color: rgba(184, 68, 44, 0.55);
    background: transparent;
    color: rgba(31, 59, 44, 0.55);
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}

.kniffelfeld--frei:hover:not(:disabled) {
    border-style: solid;
    border-color: var(--rotstift);
    background: rgba(184, 68, 44, 0.12);
    color: var(--rotstift);
}

/* Das Beste, was dieser Wurf hergibt. Ein Hinweis, keine Vorschrift -- oft ist
   es klueger, ein kleineres Feld zu nehmen und das grosse aufzuheben. */
.kniffelfeld--beste {
    border-style: solid;
    border-color: var(--rotstift);
    color: var(--rotstift);
}

/* Null Punkte sind eine gueltige Wahl, aber selten die gewollte. */
.kniffelfeld--leer {
    border-color: rgba(31, 59, 44, 0.25);
    color: rgba(31, 59, 44, 0.35);
}

/* Eingetragen: fester Kasten, Tinte, hell hinterlegt -- als waere es
   hineingeschrieben worden. */
.kniffelfeld--voll {
    border-color: rgba(31, 59, 44, 0.3);
    background: rgba(255, 255, 255, 0.75);
    color: var(--tinte);
}

/* Gestrichen: eingetragen, aber ohne Punkte. Das ist etwas anderes als eine
   Null -- es ist ein geopfertes Feld, und auf Papier macht man dafuer ein
   Kreuz. Rot, damit man beim Ueberfliegen sieht, was schiefging. */
.kniffelfeld--gestrichen {
    border-color: rgba(184, 68, 44, 0.45);
    background: rgba(184, 68, 44, 0.09);
    color: var(--rotstift);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 800;
}

/* Noch frei, aber es liegt kein Wurf da: ein leerer Kasten. Eine Null waere
   hier eine Auskunft ueber einen Wurf, den es nicht gibt. */
.kniffelfeld--wartet {
    border-style: dashed;
    border-color: rgba(31, 59, 44, 0.18);
}

/* Der Bonus ist kein Feld, das man waehlt -- er kommt von selbst. */
.kniffelfeld--rechnung {
    background: none;
    color: rgba(31, 59, 44, 0.5);
}

.kniffelfeld--gut {
    color: var(--rotstift);
}

/* --- Summen ------------------------------------------------------------- */

.kniffelblock__summe {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-top: 0.45rem;
    padding-top: 0.45rem;
    border-top: 1.5px solid rgba(31, 59, 44, 0.45);
}

.kniffelblock__summenwort {
    font-size: 1rem;
    font-weight: 800;
}

.kniffelblock__summenzahl {
    font-family: var(--hand);
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--tinte);
    padding-right: 0.75rem;
}

/* Die Endsumme bekommt einen eigenen Kasten. Sie ist das, worum es geht. */
.kniffelblock__gesamt {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-top: 0.7rem;
    padding: 0.5rem 0.9rem;
    border: 1px solid rgba(31, 59, 44, 0.35);
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.35);
}

.kniffelblock__gesamtwort {
    font-size: 1.15rem;
    font-weight: 800;
}

.kniffelblock__gesamtzahl {
    font-family: var(--hand);
    font-size: 1.9rem;
    font-weight: 700;
    color: var(--rotstift);
}

/* --- Der Wuerfeltisch --------------------------------------------------- */

.wuerfeltisch {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 2rem;
    flex-wrap: wrap;
    width: 100%;
    max-width: 62rem;
    padding: 1rem 1.4rem 1.1rem;
    border-radius: 14px;
    border: 1px solid rgba(255, 255, 255, 0.07);
    background:
        radial-gradient(ellipse at 50% 0%, rgba(255, 255, 255, 0.045), transparent 70%),
        rgba(0, 0, 0, 0.22);
}

.wuerfeltisch__wuerfel {
    display: flex;
    gap: 0.7rem;
    flex: 0 1 auto;
    min-width: 0;
}

/* Unter jedem Wuerfel dieselbe Zeile, damit die Reihe beim Auswaehlen nicht
   springt: entweder das Wort oder ein Punkt.

   Die Breite haengt hier und nicht am Wuerfel. Das ist kein Geschmack: der
   Platz ist eine Spalte, und ein flex-basis am Wuerfel darin bestimmt seine
   Hoehe. Die Breite kam dann aus dem Seitenverhaeltnis -- fuer die Reihe
   darueber zaehlte aber weiter der schmale Inhalt, und die Wuerfel lagen
   uebereinander. */
.wuerfelplatz {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;

    /* Viereinhalb Zentimeter, wenn Platz ist -- sonst so viel, wie hineingeht.

       Die Breite steht ausdruecklich da und nicht nur als flex-basis: der
       Wuerfel darin ist hundert Prozent breit, und ohne feste Bezugsgroesse
       fragt er den Platz, waehrend der Platz seinen Inhalt fragt. Beim Ausgang
       dieses Zirkels blieb die Breite des Punktes darunter uebrig -- neunzehn
       Pixel, und die Wuerfel waren Konfetti. */
    flex: 0 1 4.4rem;
    width: 4.4rem;
    min-width: 0;
}

.wuerfelplatz__vermerk {
    font-size: 0.58rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.22);
    line-height: 1;
}

.wuerfelplatz__vermerk--liegt {
    color: var(--ton-akzent);
}

.wuerfel {
    position: relative;

    /* Der Wuerfel fuellt seinen Platz und bleibt dabei quadratisch. Wie breit
       der Platz ist, entscheidet die Reihe darueber -- siehe .wuerfelplatz. */
    width: 100%;
    aspect-ratio: 1;
    height: auto;
    flex: none;

    padding: 0.5rem;
    border-radius: 12px;
    border: none;
    background: linear-gradient(160deg, #fdfbf3 0%, #f0ebdc 55%, #e2dbc8 100%);
    box-shadow:
        0 3px 0 rgba(0, 0, 0, 0.3),
        0 7px 16px rgba(0, 0, 0, 0.38),
        inset 0 1px 0 rgba(255, 255, 255, 0.9);
    cursor: pointer;
    transition: transform 0.14s ease, box-shadow 0.14s ease;
}

.wuerfel:hover:not(:disabled) {
    transform: translateY(-0.12rem);
}

.wuerfel:disabled {
    cursor: default;
    filter: saturate(0.75) brightness(0.9);
}

/* Noch nicht geworfen: der Wuerfel liegt im Becher. Ein blasser Umriss statt
   einer leeren weissen Flaeche -- so ist zu sehen, dass dort etwas hingehoert,
   ohne dass es nach einer Wuerfelseite ohne Augen aussieht. */
.wuerfel--leer {
    background: rgba(255, 255, 255, 0.05);
    border: 2px dashed rgba(255, 255, 255, 0.18);
    box-shadow: none;
}

.wuerfel--leer:hover {
    transform: none;
}

/* Liegenbleiben ist eine Entscheidung und soll auch so aussehen. */
.wuerfel--bleibt {
    transform: translateY(-0.3rem);
    box-shadow:
        0 0 0 3px var(--ton-akzent),
        0 5px 0 rgba(0, 0, 0, 0.3),
        0 11px 18px rgba(0, 0, 0, 0.4),
        inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

.wuerfel--bleibt:hover:not(:disabled) {
    transform: translateY(-0.42rem);
}

.wuerfel__flaeche {
    display: grid;
    width: 100%;
    height: 100%;
    grid-template-areas:
        "a1 a2 a3"
        "a4 a5 a6"
        "a7 a8 a9";
    gap: 0.08rem;
}

/* Die Augen in Prozent der Rasterzelle und nicht in Zentimetern: so schrumpfen
   sie mit dem Wuerfel mit. */
.wuerfel__auge {
    align-self: center;
    justify-self: center;
    width: 62%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: #1d2a22;
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.55);
}

/* Der Wurf. Die Zwischenbilder liefert die Komponente; hier kommt die Bewegung
   dazu, die sie zu einem Wurf macht.

   Wer Bewegung abbestellt hat, bekommt sie nicht -- die Zwischenbilder bleiben,
   sie sind die eigentliche Auskunft. */
@media (prefers-reduced-motion: no-preference) {
    .wuerfel--rollt {
        animation: wuerfelwurf 0.21s linear infinite;
    }
}

@keyframes wuerfelwurf {
    0%   { transform: translateY(0) rotate(0deg); }
    25%  { transform: translateY(-0.5rem) rotate(-9deg); }
    50%  { transform: translateY(0.1rem) rotate(6deg); }
    75%  { transform: translateY(-0.3rem) rotate(-4deg); }
    100% { transform: translateY(0) rotate(0deg); }
}

/* --- Wurfknopf und Hinweis ---------------------------------------------- */

/* Feste Hoehe: am Ende der Partie steht hier ein einzelner Satz statt Knopf,
   Wurfpunkten und Hinweis. Ohne sie schrumpfte der Tisch im letzten Zug. */
.wuerfeltisch__aktion {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    flex: 0 1 16rem;
    min-height: 6.4rem;
}

/* Der Zug dieses Spiels ist das Wuerfeln, und so sieht der Knopf auch aus. Die
   Aufschrift bleibt dieselbe -- wie viele fliegen, sagt der Hinweis darunter;
   ein Wort, das sich bei jeder Auswahl aendert, muss man jedes Mal neu lesen. */
.wurfknopf {
    width: 100%;
    min-width: 11rem;
    padding: 0.62rem 1.4rem;
    border-radius: 10px;
    border: 1px solid #e8b34a;
    background: linear-gradient(180deg, #f7c95f 0%, #e9ad33 100%);
    color: #3a2a06;
    font: inherit;
    font-size: 1.1rem;
    font-weight: 800;
    letter-spacing: 0.01em;
    cursor: pointer;
    transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease;
    box-shadow: 0 3px 0 rgba(0, 0, 0, 0.32), 0 8px 16px rgba(0, 0, 0, 0.3);
}

.wurfknopf:hover:not(:disabled) {
    transform: translateY(-0.1rem);
    box-shadow: 0 4px 0 rgba(0, 0, 0, 0.32), 0 11px 20px rgba(0, 0, 0, 0.34);
}

.wurfknopf:active:not(:disabled) {
    transform: translateY(0.12rem);
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.32);
}

.wurfknopf:disabled {
    cursor: default;
    filter: grayscale(0.75) brightness(0.7);
    box-shadow: none;
}

.wurfpunkte {
    display: flex;
    gap: 0.3rem;
}

.wurfpunkt {
    width: 0.45rem;
    height: 0.45rem;
    border-radius: 50%;
    border: 1px solid rgba(242, 181, 68, 0.55);
}

.wurfpunkt--verbraucht {
    background: var(--ton-akzent);
    border-color: var(--ton-akzent);
}

/* Immer zwei Zeilen hoch, auch wenn nur eine dasteht. Der Text wechselt mit
   der Lage zwischen einer und zwei Zeilen, und der Tisch sprang dabei. */
.wurfhinweis {
    margin: 0;
    max-width: 15rem;
    min-height: 2.7em;
    font-size: 0.74rem;
    line-height: 1.35;
    text-align: center;
    color: var(--ton-schrift-leise);
}

.wuerfeltisch__fertig {
    margin: 0;
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--ton-akzent);
}

/* --- Schmale Schirme ---------------------------------------------------- */

@media (max-width: 640px) {
    .kniffelblock {
        padding: 0.8rem 0.9rem 1rem;
    }

    .kniffelblock__spalten {
        gap: 0 1.5rem;
    }

    /* Die Bedingung neben dem Namen kostet hier Breite, die die
       Fuehrungslinie braucht. Was ein Full House ist, steht in der Anleitung. */
    .kniffelzeile__bedingung {
        display: none;
    }

    .wuerfeltisch {
        gap: 1rem;
        padding: 0.8rem 0.7rem 0.9rem;
    }

    .wuerfeltisch__wuerfel {
        gap: 0.4rem;
    }

    .wuerfeltisch__aktion {
        flex: 1 1 100%;
    }
}


/* Die Marke in der Bestenliste: die vorgespielte Referenzpartie. Sie steht in
   der Liste, damit man sieht, was zu schlagen ist -- aber sie ist kein
   Mitspieler, und das soll man ihr ansehen. */
.tabelle__marke {
    color: var(--ton-schrift-leise);
}

.tabelle__marke td:first-child {
    color: var(--ton-akzent);
}

.markenvermerk {
    margin-left: 0.45rem;
    padding: 0.05rem 0.35rem;
    border-radius: 999px;
    border: 1px solid var(--ton-akzent-schwach);
    background: var(--ton-akzent-schwach);
    color: var(--ton-akzent);
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    white-space: nowrap;
}

/* Der Lösbarkeitsvorbehalt bei mehrfarbigem Spider. In der Akzentfarbe: er ist
   kein Fehler, aber er soll gelesen werden, bevor jemand antritt. */
.duellkarte__vorbehalt {
    margin: 0;
    font-size: 0.74rem;
    line-height: 1.4;
    color: var(--ton-akzent);
}

.duellkarte__knoepfe {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0.25rem 0 0;
}

.duellkarte__ausgang {
    margin: 0;
    font-weight: 700;
}

.duellkarte__ausgang--gewonnen {
    color: var(--ton-gueltig);
}

.duellkarte__ausgang--verloren {
    color: var(--ton-schrift-leise);
}

.duellkarte__werte {
    display: flex;
    gap: 1.2rem;
    margin: 0.15rem 0 0;
}

.duellkarte__wert {
    display: flex;
    flex-direction: column;
}

.duellkarte__zahl {
    font-size: 1.02rem;
    font-variant-numeric: tabular-nums;
}

.duellkarte__name {
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ton-schrift-leise);
}

/* Der Kopf des Duells in der Seitentafel, waehrend gespielt wird. */
.duellkopf__gegner {
    margin: 0;
    font-weight: 700;
}

.duellkopf__spiel {
    margin: 0.15rem 0 0;
    font-size: 0.86rem;
}

.duellkopf__frist {
    margin: 0.15rem 0 0;
    font-size: 0.78rem;
    color: var(--ton-akzent);
}

/* Die Zahl der offenen Duelle. Klein und rund, an der Kachel und im Menue. */
.kachel__abzeichen,
.spielwahl__abzeichen {
    display: inline-block;
    min-width: 1.15rem;
    padding: 0 0.3rem;
    border-radius: 999px;
    background: var(--ton-akzent);
    color: var(--ton-rahmen);
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1.15rem;
    text-align: center;
}

.kachel__abzeichen {
    margin-left: auto;
}

.spielwahl__abzeichen {
    margin-left: 0.4rem;
}

/* --- Schmale Schirme: die Spalte neben dem Brett wandert darunter -------- */

/* Wortsuche und Sudoku rechnen ihre Feldgroesse als "Breite minus Platz fuer
   die Spalte daneben". Auf einem Telefon bricht diese Spalte laengst darunter
   um -- der Abzug blieb aber stehen. Das Gitter verschenkte damit rund 180 px
   an eine Liste, die gar nicht mehr neben ihm stand: die Wortsuche stiess
   dadurch auf ihre Untergrenze von 18 px, und "leicht" wurde keinen Deut
   groesser als "mittel".
   
   Die Abfrage geht an den Container und nicht an das Fenster: dasselbe Brett
   steht einmal neben der Schiene und einmal ohne sie, und was zaehlt, ist der
   Platz, den es wirklich hat.
   
   Und sie steht am Ende der Datei, nicht bei den Brettern: die Grundregeln
   setzen dieselben Variablen mit derselben Spezifitaet, und dann gewinnt die
   spaetere. Weiter oben stand dieser Block wirkungslos da. */
@container (max-width: 640px) {
    .wortsuche__gitter { --listenbreite: 0rem; }
    .sudoku__gitter { --blockbreite: 0rem; }

    .wortliste {
        width: 100%;
        columns: 3;
    }

    /* Der Ziffernblock quer statt hoch: unter dem Gitter ist Breite da und
       Hoehe knapp -- genau umgekehrt als daneben. */
    .ziffernblock {
        width: 100%;
        max-width: 22rem;
        grid-template-columns: repeat(5, 1fr);
    }
}

/* ===================================================================
   Nadelstich -- die Karte und die Nadel

   Die Kartenblaetter kommen als fertiges SVG aus wwwroot/karten und
   tragen keine einzige Farbe: sie sind Daten. Wie sie aussehen, steht
   hier, damit es genau eine Stelle dafuer gibt.

   Die Karte ist das ganze Brett. Frage, Aufloesung und Knopf liegen als
   Schicht darauf und verbrauchen keine Hoehe. Der erste Anlauf stellte
   sie darueber und darunter -- die Buehne lief dann um gut zweihundert
   Bildpunkte ueber, und am Rechner stand eine Bildlaufleiste da, die
   nichts zu zeigen hatte.
   =================================================================== */

.nadelstich {
    display: grid;
    place-items: center;
    width: 100%;
    height: 100%;
    min-height: 0;
}

/* --- Das Kartenblatt --- */

/* DIE KARTE FUELLT DIE GANZE BUEHNE.

   Bis zum 22.08.2026 war sie so geformt wie der Spielausschnitt und stand als
   Rechteck in der Mitte. Was daneben blieb, war leere Buehne: am Rechner
   gemessen 199 Bildpunkte je Seite und ein Drittel der Flaeche, auf dem Telefon
   hochkant 222 oben und unten und drei Fuenftel.

   Der Ausschnitt behaelt sein Seitenverhaeltnis -- er ist der viewBox, und ein
   verzogener viewBox hiesse verzogene Laender. Er wird nur nicht mehr
   eingepasst, sondern mittig hineingelegt; "xMidYMid meet" tut genau das. In
   den Streifen daneben steht das Umland, das die Karte seither mitzeichnet:
   ein SVG beschneidet an seinem Element und nicht am viewBox, also ist alles
   zu sehen, was dort liegt. Siehe Schaurand im Kartenblatt.

   Dass die Mitte des viewBox die Mitte des Elements bleibt, haengt an "xMidYMid"
   -- und daran haengt das Fadenkreuz. Ein anderer Wert dort verschoebe das Ziel
   gegen den Stich. */
.nadelkarte {
    width: 100%;
    height: 100%;

    position: relative;
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 12px;
    background: #0b2233;

    /* Ohne das scrollt der Browser die Seite, sobald ein Finger die Karte
       beruehrt -- und die Nadel bliebe auf halbem Weg stehen. */
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;

    /* Eine offene Hand: die Karte laesst sich anfassen und schieben. Ein
       Fadenkreuz als Zeiger waere hier irrefuehrend -- gezielt wird mit
       dem Kreuz in der Mitte, nicht mit dem Mauszeiger. */
    cursor: grab;
}

.nadelkarte--schiebt {
    cursor: grabbing;
}

/* Wer mit der Tastatur hierherkommt, soll es sehen -- die Pfeiltasten
   schieben dann die Karte. */
.nadelkarte:focus-visible {
    outline: 2px solid var(--ton-akzent);
    outline-offset: 2px;
}

.nadelkarte--leer {
    display: grid;
    place-items: center;
    color: var(--ton-schrift-leise);
}

/* Das <svg> der Landkarte heisst "kartenblatt" und nicht "karte" -- der Name
   war schon vergeben. ".karte" ist die SPIELKARTE aus Solitaer und FreeCell:
   weisser Verlauf, Schlagschatten, abgerundete Ecken, "cursor: pointer". Das
   Landkarten-SVG trug dieselbe Klasse und erbte all das.

   Sichtbar wurde es dort, wo das Blatt den Ausschnitt nicht ausfuellt: beim
   Schieben ueber den Rand hinaus stand am Rand kein Meer, sondern eine
   weisse Flaeche -- die Spielkarte schien durch. Der falsche Zeiger kam
   dazu: ueber der Karte zeigte die Hand aufs Klicken statt aufs Schieben.

   UMBENANNT WURDE NUR DIE HUELLE, NICHT IHR INHALT. Die Klassen darin --
   "karte__meer", "karte__land", "karte__see", "karte__fluss" -- heissen
   weiter so, obwohl das neben "kartenblatt" schief aussieht. Der Grund ist
   handfest: sie stehen in "wwwroot/karten/*.svg", zusammen eine halbe
   Megabyte, die ein Browser lange behaelt. Diese Klasse der Aenderung geht
   nur auf, wenn Datei und Stilvorlage GLEICHZEITIG ankommen -- und genau das
   ist nicht garantiert.

   Am 21.08.2026 hat das eine schwarze Karte gekostet: die Stilvorlage kam
   frisch (sie traegt "no-cache"), das Blatt kam alt aus dem Zwischenspeicher.
   Alte Klassen, neue Regeln, also keine einzige Fuellung -- und der
   SVG-Standard fuer "fill" ist Schwarz. Ein Kollisionsproblem gab es bei
   diesen Namen ohnehin nie: die Spielkarte heisst "karte__bild". Nur die
   Huelle stiess sich.

   Merksatz: Klassennamen in lange zwischengespeicherten Dateien sind
   oeffentliche Schnittstellen. Umbenennen kostet dort mehr, als es einbringt. */
.nadelkarte .kartenblatt {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}

/* --- Die Farben der Karte ---

   Sie folgen absichtlich nicht der Palette der Anwendung. Eine Karte hat
   ihre eigene Sprache: Wasser ist blau, Land ist gruen, und beides muss
   sich auf einen Blick trennen lassen.

   GRENZE UND FLUSS. Vorher waren beide entsaettigte Mitteltoene in fast
   derselben Strichstaerke -- #5f8f75 gegen #43728f bei 0,75 gegen 0,9
   Bildpunkten. Auf einem Blatt von tausend Bildpunkten sah das gleich
   aus. Jetzt trennen sie drei Dinge zugleich: der Farbton (klares Gruen
   gegen klares Blau), die Saettigung und die Strichstaerke -- der Fluss
   ist fast doppelt so dick. Und wem das noch nicht reicht, der schaltet
   die Fluesse ab. */

.karte__meer { fill: #0b2233; }

/* Die Grenze ist dunkler als das Land, der Fluss heller. Damit trennen
   sie sich nicht nur im Farbton, sondern auch in der Helligkeit -- und
   die traegt auch dann, wenn jemand Gruen und Blau schlecht
   auseinanderhaelt. Mit einer hellen Grenze lag das Kontrastverhaeltnis
   zwischen beiden bei 1,15: praktisch gleich hell. */
.karte__land {
    fill: #356e52;
    stroke: rgba(8, 26, 18, 0.55);
    stroke-width: 0.7;
    vector-effect: non-scaling-stroke;
}

/* DAS UMLAND BEKOMMT KEINE GRENZEN. Zwei Gruende, und beide zaehlen.

   Der erste ist die Zeit. Ein Strich mit "non-scaling-stroke" wird bei jedem
   Bild neu in Bildschirmkoordinaten gelegt, und seine Kosten haengen an der
   Laenge des Umrisses, nicht an der Flaeche. Gemessen am 22.08.2026,
   verschraenkt ueber sechzig Runden auf 1259 x 725 Bildpunkten: mit Strich am
   Umland 10.7 Millisekunden je Bild, ohne 8.4 -- ein Fuenftel weniger, und im
   oberen Viertel der Bilder, also genau dort, wo Ruckeln entsteht, ein Drittel.

   Der zweite ist das Auge. Die Kulisse soll Kulisse bleiben. Ohne ihre
   Binnengrenzen liegt hinter dem Spielfeld eine ruhige Landmasse statt einer
   zweiten, gleich lauten Karte -- und der Ausschnitt, um den es geht, hebt
   sich von selbst ab.

   Ueber die Gruppe und nicht ueber eine eigene Klasse in der SVG: die Blaetter
   liegen lange im Zwischenspeicher, und eine Klasse, fuer die eine alte
   Stilvorlage keine Regel hat, faellt auf Schwarz zurueck. Am 21.08.2026 hat
   genau das eine schwarze Karte gekostet. So greift die Regel auch auf jedem
   Blatt, das schon im Browser liegt. */
.karte__umland .karte__land {
    stroke: none;
}

/* Die Grenzen der Bundeslaender. Es gibt sie nur auf dem Deutschlandblatt --
   auf der Europakarte waeren es zehntausend Linien.

   HELL, WO DIE LANDESGRENZE DUNKEL IST. Dieselbe Farbe in duenner waere bei
   jeder Zoomstufe eine Verwechslung; so trennen sie sich in der Helligkeit,
   und das traegt auch bei einer haarfeinen Linie. Blau kommt nicht in Frage,
   das gehoert dem Wasser: eine Landesgrenze folgt oft einem Fluss, und dann
   liegen beide uebereinander. */
.karte__grenze {
    fill: none;
    stroke: rgba(233, 246, 238, 0.34);
    stroke-width: 0.7;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
}

/* Seen sind Wasser und tragen deshalb den Rand der Fluesse -- sonst
   waeren sie Loecher im Land und nicht als Gewaesser zu erkennen. */
.karte__see {
    fill: #0b2233;
    stroke: rgba(87, 182, 232, 0.55);
    stroke-width: 0.8;
    vector-effect: non-scaling-stroke;
}

.karte__fluss {
    fill: none;
    stroke: #57b6e8;
    stroke-width: 1.3;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
}

/* Abschaltbar. Fluesse sind Orientierung und Zierde zugleich -- wer sie
   nicht braucht, bekommt eine ruhigere Karte. */
.kartenblatt--ohnefluesse .karte__fluss {
    display: none;
}

/* --- Die Karte als Schaltflaeche: das Laenderquiz ---------------------

   Dort ist die Antwort kein Punkt, sondern ein Umriss. Zwei Dinge muessen
   dafuer stimmen, und beide haengen an derselben Zeile.

   ERSTENS: was ueber den Laendern liegt, darf keine Zeiger fangen. Seen,
   Fluesse, Binnengrenzen und der Massstabsbalken liegen in der Datei ueber
   der Laendergruppe; ohne diese Regel traefe ein Tipp auf den Bodensee
   keines der drei Laender darum herum, und der Genfersee waere ein Loch im
   Spielfeld.

   ZWEITENS haengt daran der Hover-Effekt: der Browser entscheidet mit
   derselben Treffermessung, was aufleuchtet und was "nadel.landUnter"
   findet. Beides aus einer Quelle -- was hell wird, ist auch das, was
   gewaehlt wird.

   Das Umland bleibt aussen vor: es hat keine Kennungen und gehoert nicht
   zum Spielfeld. Ein Tipp darauf ist ein Tipp aufs Nichts, und genau so
   soll er sich anfuehlen. */
.kartenblatt--waehlbar .karte__seen,
.kartenblatt--waehlbar .karte__fluesse,
.kartenblatt--waehlbar .karte__grenzen,
.kartenblatt--waehlbar .karte__umland,
.kartenblatt--waehlbar .massstab {
    pointer-events: none;
}

.kartenblatt--waehlbar .karte__laender .karte__land,
.kartenblatt--waehlbar .karte__bundeslaender .karte__flaeche {
    cursor: pointer;
    transition: fill 90ms linear;
}

/* Heller, nicht andersfarbig. Ein bernsteinfarbenes Land unter dem Zeiger
   saehe aus wie eine Antwort und nicht wie ein Angebot -- und Bernstein
   gehoert hier der Auswertung. */
.kartenblatt--waehlbar .karte__laender .karte__land:hover,
.kartenblatt--waehlbar .karte__bundeslaender .karte__flaeche:hover {
    fill: #4e9b74;
}

/* --- Die Bundeslandflaechen ---

   Sie sind unsichtbar: das Land ist schon gezeichnet, die Grenzen kommen als
   eigene Linien darueber. Gefuellt wuerden sie die Landesgrenze verduennen,
   weil ihr Rand die aeussere Haelfte von deren Strich ueberdeckte.

   "pointer-events: all" ist deshalb die ganze Zeile, um die es geht: ohne
   Fuellung gibt es nichts zu treffen, und der Standard "visiblePainted" faende
   sie nie. Mit "all" zaehlt die geometrische Innenflaeche, gemalt oder nicht.

   NUR IM WAEHLMODUS. Auf demselben Blatt spielt auch das Geo-Quiz, und dort
   soll ein Umriss weder aufleuchten noch Zeiger abfangen. */
.karte__flaeche {
    fill: none;
    stroke: none;
    vector-effect: non-scaling-stroke;
}

.kartenblatt--waehlbar .karte__bundeslaender .karte__flaeche {
    pointer-events: all;
}

/* --- Was gefunden und was danebengetippt wurde ---

   Als Klasse am Pfad, gesetzt aus nadel.js. Eine <use>-Kopie darueber waere
   der naheliegende Weg und funktioniert nicht: der geklonte Pfad bringt
   seine eigene Regel (.karte__land) mit, und die gewinnt gegen die vom
   <use> geerbte Fuellung.

   Beide behalten den Zeiger-Effekt nicht: eine Runde, die sie zeigt, ist
   vorbei. */
.karte__land--gefunden {
    fill: #3f9c62;
    stroke: var(--ton-gueltig);
    stroke-width: 2;
}

.karte__land--daneben {
    fill: #7a3b3b;
    stroke: var(--ton-daneben);
    stroke-width: 2;
}

/* Eine ausgewertete Flaeche behaelt ihre Farbe, auch unter dem Zeiger. Beide
   Elternklassen ausgeschrieben, damit diese Regeln genauso schwer wiegen wie
   die allgemeine Zeigerregel weiter oben -- sonst gewaenne dort die hoehere
   Spezifitaet, und ein gefundenes Bundesland wuerde beim Darueberfahren wieder
   landfarben. */
.kartenblatt--waehlbar .karte__laender .karte__land--gefunden:hover,
.kartenblatt--waehlbar .karte__bundeslaender .karte__land--gefunden:hover { fill: #3f9c62; }

.kartenblatt--waehlbar .karte__laender .karte__land--daneben:hover,
.kartenblatt--waehlbar .karte__bundeslaender .karte__land--daneben:hover { fill: #7a3b3b; }

/* --- Die Gebietsflaechen der Themenblaetter (Gebirge, Waelder, Regionen) ---

   Anders als die Bundeslaender sind sie SICHTBAR: es gibt keine Grenzlinien,
   die ihre Form zeigen koennten, also muss die Flaeche selbst sagen, wo
   getippt werden kann. Erdiges Ocker ueber dem Landgruen -- warm genug, um
   aufzufallen, und weder das Gruen der Treffer noch das Rot der Fehlgriffe.
   Halbtransparent, damit Bundeslandgrenzen und Seen als Orientierung
   durchscheinen. */
.karte__gebiet {
    fill: rgba(201, 168, 92, 0.34);
    stroke: rgba(228, 205, 138, 0.7);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}

.kartenblatt--waehlbar .karte__gebiete .karte__gebiet {
    cursor: pointer;
    transition: fill 90ms linear;
}

.kartenblatt--waehlbar .karte__gebiete .karte__gebiet:hover {
    fill: rgba(228, 205, 138, 0.55);
}

/* Auf den Themenblaettern sind die Gebiete die Antwort. Die Laender darunter
   fangen deshalb keine Zeiger: sonst waere jeder Tipp knapp neben ein Gebiet
   ein Fehlgriff namens "Deutschland" -- und halb Europa leuchtete beim
   Darueberfahren, als liesse es sich waehlen. Ein Tipp neben die Flaechen ist
   hier ein Tipp aufs Nichts, wie sonst einer aufs Meer. */
.kartenblatt--gebiete .karte__laender .karte__land {
    pointer-events: none;
    cursor: default;
}

/* Die Auswertung wiegt schwerer als die Ocker-Grundregel: die steht weiter
   oben mit nur einer Klasse, und bei gleichem Gewicht gewaenne sie als
   spaetere -- ein gefundenes Gebiet bliebe ockerfarben. Zwei Klassen heben
   die Auswertung darueber, in jedem Modus, samt Strich. */
.karte__gebiete .karte__land--gefunden,
.kartenblatt--waehlbar .karte__gebiete .karte__land--gefunden:hover {
    fill: #3f9c62;
    stroke: var(--ton-gueltig);
    stroke-width: 2;
}

.karte__gebiete .karte__land--daneben,
.kartenblatt--waehlbar .karte__gebiete .karte__land--daneben:hover {
    fill: #7a3b3b;
    stroke: var(--ton-daneben);
    stroke-width: 2;
}

/* --- Das Fadenkreuz ---

   Zwei durchgehende Linien quer ueber das ganze Bild, fest in der Mitte;
   die Karte wandert darunter durch. Sie muessen von der Hand nicht
   verdeckt werden koennen -- gerade das ist ihr Zweck: der Schnittpunkt
   liegt oft unter dem Finger, und dann sagen die Enden, wo gezielt wird.

   Bernstein, weil diese Farbe sonst nirgends auf der Karte vorkommt --
   Land ist gruen, Wasser blau, Grenzen dunkel. Eine Verwechslung mit
   einem Fluss oder einer Grenze ist damit ausgeschlossen. */

.fadenkreuz__linie {
    stroke: var(--ton-akzent);
    stroke-width: 1.2;
    opacity: 0.85;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
}

/* --- Was frueher geschah, bleibt blass stehen --- */

.nadellage__runde {
    opacity: 0.4;
}

.nadellage__runde--frisch {
    opacity: 1;
}

.nadellage__strich {
    stroke: var(--ton-akzent);
    stroke-width: 1.5;
    stroke-dasharray: 5 4;
    vector-effect: non-scaling-stroke;
}

.nadellage__ziel {
    fill: none;
    stroke: var(--ton-gueltig);
    stroke-width: 2.5;
    vector-effect: non-scaling-stroke;
}

.nadellage__runde--frisch .nadellage__ziel {
    fill: rgba(87, 217, 138, 0.28);
}

.nadellage__stich {
    fill: var(--ton-akzent);
}

/* --- Die Schicht darueber --------------------------------------------

   Sie liegt ueber der ganzen Karte und laesst Zeiger durch. Nur was
   angefasst werden soll, faengt sie wieder ein -- sonst laege ueber dem
   halben Blatt etwas, worauf sich nicht stechen liesse. */

.nadelschicht {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

/* Das Band mit Frage oder Antwort. Beide sitzen an derselben Stelle: die
   Antwort erscheint da, wo eben noch die Frage stand. */
.nadelband {
    position: absolute;
    top: 0.7rem;
    left: 50%;
    transform: translateX(-50%);
    max-width: min(92%, 34rem);
    padding: 0.5rem 1.4rem 0.6rem;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 10px;
    background: rgba(9, 20, 16, 0.82);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    box-shadow: 0 8px 26px rgba(0, 0, 0, 0.45);
    text-align: center;
}

.nadelband--aufloesung {
    border-color: rgba(242, 181, 68, 0.45);
    animation: nadelband-auf 180ms ease-out;
}

.nadelband--fertig {
    border-color: rgba(87, 217, 138, 0.45);
}

@keyframes nadelband-auf {
    from { opacity: 0; transform: translateX(-50%) translateY(-6px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .nadelband--aufloesung { animation: none; }
}

.nadelband__rolle {
    margin: 0;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ton-schrift-leise);
}

.nadelband__ort {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 0.15rem 0.7rem;
    margin: 0.1rem 0 0;
    font-size: clamp(1.1rem, 2.4cqw, 1.6rem);
    font-weight: 800;
    letter-spacing: -0.01em;
}

.nadelband__fragezeichen { color: var(--ton-akzent); }
.nadelband__urteil { color: var(--ton-akzent); }

.nadelband__weite {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--ton-schrift-leise);
}

.nadelband__punkte {
    font-size: 1.1rem;
    font-weight: 800;
    color: var(--ton-gueltig);
}

/* Die Zeile unter der Frage im Laenderquiz: wie viele Versuche noch
   bleiben, und -- nach einem Fehltipp -- was man stattdessen getroffen hat.

   Das ist die eigentliche Auskunft der Runde. „Nicht Portugal, sondern
   Frankreich" bringt beim naechsten Mal etwas; ein rotes Feld allein nicht. */
.nadelband__versuche {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 0.15rem 0.6rem;
    margin: 0.25rem 0 0;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--ton-schrift-leise);
}

.nadelband__daneben {
    color: var(--ton-daneben);
    font-weight: 700;
}

/* --- Der eine Knopf, unten rechts ---

   Immer an derselben Stelle, nur die Aufschrift wechselt: Einschlagen,
   Weiter, Karte ansehen. Auf dem Telefon liegt er da, wo der Daumen
   ohnehin ist. Zwei Knoepfe an zwei Orten hiessen, jedes Mal aufs Neue
   zu suchen, wo der naechste Schritt liegt. */

/* Der Platz traegt die Lage und faengt die Zeiger; der Knopf darin sitzt
   nur noch drin. Grund: ein abgeschalteter Knopf bekommt gar keine
   Zeigerereignisse, sie gingen an ihm vorbei an die Karte -- und ein Tipp
   auf das ausgegraute "Einschlagen" setzte eine Nadel dahinter. */
.nadelplatz {
    position: absolute;
    right: clamp(0.7rem, 2cqw, 1.4rem);
    bottom: clamp(0.7rem, 2cqw, 1.4rem);
    pointer-events: auto;
    touch-action: none;
}

.nadelknopf {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    min-height: 3rem;
    padding: 0 1.3rem 0 1rem;
    border: 1px solid rgba(15, 25, 20, 0.5);
    border-radius: 999px;
    background: var(--ton-akzent);
    color: #17281f;
    font: inherit;
    font-size: 1rem;
    font-weight: 800;
    cursor: pointer;
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.5);
    transition: transform 120ms ease, filter 120ms ease;
}

.nadelknopf:hover:not(:disabled) {
    filter: brightness(1.08);
    transform: translateY(-1px);
}

.nadelknopf:active:not(:disabled) {
    transform: translateY(1px);
}

/* Ausgegraut statt versteckt: der Knopf soll auch dann an seinem Platz
   stehen, wenn noch keine Nadel gesetzt ist -- sonst taucht unten rechts
   im Spiel etwas auf, das vorher nicht da war. */
.nadelknopf:disabled {
    background: rgba(255, 255, 255, 0.13);
    border-color: rgba(255, 255, 255, 0.16);
    color: var(--ton-schrift-leise);
    cursor: default;
    box-shadow: none;
}

.nadelknopf__zeichen {
    display: inline-flex;
    width: 1.35rem;
    height: 1.35rem;
}

.nadelknopf__zeichen svg {
    width: 100%;
    height: 100%;
}

.nadelfertig {
    position: absolute;
    right: clamp(0.7rem, 2cqw, 1.4rem);
    bottom: clamp(0.7rem, 2cqw, 1.4rem);
    margin: 0;
    padding: 0.7rem 1.2rem;
    border: 1px solid rgba(87, 217, 138, 0.4);
    border-radius: 999px;
    background: rgba(9, 20, 16, 0.85);
    font-weight: 700;
}

/* Der Hinweis steht nur da, solange noch keine Nadel gesetzt ist. Danach
   ist er beantwortet und verschwindet -- er liegt in der Schicht und
   verschiebt dabei nichts. */
/* Unten mittig, nicht mehr unten links: dort steht seit dem Zoom der
   Massstabsbalken, und zwei Dinge uebereinander waeren unlesbar. */
.nadelhinweis {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: clamp(0.7rem, 2cqw, 1.2rem);
    max-width: min(70%, 30rem);
    text-align: center;
    margin: 0;
    font-size: 0.82rem;
    color: rgba(238, 245, 241, 0.72);
    text-shadow: 0 1px 6px rgba(0, 0, 0, 0.9);
}

/* --- Zoom ---------------------------------------------------------------

   Der Zoom aendert nur den viewBox der Karte. Deshalb bleiben Kuestenlinien
   und Fluesse bei jeder Vergroesserung haarfein: sie tragen
   "non-scaling-stroke" und wachsen nicht mit. Eine CSS-Transformation haette
   das nicht geleistet -- dort waere aus einem Dreiviertelpunkt Kuestenlinie
   bei achtfacher Vergroesserung ein Filzstiftstrich geworden. */

.zoomstock {
    position: absolute;
    left: clamp(0.7rem, 2cqw, 1.4rem);
    top: clamp(0.7rem, 2cqw, 1.4rem);
    pointer-events: auto;
    touch-action: none;

    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.zoomknopf {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.4rem;
    height: 2.4rem;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 8px;
    background: rgba(9, 20, 16, 0.84);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    color: var(--ton-schrift);
    font: inherit;
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease;
}

.zoomknopf:hover:not(:disabled) {
    background: rgba(29, 70, 53, 0.92);
    border-color: rgba(242, 181, 68, 0.5);
}

.zoomknopf:disabled {
    color: rgba(157, 181, 170, 0.5);
    cursor: default;
}

/* Ein Schalter, der aus ist -- nicht dasselbe wie ein Knopf, der nicht
   kann. Deshalb durchgestrichen und nicht ausgegraut. */
.zoomknopf--aus {
    color: rgba(157, 181, 170, 0.6);
    text-decoration: line-through;
}

.zoomknopf--wasser {
    color: #57b6e8;
    font-size: 1.1rem;
}

.zoomknopf--wasser.zoomknopf--aus {
    color: rgba(87, 182, 232, 0.45);
}

/* Der dritte Knopf zeigt die Vergroesserung und stellt sie zugleich zurueck.
   Zwei Dinge an einer Stelle, weil beide dieselbe Frage betreffen: wie nah
   bin ich dran, und wie komme ich wieder heraus. */
.zoomknopf--ganz {
    width: auto;
    min-width: 2.4rem;
    padding: 0 0.5rem;
    font-size: 0.8rem;
    font-weight: 800;
    letter-spacing: 0.02em;
}

/* --- Der Massstabsbalken ---

   Er steht im SVG und nicht daneben: seine Laenge ist eine Strecke auf der
   Karte, und beim Zoomen muss sie mitwachsen. Die Striche tragen wieder
   "non-scaling-stroke", damit sie dabei nicht dicker werden. */

.massstab__balken,
.massstab__ende {
    stroke: rgba(238, 245, 241, 0.85);
    stroke-width: 2;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

.massstab__wort {
    fill: rgba(238, 245, 241, 0.9);
    font-family: inherit;
    font-weight: 700;
    paint-order: stroke;
    stroke: rgba(9, 20, 16, 0.85);
    stroke-width: 3;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
}

/* Auf schmalen Schirmen bleibt vom Knopf das Zeichen. Unten rechts ist
   der Platz knapp, und "Einschlagen" braucht daneben mehr Breite, als
   ein Telefon hergibt. */
@container buehne (max-width: 30rem) {
    .nadelknopf__wort { display: none; }

    .nadelknopf {
        padding: 0;
        width: 3.4rem;
        height: 3.4rem;
        justify-content: center;
        gap: 0;
    }

    .nadelknopf__zeichen {
        width: 1.6rem;
        height: 1.6rem;
    }

    .nadelhinweis { display: none; }

    .zoomknopf {
        width: 2.1rem;
        height: 2.1rem;
        font-size: 1.1rem;
    }

    .zoomknopf--ganz {
        width: auto;
        min-width: 2.1rem;
        font-size: 0.72rem;
    }
}

/* ===================================================================
   Halle und Partie -- zwei Rahmen statt einem

   IN DER HALLE oben eine schmale Leiste und darunter die Seite. Die
   Halle ist die Navigation; ein zweites Menue daneben waere dieselbe
   Doppelung, die die Startseite unuebersichtlich gemacht hat.

   IN EINER PARTIE gibt es keine Navigation: oben der Weg zurueck und
   die Werte, unten die Knoepfe des Spiels, dazwischen nur das Brett.
   Gemessen auf 1440 x 900 blieben der Buehne vorher 1072 x 862 -- mit
   offener Seitentafel, und die stand standardmaessig offen. Jetzt sind
   es 1440 x rund 800: ein Viertel mehr Flaeche. Auf einem Telefon
   waechst die Breite von 305 auf 375 Bildpunkte.

   Warum quer statt hochkant: eine Leiste kostet Hoehe, eine Schiene
   kostet Breite. Auf einem Telefon ist Hoehe das, wovon reichlich da
   ist -- und ein Spielbrett ist fast immer breiter als hoch.
   =================================================================== */

.rahmen--halle,
.rahmen--partie {
    display: grid;

    /* Die Spalte muss ausdruecklich schrumpfen duerfen. Ohne das
       "minmax(0, 1fr)" richtet sich das Raster nach der breitesten
       Zeile -- und die Leiste einer Partie ist einzeilig und lang.
       Gemessen wurde die Buehne dadurch 1711 Bildpunkte breit auf einem
       Fenster von 1440; der Ueberhang lag ausserhalb des Bildes. */
    grid-template-columns: minmax(0, 1fr);
    height: 100dvh;
    overflow: hidden;
}

.rahmen--halle {
    grid-template-rows: auto 1fr;
}

.rahmen--partie {
    grid-template-rows: auto 1fr;
}

/* --- Der Kopf der Halle --- */

.hallenkopf {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 0.55rem clamp(0.7rem, 2vw, 1.4rem);
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
    background: rgba(0, 0, 0, 0.25);
}

.hallenkopf__marke {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    color: var(--ton-schrift);
    text-decoration: none;
}

.hallenkopf__zeichen {
    display: grid;
    place-items: center;
    width: 2rem;
    height: 2rem;
    border-radius: 9px;
    background: var(--ton-akzent);
    color: #2a1c00;
    font-weight: 800;
    font-size: 0.8rem;
    letter-spacing: 0.02em;
}

.hallenkopf__wort {
    font-weight: 700;
    letter-spacing: -0.01em;
    white-space: nowrap;
}

.hallenkopf__rechts {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-left: auto;
}

.hallenkopf__klang {
    padding: 0.4rem 0.6rem;
    line-height: 1;
}

.halle__buehne {
    min-height: 0;
    overflow: auto;
    padding: clamp(0.8rem, 2.5vw, 2rem);
}

/* Was eine Seite frueher in die Seitentafel gelegt haette, steht in der
   Halle quer ueber der Seite statt hochkant daneben. */
.hallentafel {
    max-width: 60rem;
    margin: 0 auto 1.4rem;
}

.hallentafel .spielwahl {
    flex-direction: row;
    flex-wrap: wrap;
}

.hallentafel .tafel__rubrik:first-child {
    margin-top: 0;
}

/* --- Die Leiste einer Partie ---

   Eine Leiste, nicht zwei. Der erste Anlauf hatte die Werte oben und die
   Knoepfe unten und kostete damit neunundneunzig Bildpunkte Hoehe --
   gemessen schrumpfte die Nadelstich-Karte dabei von 978 auf 905
   Bildpunkte. Bei einem Brett, das breiter als hoch ist, bringt
   zusaetzliche Breite nichts, solange die Hoehe der Engpass bleibt.

   Auf schmalen Schirmen bricht sie um: Weg zurueck und Titel oben, Werte
   und Knoepfe darunter. Das kostet dort eine zweite Zeile Hoehe -- und
   Hoehe ist auf einem Telefon das, wovon reichlich da ist. */

.partieleiste {
    display: flex;
    align-items: center;

    /* Auf breiten Schirmen eine einzige Zeile. Umbrechen darf sie erst,
       wenn es wirklich eng wird -- jede zweite Zeile kostet das Brett
       sechsunddreissig Bildpunkte Hoehe, und bei einem Brett, das
       breiter als hoch ist, ist die Hoehe der Engpass. Was nicht passt,
       wird gekuerzt statt umgebrochen. */
    flex-wrap: nowrap;
    min-width: 0;
    overflow: hidden;
    gap: 0.45rem 0.7rem;
    padding: 0.35rem clamp(0.5rem, 1.6vw, 1rem);
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
    background: rgba(0, 0, 0, 0.28);
}

/* Eine Bedienung, auf die eine Vollbildseite angewiesen ist -- sie steht als
   eigene Zeile unter der Leiste und wird nicht eingeklappt.

   Der Anlass steht bei "Tafelart" im Rahmenzustand: die Kuratoransicht legte
   ihre Spielauswahl in die Tafel, der Vollbildrahmen raeumte sie hinter einen
   Knopf, und die Seite war eine Sackgasse. Eine Zeile kostet das Brett rund
   vierzig Bildpunkte Hoehe -- deutlich weniger als ein Weg, den niemand
   findet.

   Waagerecht rollbar statt umbrechend, aus demselben Grund wie bei der
   Leiste: zwei Zeilen kosten mehr als ein Schiebebalken. */
.partietafel {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 0.4rem 0.7rem;
    min-width: 0;
    overflow-x: auto;
    padding: 0.35rem clamp(0.5rem, 1.6vw, 1rem);
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
    background: rgba(0, 0, 0, 0.18);
}

.partietafel .spielwahl {
    flex-direction: row;
    flex-wrap: nowrap;
}

/* In einer Zeile ist eine Rubrik eine Beschriftung davor, keine Ueberschrift
   darueber -- sonst schoebe ihr Aussenabstand die Zeile auseinander. */
.partietafel .tafel__rubrik {
    margin: 0;
    white-space: nowrap;
}

.partieleiste__zurueck {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.7rem;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.06);
    color: var(--ton-schrift);
    font-size: 0.85rem;
    text-decoration: none;
    white-space: nowrap;
}

.partieleiste__zurueck:hover {
    background: rgba(255, 255, 255, 0.12);
}

.partieleiste__titel {
    flex: 0 1 auto;
    min-width: 3rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.partieleiste__beitext,
.partieleiste__notiz {
    flex: 0 1 auto;
    min-width: 0;
    font-size: 0.8rem;
    color: var(--ton-schrift-leise);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Die Werte in die Mitte-rechts, die Knoepfe rechts: so stehen beide
   immer an derselben Stelle, auch wenn der Titel unterschiedlich lang
   ist. */
.partieleiste__werte {
    display: flex;
    align-items: center;
    flex: none;
    gap: clamp(0.6rem, 2vw, 1.4rem);
    margin-left: auto;
}

/* Die Anzeigen lagen frueher hochkant in der Schiene: Wert oben, Wort
   darunter. Quer in einer Leiste ist nebeneinander richtig. */
.partieleiste__werte .anzeige {
    flex-direction: row;
    align-items: baseline;
    gap: 0.35rem;
}

.partieleiste__taten {
    display: flex;
    align-items: center;
    flex: none;
    gap: 0.4rem;
}

.partieleiste__klang {
    padding: 0.4rem 0.6rem;
    line-height: 1;
}

.partieleiste__wer {
    font-size: 0.78rem;
    color: var(--ton-schrift-leise);
    white-space: nowrap;
}

/* Auf dem Telefon faellt weg, was nicht gebraucht wird: das Wort am
   Pfeil, die Dealnummer, der Kontoname. Der Pfeil allein genuegt -- er
   steht an derselben Stelle wie ueberall sonst. */
@media (max-width: 700px) {
    /* Jetzt darf sie umbrechen: unten ist Hoehe, und in der Breite geht
       sonst nichts mehr.

       Werte und Knoepfe bekommen dabei je eine eigene Zeile. Mit
       "flex: none" standen sie sonst starr nebeneinander und liefen aus
       dem Bild -- gemessen dreihunderteinundzwanzig Bildpunkte weit. */
    .partieleiste {
        flex-wrap: wrap;
    }

    /* Je eine eigene Zeile -- und in dieser Zeile bleiben sie. Umbrechen
       durften sie zuerst, und die Uebungsseite mit ihren sechs Knoepfen
       machte daraus eine Leiste von zweihundertfuenfunddreissig
       Bildpunkten: knapp ein Drittel des Telefons, fuer Knoepfe. Jetzt
       eine Zeile, die sich schieben laesst. */
    .partieleiste__werte,
    .partieleiste__taten {
        flex: 1 1 100%;
        flex-wrap: nowrap;
        min-width: 0;
        margin-left: 0;
        overflow-x: auto;
        scrollbar-width: none;
    }

    .partieleiste__werte::-webkit-scrollbar,
    .partieleiste__taten::-webkit-scrollbar {
        display: none;
    }

    /* Damit sie sich beim Schieben nicht zusammenquetschen. */
    .partieleiste__werte > *,
    .partieleiste__taten > * {
        flex: none;
    }

    .partieleiste__werte {
        justify-content: flex-start;
    }

    .partieleiste__zurueckwort,
    .partieleiste__beitext,
    .partieleiste__notiz,
    .partieleiste__wer {
        display: none;
    }

    .partieleiste__titel {
        font-size: 0.9rem;
    }

    .partieleiste__werte {
        gap: 0.8rem;
    }
}

/* ===================================================================
   Die Halle als Seite

   Nach Verbindlichkeit geordnet: erst das freie Spiel, bei dem nichts
   auf dem Spiel steht, dann die Aufgabe des Tages, dann die Duelle, bei
   denen jemand wartet.
   =================================================================== */

.halle {
    display: flex;
    flex-direction: column;
    gap: 1.6rem;
    width: 100%;
    max-width: 60rem;
    margin: 0 auto;
}

.halle__gruss {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.halle__titel {
    margin: 0;
    font-size: clamp(1.5rem, 3.6vw, 2.2rem);
    font-weight: 800;
    letter-spacing: -0.02em;
}

.halle__titel span {
    color: var(--ton-akzent);
}

.halle__text {
    margin: 0;
    max-width: 44rem;
    color: var(--ton-schrift-leise);
}

/* --- Ein Tor: die grosse Tuer eines Bandes --- */

.tor {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.1rem 1.2rem;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 14px;
    background: linear-gradient(135deg, rgba(29, 70, 53, 0.55), rgba(255, 255, 255, 0.03));
    color: var(--ton-schrift);
    text-decoration: none;
    transition: border-color 0.12s ease, transform 0.12s ease;
}

.tor:hover {
    border-color: rgba(242, 181, 68, 0.55);
    transform: translateY(-1px);
}

.tor--schmal {
    padding: 0.85rem 1.1rem;
    background: rgba(255, 255, 255, 0.04);
}

.tor--wartet {
    border-color: rgba(242, 181, 68, 0.5);
    background: linear-gradient(135deg, rgba(242, 181, 68, 0.16), rgba(255, 255, 255, 0.03));
}

.tor__zeichen {
    display: grid;
    place-items: center;
    flex: none;
    width: 2.8rem;
    height: 2.8rem;
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.3);
    color: var(--ton-akzent);
    font-size: 1.2rem;
}

.tor__worte {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-width: 0;
}

.tor__titel {
    font-size: 1.15rem;
    font-weight: 800;
    letter-spacing: -0.01em;
}

.tor__text {
    font-size: 0.88rem;
    color: var(--ton-schrift-leise);
}

.tor__weg {
    margin-left: auto;
    flex: none;
    color: var(--ton-akzent);
    font-size: 1.3rem;
}

/* --- Ein Band: Ueberschrift und Inhalt --- */

.band {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.band__titel {
    margin: 0;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ton-schrift-leise);
}

.band__text {
    margin: -0.3rem 0 0.2rem;
    font-size: 0.85rem;
    color: var(--ton-schrift-leise);
}

/* --- Der leise Fuss --- */

.halle__fuss {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 1.2rem;
    margin-top: 0.6rem;
    padding-top: 1rem;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
    font-size: 0.85rem;
}

.halle__fuss a,
.halle__fussknopf {
    color: var(--ton-schrift-leise);
    text-decoration: none;
    border: 0;
    background: transparent;
    padding: 0;
    font: inherit;
    font-size: 0.85rem;
    cursor: pointer;
}

.halle__fuss a:hover,
.halle__fussknopf:hover {
    color: var(--ton-schrift);
    text-decoration: underline;
}

/* --- Die Spielauswahl --- */

.auswahl {
    display: flex;
    flex-direction: column;
    gap: 1.2rem;
    width: 100%;
    max-width: 66rem;
    margin: 0 auto;
}

.auswahl__titel {
    margin: 0 0 0.3rem;
    font-size: clamp(1.4rem, 3.2vw, 2rem);
    font-weight: 800;
    letter-spacing: -0.02em;
}

.auswahl__text {
    margin: 0;
    max-width: 44rem;
    color: var(--ton-schrift-leise);
}

.auswahl__fuss {
    margin: 0;
    font-size: 0.85rem;
    color: var(--ton-schrift-leise);
}

.auswahl__fuss a {
    color: var(--ton-akzent);
}

/* Das Zeichen in der Tagesliste -- dieselben Kartenfarben wie auf den
   Kacheln, nur klein. */
.heute__zeichen {
    display: inline-block;
    width: 1.1rem;
    text-align: center;
    margin-right: 0.35rem;
}

/* =====================================================================
   Fundraster
   ===================================================================== */

/* Brett und Vorrat sitzen zusammen in der Mitte.

   Vorher hatte diese Flaeche drei Zeilen -- Brett, Vorrat, Hinweiszeile --
   und die erste war "minmax(0, 1fr)". Das Brett ist aber quadratisch und
   gedeckelt; es fuellte seine Zeile nicht, sondern klebte oben, waehrend
   der Vorrat am unteren Rand hing. Auf einem breiten Schirm lagen dann
   dreihundert Bildpunkte Nichts dazwischen.

   Jetzt bemessen sich beide Zeilen nach ihrem Inhalt, und "align-content"
   rueckt das Paar als Ganzes in die Mitte. */
.fundraster {
    display: grid;
    grid-template-rows: auto auto;
    align-content: center;
    justify-items: center;
    gap: 0.7rem;
    width: 100%;
    height: 100%;
    min-height: 0;
}

/* Das Brett ist quadratisch und nimmt, was die Buehne hergibt -- in der
   Breite wie in der Hoehe. Dieselbe Rechnung wie beim Kartenblatt des
   Geo-Quiz: "aspect-ratio" mit hundert Prozent Breite ergaebe eine Hoehe,
   die ueber die Buehne hinausragt, und genau daraus entsteht eine
   Bildlaufleiste. */
.rasterbrett {
    position: relative;
    display: grid;
    grid-template-columns: repeat(var(--spalten, 8), 1fr);
    grid-template-rows: repeat(var(--zeilen, 8), 1fr);
    gap: 2px;

    /* Zoom aussen um die Schranken -- die Begruendung steht bei --karte-breite.
       „max-width: 100%“ bleibt die letzte Sicherung: ein hochgezoomtes Raster
       darf breiter werden als die Buehne, aber nicht breiter als sein Kasten. */
    width: calc(min(100cqw, 100cqh - 9rem, 34rem) * var(--zoom, 1));
    aspect-ratio: 1;
    max-width: 100%;

    padding: 6px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 14px;
    background: rgba(0, 0, 0, 0.3);
}

.rasterfeld {
    border: 0;
    border-radius: 4px;
    padding: 0;
    min-width: 0;
    min-height: 0;
    cursor: pointer;
    transition: background-color 0.1s ease, box-shadow 0.1s ease;
}

.rasterfeld:disabled {
    cursor: default;
}

.rasterfeld--leer {
    background: rgba(255, 255, 255, 0.05);
}

.rasterfeld--belegt {
    background: #6f86a8;
    box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.25);
}

/* Die beiden Fundstuecke. Gruen und Blau wie im Vorbild -- aber ohne
   Symbol darin: ein Zeichen von acht Bildpunkten Kantenlaenge ist auf
   einem Telefon nicht mehr zu erkennen, und die Farbe allein sagt
   dasselbe schneller. Unterschieden werden sie zusaetzlich durch die
   Helligkeit, damit sie auch dann auseinandergehen, wenn jemand Gruen und
   Blau schlecht trennt. */
.rasterfeld--gruen {
    background: #4fd07a;
    box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.3);
}

.rasterfeld--blau {
    background: #2f9bd8;
    box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.3);
}

/* Die Vorschau: wo der gewaehlte Stein landen wuerde. Bernstein heisst
   "geht", Rot heisst "geht nicht" -- und beides liegt ueber der Farbe des
   Feldes, damit man sieht, was man ueberdecken wuerde. */
.rasterfeld--passt {
    box-shadow: inset 0 0 0 2px var(--ton-akzent);
    background: var(--ton-akzent-schwach);
}

.rasterfeld--sperrt {
    box-shadow: inset 0 0 0 2px var(--ton-rot);
}

.rasterfeld:focus-visible {
    outline: 2px solid var(--ton-akzent);
    outline-offset: 1px;
}

/* --- Der Vorrat --- */

.steinvorrat {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.6rem;
    width: min(100%, 34rem);
}

.vorratsplatz {
    display: grid;
    place-items: center;
    min-height: 4.5rem;
    padding: 0.5rem;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.22);
    cursor: pointer;
}

.vorratsplatz--gewaehlt {
    border-color: var(--ton-akzent);
    background: var(--ton-akzent-schwach);
}

.vorratsplatz--leer {
    background: rgba(0, 0, 0, 0.1);
    border-style: dashed;
    cursor: default;
}

/* Ein Stein, der nirgends mehr hinpasst. Er bleibt bedienbar -- wer ihn
   antippt, soll sehen duerfen, warum es nicht geht -- aber er sagt vorher,
   dass es aussichtslos ist. */
.vorratsplatz--eng {
    opacity: 0.45;
}

.steinbild {
    display: grid;
    grid-template-columns: repeat(var(--breite, 1), 0.85rem);
    grid-template-rows: repeat(var(--hoehe, 1), 0.85rem);
    gap: 2px;
}

.steinbild__feld {
    border-radius: 3px;
    background: #8fa6c8;
    box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.25);
}

.vorratsplatz--gewaehlt .steinbild__feld {
    background: var(--ton-akzent);
}

/* --- Das Ende einer Partie --- */

/* --- Die Schlusstafel der beiden Rasterspiele ---

   DIE FARBE GEHOERT DEM ERGEBNIS. Bis zum 22.08.2026 stand jedes Schlusswort
   in der Akzentfarbe -- Gold, also die Farbe, mit der diese Anwendung sonst
   Gutes auszeichnet. „Alles geborgen" sah damit aus wie „Nichts geborgen", und
   am Ende jeder Partie stand scheinbar ein Erfolg. Jetzt setzt die Karte ihre
   eigene Leitfarbe in --ergebnis, und Zeichen, Wort und Rahmen nehmen sie auf.

   Der Grund liegt darunter durch. Vorher deckte die Tafel das Brett mit 88
   Prozent Deckkraft zu -- man sah nicht mehr, wie die Partie ausgegangen war,
   und gerade beim Feststecken ist die letzte Lage das Interessanteste. */

.rasterende {
    position: absolute;
    inset: 0;
    display: grid;
    place-content: center;
    padding: 0.8rem;
    border-radius: 14px;
    background: radial-gradient(ellipse at 50% 45%,
        rgba(8, 20, 15, 0.92) 0%, rgba(8, 20, 15, 0.62) 100%);
    text-align: center;
}

.rasterende__karte {
    --ergebnis: var(--ton-akzent);

    display: grid;
    justify-items: center;
    gap: 0.15rem;
    padding: 1rem 1.5rem 1.1rem;
    border-radius: 16px;

    /* Erst schlicht, dann eingefaerbt: "color-mix" kommt in dieser Stilvorlage
       sonst nicht vor, und ein Browser, der es nicht kennt, wirft die ganze
       Deklaration weg. Ohne die erste Zeile stuende die Karte dann ohne Rahmen
       und ohne Grund da. */
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-color: color-mix(in srgb, var(--ergebnis) 40%, transparent);

    background: rgba(10, 26, 19, 0.96);
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--ergebnis) 12%, rgba(10, 26, 19, 0.96)) 0%,
        rgba(10, 26, 19, 0.96) 60%);

    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5),
                inset 0 1px 0 color-mix(in srgb, var(--ergebnis) 30%, transparent);
}

/* Geschafft und festgefahren beim Fundraster, das ein Ziel hat -- und dazwischen
   die sechs Stufen des Farbrasters, das keines hat.

   Die Rampe muss durchgehend lauter werden, sonst sagt die Farbe etwas anderes
   als die Zahl: Schiefer, Salbei, fast Weiss, Gruen, Limone, Gold. Beim ersten
   Anlauf stand auf Stufe 4 ein blasses Mint -- heller als Gruen im Namen, aber
   matter im Bild, und damit sah die vorletzte Stufe schwaecher aus als die
   drittletzte. */
.rasterende__karte--geschafft { --ergebnis: var(--ton-gueltig); }
.rasterende__karte--steckt { --ergebnis: #7f98a8; }

.rasterende__karte--stufe0 { --ergebnis: #7f98a8; }
.rasterende__karte--stufe1 { --ergebnis: #9db5aa; }
.rasterende__karte--stufe2 { --ergebnis: #cfe0d6; }
.rasterende__karte--stufe3 { --ergebnis: var(--ton-gueltig); }
.rasterende__karte--stufe4 { --ergebnis: #b6dd5a; }
.rasterende__karte--stufe5 { --ergebnis: var(--ton-akzent); }

.rasterende__zeichen {
    margin: 0 0 0.2rem;
    display: grid;
    place-items: center;
    width: 2.1rem;
    height: 2.1rem;
    border-radius: 50%;

    border: 1px solid rgba(255, 255, 255, 0.18);
    border-color: color-mix(in srgb, var(--ergebnis) 45%, transparent);

    background: rgba(255, 255, 255, 0.07);
    background: color-mix(in srgb, var(--ergebnis) 16%, transparent);

    color: var(--ergebnis);
    font-size: 1.1rem;
    line-height: 1;
}

.rasterende__wort {
    margin: 0;
    color: var(--ergebnis);
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: 0.01em;
}

.rasterende__rang {
    margin: 0;
    max-width: 28ch;
    color: var(--ton-schrift-leise);
    font-size: 0.82rem;
    line-height: 1.35;
}

/* Die Zahl ist der zweite Blick und darf deshalb gross sein -- aber sie steht
   unter dem Ergebnis und nicht darueber. Erst „geschafft oder nicht", dann
   „wie viel". */
.rasterende__zahl {
    margin: 0.5rem 0 0;
    display: flex;
    align-items: baseline;
    gap: 0.35rem;
    color: var(--ton-schrift);
    font-size: 2.3rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.rasterende__einheit {
    color: var(--ton-schrift-leise);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* Zwei Spalten, damit die Zahlen untereinander stehen und nicht im Fliesstext
   verschwinden. Vorher war das ein Satz -- „37 Steine gelegt, 11 Reihen
   geraeumt, groesste Farbgruppe 9" --, den man lesen musste, statt ihn zu
   sehen. */
.rasterende__liste {
    margin: 0.7rem 0 0;
    display: grid;
    gap: 0.05rem;
    width: 100%;
    min-width: 13.5rem;
    font-size: 0.85rem;
}

.rasterende__posten {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1.2rem;
    padding: 0.2rem 0;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
}

.rasterende__posten:first-child {
    border-top: 0;
}

.rasterende__posten dt {
    color: var(--ton-schrift-leise);
}

.rasterende__posten dd {
    margin: 0;
    color: var(--ton-schrift);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Die beiden Fundfarben tragen ihre eigene -- dieselben Toene wie die Zaehler
   in der Leiste und wie die Fundstuecke auf dem Brett. */
.rasterende__posten--gruen dd { color: #4fd07a; }
.rasterende__posten--blau dd { color: #2f9bd8; }
.rasterende__posten--bonus dd { color: var(--ton-akzent); }

@media (prefers-reduced-motion: no-preference) {
    .rasterende__karte {
        animation: rasterende-auf 0.28s ease-out both;
    }

    @keyframes rasterende-auf {
        from { opacity: 0; transform: translateY(0.6rem) scale(0.97); }
        to { opacity: 1; transform: none; }
    }
}

/* Auf einem Telefon quer schrumpft das Brett dramatisch -- gemessen auf
   812 x 375 sind es 161 Bildpunkte im Quadrat. Die Karte muss dann mitschrumpfen
   statt darueber hinauszulaufen; beim ersten Anlauf stand sie mit 245 auf 161
   und ragte weit ueber das Brett in den Vorrat hinein.

   Was hier faellt, faellt in dieser Reihenfolge: das Zeichen (Zierde), der
   Untertitel (er erklaert, was die Liste ohnehin zeigt), die Mindestbreite der
   Liste. Wort und Punktzahl bleiben immer -- ohne sie waere die Tafel keine. */
@media (max-height: 34rem) {
    .rasterende {
        padding: 0.35rem;
    }

    .rasterende__karte {
        gap: 0;
        max-width: 100%;
        padding: 0.5rem 0.75rem 0.6rem;
    }

    .rasterende__zeichen { display: none; }
    .rasterende__rang { display: none; }
    .rasterende__wort { font-size: 1rem; }
    .rasterende__zahl { margin-top: 0.25rem; font-size: 1.5rem; }

    .rasterende__liste {
        margin-top: 0.35rem;
        min-width: 0;
        font-size: 0.7rem;
    }

    .rasterende__posten {
        gap: 0.6rem;
        padding: 0.1rem 0;
    }
}

/* Die beiden Zaehler in der Leiste tragen die Farbe ihres Fundstuecks --
   sonst stuenden dort zwei gleich aussehende Bruchzahlen nebeneinander. */
.anzeige--gruen .anzeige__wert { color: #4fd07a; }
.anzeige--blau .anzeige__wert { color: #2f9bd8; }

/* --- Der Stein, der gerade gezogen wird ---

   Er liegt ueber allem und faengt keine Zeigerereignisse ab: die gehoeren
   dem Vorratsplatz, der den Zeiger eingefangen hat. Faenge dieses Bild
   sie ab, ginge der Zug beim ersten Bildlauf verloren.

   Seine Feldgroesse kommt aus dem Brett und steht deshalb nicht hier,
   sondern als Variable im style-Attribut -- das Raster passt sich der
   Buehne an, und der gezogene Stein muss dasselbe Mass haben, sonst
   zeigte er nicht, was er belegen wird. */
.zugstein {
    position: fixed;
    z-index: 60;
    display: grid;
    grid-template-columns: repeat(var(--breite, 1), var(--feldbreite, 1rem));
    grid-template-rows: repeat(var(--hoehe, 1), var(--feldhoehe, 1rem));
    gap: var(--luecke, 2px);
    pointer-events: none;
    filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.45));
}

.zugstein__feld {
    border-radius: 4px;
    box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.25);
}

.zugstein--passt .zugstein__feld {
    background: var(--ton-akzent);
}

/* Rot heisst nicht "Fehler", sondern "hier nicht" -- der Stein bleibt in
   der Hand, es geht nichts verloren. */
.zugstein--sperrt .zugstein__feld {
    background: var(--ton-rot);
    opacity: 0.75;
}

/* Der Platz, von dem der Stein gerade unterwegs ist, bleibt leer stehen --
   sonst laege der Stein zweimal auf dem Schirm. */
.vorratsplatz--unterwegs .steinbild {
    opacity: 0.25;
}

/* Ohne das scrollt der Browser die Seite, sobald ein Finger einen Stein
   beruehrt -- und der Stein bliebe auf halbem Weg liegen. Dieselbe Zeile
   wie beim Kartenblatt des Geo-Quiz und aus demselben Grund. */
.vorratsplatz {
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}

/* --- Farbraster: die beiden zusaetzlichen Farben ---

   Gruen und Blau kommen vom Fundraster. Violett und Rost sind so gewaehlt,
   dass sich alle vier nicht nur im Farbton unterscheiden, sondern auch in
   der Helligkeit -- wer Gruen und Blau schlecht trennt, sieht immer noch
   vier verschieden helle Felder. Rost kommt nur im schweren Grad dazu. */
.rasterfeld--violett {
    background: #9d6bd8;
    box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.3);
}

.rasterfeld--rost {
    background: #d2743a;
    box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.3);
}

.steinbild__feld.rasterfeld--gruen { background: #4fd07a; }
.steinbild__feld.rasterfeld--blau { background: #2f9bd8; }
.steinbild__feld.rasterfeld--violett { background: #9d6bd8; }
.steinbild__feld.rasterfeld--rost { background: #d2743a; }

/* Der gezogene Stein behaelt beim Farbraster seine Farben -- welche Ecke
   welche hat, ist genau die Frage, die man beim Zielen beantwortet. Ob er
   passt, sagt deshalb nur der Rahmen. */
.zugstein--bunt .zugstein__feld.rasterfeld--gruen { background: #4fd07a; }
.zugstein--bunt .zugstein__feld.rasterfeld--blau { background: #2f9bd8; }
.zugstein--bunt .zugstein__feld.rasterfeld--violett { background: #9d6bd8; }
.zugstein--bunt .zugstein__feld.rasterfeld--rost { background: #d2743a; }

.zugstein--bunt .zugstein__feld {
    box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.55),
                inset 0 -2px 0 rgba(0, 0, 0, 0.3);
}

.zugstein--verboten .zugstein__feld {
    box-shadow: inset 0 0 0 2px var(--ton-rot);
    opacity: 0.6;
}

/* =====================================================================
   Die Startseite: nur Kacheln
   =====================================================================

   Neuanfang vom 22.08.2026. Die Seite hat genau eine Aufgabe -- alle
   Spiele zeigen -- und muss das auf vier Formaten koennen: Rechner,
   Tablet quer, Tablet hoch, Telefon hoch. Deshalb keine festen
   Spaltenzahlen, sondern eine Mindestbreite je Kachel; der Browser
   rechnet aus, wie viele nebeneinander passen.

   240 Bildpunkte als Mindestmass: darunter bricht der Beschreibungssatz
   auf vier Zeilen um und die Kachel wird hoeher als breit. Auf einem
   Telefon im Hochformat (375 Punkte abzueglich Rand) ergibt das genau
   eine Spalte, auf einem Tablet quer vier bis fuenf. */

.auswahl {
    width: 100%;
    max-width: 74rem;
    margin: 0 auto;
    padding: clamp(0.6rem, 2vw, 1.4rem);
}

.kachelreihe {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: clamp(0.6rem, 1.6vw, 1rem);
}

/* Auf einem Telefon im Hochformat waere eine Kachel mit Wasserzeichen,
   Abzeichen, Titel und Satz fast ein halber Schirm hoch -- man saehe
   zwei Spiele und muesste fuer den Rest rollen. Dort wird die Kachel
   deshalb zur Zeile: Zeichen links, Name und Satz rechts daneben. */
@media (max-width: 34rem) {
    .kachelreihe {
        grid-template-columns: 1fr;
        gap: 0.45rem;
    }
}

/* Die flache Form gilt auch im Querformat -- dort ist der Schirm breit
   genug fuer zwei Spalten, aber nur 375 Punkte hoch. Eine Kachel von
   133 Punkten Hoehe liesse dort keine drei Reihen zu. Die Spaltenzahl
   haengt weiter allein an der Breite: eine einzige Zeile ueber 812
   Punkte waere ihrerseits Verschwendung. */
@media (max-width: 34rem), (max-height: 30rem) {
    .kachel--spiel {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        grid-template-areas:
            "zeichen titel"
            "zeichen text";
        align-items: center;
        column-gap: 0.8rem;
        row-gap: 0.1rem;
        padding: 0.6rem 0.8rem;
        min-height: 0;
    }

    .kachel--spiel .kachel__kopf { grid-area: zeichen; margin: 0; }
    .kachel--spiel .kachel__titel { grid-area: titel; margin: 0; }
    .kachel--spiel .kachel__text { grid-area: text; margin: 0; font-size: 0.8rem; }

    /* Das Wasserzeichen ist auf einer Zeile nur Unruhe. */
    .kachel--spiel .kachel__wasserzeichen { display: none; }
}

/* --- Der Rueckweg aus dem Vollbild --- */

.pur__zurueck {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    text-decoration: none;
}

/* Auf schmalen Schirmen bleibt der Pfeil, das Wort geht. Die Leiste
   traegt dort schon Rueckgaengig, Neues Spiel, Grad und Anleitung. */
@media (max-width: 30rem) {
    .pur__zurueckwort { display: none; }
}

/* --- Der Hinweis auf eine neue Fassung ---

   Er liegt ueber allem und verschiebt nichts. Oben und mittig: unten stehen in
   einer Partie die Knoepfe, und was von oben hereinkommt, kommt dem Daumen
   nicht in die Quere.

   Warum es ihn gibt, steht im Fassungsdienst. Kurz: der Server setzt die
   richtigen Kopfzeilen, aber ob ein Zwischenspeicher sich daran haelt,
   entscheidet nicht der Server -- und auf einem iPad tat Chrome es nicht. */
/* Mittig auf dem Schirm, nicht am oberen Rand: Hendrik will das Update sehen,
   nicht suchen (28.08.2026). "inset: 0" mit "margin: auto" zentriert einen
   fest positionierten Kasten in beiden Richtungen, sobald er eigene Masse hat
   -- dieselbe Bauart wie beim Anleitungsdialog.

   Er bleibt ein Kasten und wird kein <dialog>: er soll nichts sperren. Wer
   mitten in einer Partie ist, darf erst den Zug zu Ende machen und dann
   "Später" sagen. */
.fassungshinweis {
    position: fixed;
    inset: 0;
    margin: auto;
    z-index: 90;

    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.9rem;

    /* "fit-content" in beiden Richtungen ist die Voraussetzung fuer das
       Zentrieren ueber "margin: auto" -- ohne eigene Masse fuellte der Kasten
       den Schirm. Die Schranke holt lange Saetze auf schmalen Schirmen
       zurueck. */
    width: fit-content;
    height: fit-content;
    max-width: min(30rem, calc(100vw - 1.4rem));
    padding: 1.1rem 1.4rem;

    border: 1px solid rgba(242, 181, 68, 0.45);
    border-radius: 12px;
    background: #14301f;
    box-shadow: 0 8px 26px rgba(0, 0, 0, 0.55);
}

.fassungshinweis__wort {
    margin: 0;
    color: var(--ton-schrift);
    font-size: 1.02rem;
    font-weight: 700;
    text-align: center;
}

.fassungshinweis__taten {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

@media (prefers-reduced-motion: no-preference) {
    .fassungshinweis {
        animation: fassung-herein 0.3s ease-out both;
    }

    /* Nur Deckkraft und ein kleiner Rutsch: das Zentrieren besorgt seit dem
       28.08.2026 "margin: auto", nicht mehr ein transform. Der alte Endwert
       translateX(-50%) blieb ueber "both" dauerhaft stehen und schob den
       Kasten um seine halbe Breite aus der Mitte -- gemessen 123 Bildpunkte. */
    @keyframes fassung-herein {
        from { opacity: 0; transform: translateY(-0.7rem); }
        to { opacity: 1; transform: translateY(0); }
    }
}

/* --- Die Karten am Finger ---

   Sie liegen fest am Bildschirm und fangen keine Zeigerereignisse ab: die
   gehoeren der Karte, die den Zeiger eingefangen hat, und die Trefferpruefung
   beim Loslassen muss sehen, was DARUNTER liegt. Faenden sie die Ereignisse ab,
   laege unter dem Finger immer nur der gezogene Stapel selbst.

   Ihre Masse kommen aus dem Brett (--karte-breite, --karte-hoehe): ein
   gezogener Stapel, der anders gross waere als das Brett, zeigte nicht, was er
   belegen wird. */
.zugkarten {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 60;
    pointer-events: none;
    width: var(--karte-breite);

    /* BEWEGT WIRD MIT "transform", NICHT MIT "left" UND "top" -- und bewegt wird
       aus JavaScript heraus, nicht aus der Anwendung. Vorher setzte jede
       Mausbewegung neue Koordinaten in die Auszeichnung, und dafuer zeichnete
       Blazor das ganze Brett neu: sieben Spalten, bis zu zweiundfuenfzig
       Kartenbauteile, sechzigmal in der Sekunde. Die Karte hing entsprechend
       hinterher. Siehe kartenzug.folge.

       Der Kipp und die Vergroesserung stehen jetzt in derselben Angabe, weil
       JavaScript sie zusammen mit der Verschiebung setzt -- zwei transform-
       Angaben auf einem Element gaebe es nicht, die zweite gewaenne. */
    transform-origin: 50% 20%;
    will-change: transform;
    filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.55));

    /* Unsichtbar, bis JavaScript ihn wirklich hingelegt hat -- die Sicherung
       gegen genau den Fehler, den er am 22.08.2026 gelegentlich zeigte.
       Bekaeme er nie eine Verschiebung, laege er bei null: oben links in der
       Ecke, mitten im Bild und weit weg vom Zeiger. So bliebe er in diesem
       Fall schlicht aus, und der Zug liefe trotzdem zu Ende. */
    opacity: 0;
}

.zugkarten__blatt {
    position: absolute;
    left: 0;
    display: block;
    width: var(--karte-breite);
    height: var(--karte-hoehe);
    border-radius: var(--karte-radius);

    /* DER WEISSE GRUND GEHOERT DAZU. Die Kartengrafik zeichnet nur Rand, Werte
       und Bild -- ihre Flaeche ist durchsichtig, und das Weiss kommt bei einer
       liegenden Karte vom Kasten darunter (.karte). Der gezogene Stapel ist
       aber nur das <img>, und ohne diesen Grund sah man durch die Karten
       hindurch auf das Brett: bei einer Folge aus drei Karten ein Gewirr aus
       Umrissen. Derselbe Verlauf wie bei .karte, damit beide gleich aussehen. */
    background: linear-gradient(180deg, #ffffff 0%, #f2f4f6 100%);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.16);
}

/* Waehrend gezogen wird, bleibt die Karte an ihrem Platz blass stehen -- sonst
   klaffte in der Spalte eine Luecke, und man saehe nicht mehr, woher der Stapel
   kommt.

   Nur waehrend des Ziehens und nicht bei jeder Auswahl: wer eine Karte antippt,
   soll sie hervorgehoben sehen und nicht ausgeblichen. Das erledigt weiter
   .karte--gewaehlt mit Versatz und Rahmen. */
.brett--zieht .karte--gewaehlt {
    opacity: 0.35;

    /* Und ohne den Versatz. Er ist das Zeichen fuer "ausgewaehlt" und beim
       Ziehen doppelt gemoppelt -- die Karte haengt ja sichtbar am Finger.
       Ausserdem zaehlt eine verschobene Karte zur rollbaren Breite: in der
       letzten Spalte schob sie das Brett um zehn Bildpunkte auf und liess eine
       Rollleiste erscheinen, die niemand braucht. */
    transform: none;
}

/* --- Kennzahlen über der Hiscoretabelle ---

   Die erste Kachel wiegt doppelt: dort steht das Beste aller Zeiten, und dafuer
   kommt man auf die Seite. Die anderen ordnen es nur ein.

   ALLE DREI SEHEN GLEICH AUS. Die grosse hatte einen gruenen Rand und einen
   gruenen Grund -- auf einer ohnehin gruenen Seite war das ein Farbblock zu
   viel. Ihr Gewicht kommt jetzt aus der Breite und aus der groesseren, gruenen
   Zahl; der Kasten selbst ist derselbe wie nebenan.

   Umbruch statt Scrollen. Auf dem Telefon stehen sie zu zweit nebeneinander,
   und die grosse nimmt sich die ganze Zeile -- eine Reihe, die seitlich
   herauslaeuft, wuerde die wichtigste Zahl als erste verstecken. */
.anleitung__inhalt .tabellenrahmen {
    max-width: none;
    margin-top: 0.9rem;
}

.kennzahlen {
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem;
    margin-bottom: 1rem;
}

.kennzahl {
    flex: 1 1 8rem;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.75rem 0.9rem;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.04);
}

.kennzahl--gross {
    flex: 2 1 16rem;
}

.kennzahl__wert {
    font-size: 1.7rem;
    font-weight: 700;
    line-height: 1.05;
    font-variant-numeric: tabular-nums;
}

.kennzahl--gross .kennzahl__wert {
    font-size: 2.2rem;
    color: var(--ton-gueltig);
}

.kennzahl__name {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--ton-schrift-leise);
}

.kennzahl__fussnote {
    margin-top: 0.15rem;
    font-size: 0.72rem;
    color: var(--ton-schrift-leise);
}

/* Auf dem Telefon nimmt sich die grosse Kachel die ganze Zeile. Ohne das
   stand sie neben einer schmalen -- 226 zu 113 Bildpunkte, gemessen bei 375 --
   und die wichtigste Zahl war die gequetschte. */
@media (max-width: 30rem) {
    .kennzahl--gross {
        flex-basis: 100%;
    }
}

/* Ein Knopf, der in eine Tabellenzelle passt. */
.knopf--schmal {
    padding: 0.2rem 0.55rem;
    font-size: 0.78rem;
    white-space: nowrap;
    text-decoration: none;
}

/* Am Finger darf er nicht so flach sein: gemessen waren es vierundzwanzig
   Bildpunkte Hoehe, und danach trifft niemand. Nicht ueber die Fensterbreite
   gesteuert, sondern ueber das Zeigegeraet -- ein Tablet ist breit und wird
   trotzdem angetippt. */
@media (pointer: coarse) {
    .knopf--schmal {
        padding: 0.5rem 0.7rem;
    }
}

/* Die Zeile unter „Gelöst.": eine Bestmarke wird gefeiert, ein blosser
   Eintrag nur vermerkt. */
.meldeschirm__marke {
    color: var(--ton-gueltig);
    font-weight: 600;
}

.meldeschirm__nebenbei {
    color: var(--ton-schrift-leise);
    font-size: 0.85rem;
}


/* --- Die Kontoseite --- */
.konto {
    max-width: 60rem;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}

.konto__gruss {
    margin: 0;
    font-size: 1.05rem;
}

.konto__weg {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin: 0.4rem 0 0;
}


/* Die Hiscore-Zeile der Spielarten, die ihren Schirm selbst mitbringen.
   Schmal und ueber der Leiste -- das Ergebnis steht schon auf dem Brett, hier
   steht nur, was daraus geworden ist. */
.pur__vermerk {
    display: flex;
    justify-content: center;
    gap: 0.6rem;
    padding: 0.35rem 0.7rem 0;
    text-align: center;
}

.pur__vermerk p {
    margin: 0;
}

/* --- Wortraten ----------------------------------------------------------

   Sechs Zeilen zu fuenf Kacheln, darunter die Tastatur. Die Kachelgroesse
   kommt aus der Buehne: senkrecht muessen Gitter, Hinweiszeile und drei
   Tastenreihen uebereinander passen, waagerecht fuenf Kacheln nebeneinander
   -- die kleinere der beiden Schranken gewinnt, wie bei den Kartenbrettern. */
.wortraten {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(0.6rem, 2cqh, 1.1rem);
    outline: none;
    touch-action: manipulation;

    /* Zoom aussen um die Schranken -- die Begruendung steht bei --karte-breite. */
    --wortfeld: calc(clamp(38px, min(16cqw, 9.5cqh), 62px) * var(--zoom, 1));
}

.wortraten__gitter {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.wortzeile {
    display: flex;
    gap: 6px;
}

.wortfeld {
    width: var(--wortfeld);
    height: var(--wortfeld);
    display: grid;
    place-items: center;
    border: 2px solid rgba(255, 255, 255, 0.22);
    border-radius: 8px;
    font-size: calc(var(--wortfeld) * 0.52);
    font-weight: 800;
    text-transform: uppercase;
    color: var(--ton-schrift);
    user-select: none;
}

.wortfeld--getippt {
    border-color: rgba(255, 255, 255, 0.55);
}

/* Die drei Antworten. Deckende Flaechen mit dunkler Schrift: die Farbe IST
   hier die Information, sie darf nicht im Hintergrund versinken. */
.wortfeld--richtig {
    background: #57d98a;
    border-color: #57d98a;
    color: #0d2417;
}

.wortfeld--enthalten {
    background: #f2b544;
    border-color: #f2b544;
    color: #2b1f07;
}

.wortfeld--fehlt {
    background: rgba(255, 255, 255, 0.10);
    border-color: transparent;
    color: var(--ton-schrift-leise);
}

.wortraten__hinweis {
    margin: 0;
    color: var(--ton-schrift-leise);
    font-size: 0.85rem;
    min-height: 1.2em;
}

.wortraten__aufloesung {
    margin: 0;
    font-size: 1rem;
    color: var(--ton-schrift);
    letter-spacing: 0.02em;
}

.worttasten {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}

.worttasten__reihe {
    display: flex;
    gap: 5px;
}

.worttaste {
    appearance: none;
    border: 0;
    border-radius: 6px;
    min-width: clamp(26px, 8.4cqw, 42px);
    height: clamp(40px, 6.4cqh, 54px);
    padding: 0 4px;
    background: rgba(255, 255, 255, 0.14);
    color: var(--ton-schrift);
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 700;
    cursor: pointer;
    user-select: none;
}

.worttaste:disabled {
    opacity: 0.45;
    cursor: default;
}

.worttaste--breit {
    min-width: clamp(52px, 14cqw, 72px);
    font-size: 0.8rem;
}

.worttaste--richtig { background: #57d98a; color: #0d2417; }
.worttaste--enthalten { background: #f2b544; color: #2b1f07; }
.worttaste--fehlt { background: rgba(255, 255, 255, 0.05); color: var(--ton-schrift-leise); }

/* --- Quiz ---------------------------------------------------------------

   Bühne und Leiter nebeneinander: die Frage braucht Breite, die Leiter
   braucht Hoehe, und zusammen fuellen sie einen Bildschirm im Querformat
   ohne Leerlauf. Auf dem Telefon wird daraus eine Spalte -- die Leiter
   rutscht dann unter die Antworten, wo sie nachgeschlagen und nicht
   beobachtet wird. */
/* Wie beim Kniffelblock: ein Schriftstueck, kein gerechnetes Brett -- deshalb
   "zoom" statt eines Faktors in der Groessenrechnung. Die Container-Abfragen
   darin messen danach die gezoomte Breite, und das ist richtig so: Bei halber
   Groesse ist der Kasten in CSS-Pixeln doppelt so breit und darf die Antworten
   nebeneinander behalten. */
.quiz {
    zoom: var(--zoom, 1);

    display: flex;
    align-items: stretch;
    justify-content: center;
    gap: 1.2rem;
    width: 100%;
    max-width: 60rem;
    margin: 0 auto;
    container-type: inline-size;
}

.quiz__buehne {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    justify-content: center;
    gap: 0.9rem;
    min-width: 0;
}

.quiz__gebiet {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.8rem;
    margin: 0;
    font-size: 0.8rem;
    color: var(--ton-schrift-leise);
}

.quiz__fach {
    color: var(--ton-akzent);
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

/* Die Frage traegt das Spiel und bekommt deshalb Raum. Sie waechst mit der
   Breite der Buehne, hoert aber bei 1.5rem auf: darueber braucht ein langer
   Satz drei Zeilen, und drei Zeilen Frage schieben die Antworten aus dem
   Bild. */
/* Drei Zeilen Frage plus Innenabstand. Dieselbe Ueberlegung wie bei 50:50 --
   die Begruendung steht dort ausfuehrlich. */
.quiz__frage {
    display: grid;
    place-items: center;
    min-height: calc(4.05em + 2rem);
    margin: 0;
    padding: 1rem 1.1rem;
    background: rgba(0, 0, 0, 0.28);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 12px;
    font-size: clamp(1rem, 2.6cqw, 1.5rem);
    line-height: 1.35;
    text-wrap: balance;
}

/* Zwei Spalten, solange sie passen. Vier untereinander waeren auf einem
   breiten Schirm eine sehr lange Liste, und man liest sie dann von oben
   nach unten statt sie zu ueberblicken. */
.quiz__antworten {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
}

@container (max-width: 32rem) {
    .quiz__antworten {
        grid-template-columns: minmax(0, 1fr);
    }

    /* EINE ZEILE MEHR IM SCHMALEN RAHMEN.

       Die Schriftgroesse der Frage faellt mit der Breite, aber nur bis zu
       ihrer Untergrenze -- darunter wird der Kasten schmaler, ohne dass die
       Schrift kleiner wird, und der Text braucht eine Zeile mehr. Gemessen am
       29.08.2026: bei 320 bis 340 Bildpunkten Rahmenbreite laufen die
       laengsten echten Fragen ("Wer fuehrte Regie bei ,Harry Potter und die
       Heiligtuemer des Todes - Teil 2'?") auf vier Zeilen und schoben die
       Antworten um zwei Bildpunkte. Wenig, aber es ist genau das, was hier
       nicht passieren soll. */
    .quiz__frage {
        min-height: calc(5.4em + 2rem);
    }
}

/* Gleich hoch, ob die Antwort „Rom“ heisst oder „Vereinigte Arabische
   Emirate“ -- sonst ist die Knopfreihe mal ein-, mal zweizeilig. */
.quizantwort {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    min-height: 3.1rem;
    padding: 0.7rem 0.9rem;
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 10px;
    color: var(--ton-schrift);
    font-family: inherit;
    font-size: 0.95rem;
    text-align: left;
    cursor: pointer;
    transition: background 90ms linear, border-color 90ms linear;
}

button.quizantwort:hover:not(:disabled) {
    background: rgba(242, 181, 68, 0.14);
    border-color: var(--ton-akzent);
}

/* Der Buchstabe ist die Anfassflaeche fuer das Auge: er steht immer an
   derselben Stelle, waehrend die Antworten verschieden lang sind. */
.quizantwort__zeichen {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 1.7rem;
    height: 1.7rem;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.1);
    color: var(--ton-akzent);
    font-weight: 700;
    font-size: 0.85rem;
}

.quizantwort__wort { min-width: 0; }

/* Die Aufloesung. Gruen und rot wie ueberall im Projekt; was weder das eine
   noch das andere ist, tritt zurueck -- es war nie zur Debatte. */
.quizantwort--richtig {
    background: rgba(87, 217, 138, 0.2);
    border-color: var(--ton-gueltig);
}

.quizantwort--richtig .quizantwort__zeichen {
    background: var(--ton-gueltig);
    color: #0b1a14;
}

.quizantwort--daneben {
    background: rgba(255, 123, 123, 0.18);
    border-color: var(--ton-daneben);
}

.quizantwort--daneben .quizantwort__zeichen {
    background: var(--ton-daneben);
    color: #2a0f0f;
}

.quizantwort--blass { opacity: 0.45; }

/* Einsatzzeile und Auflösungszeile loesen einander ab und muessen deshalb
   gleich hoch sein. In der Einsatzzeile steht mal ein Knopf („Aufhoeren mit
   …“) und mal nicht -- auch das waere ein Sprung. */
.quiz__einsatz {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem 1.1rem;
    min-height: 2.9rem;
    font-size: 0.85rem;
    color: var(--ton-schrift-leise);
}

.quiz__aufhoeren { margin-left: auto; }

.quiz__urteil {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    min-height: 2.9rem;
}

.quiz__richtig { margin: 0; color: var(--ton-gueltig); }
.quiz__falsch  { margin: 0; color: var(--ton-daneben); }

.quiz__ende {
    text-align: center;
}

.quiz__endwort {
    margin: 0 0 0.3rem;
    font-size: 1.1rem;
    color: var(--ton-schrift-leise);
}

.quiz__endpunkte {
    margin: 0;
    font-size: clamp(2rem, 8cqw, 3.4rem);
    font-weight: 700;
    color: var(--ton-akzent);
    line-height: 1.1;
}

.quiz__endzeile {
    margin: 0.3rem 0 0;
    color: var(--ton-schrift-leise);
}

/* --- Die Leiter ---

   Von oben nach unten gelesen, wie beim Vorbild: die grosse Zahl steht oben,
   und man arbeitet sich hinauf. */
.quizleiter {
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 0;
    list-style: none;
    font-variant-numeric: tabular-nums;
}

.quizleiter__sprosse {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.7rem;
    padding: 0.25rem 0.6rem;
    border-radius: 6px;
    font-size: 0.8rem;
    color: var(--ton-schrift-leise);
}

.quizleiter__nummer {
    opacity: 0.55;
    font-size: 0.72rem;
}

/* Eine Sicherheitsstufe steht heller und traegt einen Strich links -- sie ist
   der Boden, auf den man faellt, und das soll man vorher sehen. */
.quizleiter__sprosse--sicher {
    border-left: 3px solid var(--ton-gueltig);
    color: var(--ton-schrift);
    font-weight: 600;
}

.quizleiter__sprosse--geschafft {
    color: var(--ton-gueltig);
}

.quizleiter__sprosse--dran {
    background: var(--ton-akzent-schwach);
    color: var(--ton-akzent);
    font-weight: 700;
}

/* Auf dem Telefon unter die Antworten und quer: senkrecht kostete sie dort
   zwoelf Zeilen Hoehe, die dem Brett fehlen. Waagerecht laesst sie sich
   schieben und bleibt trotzdem nachschlagbar. */
@container (max-width: 32rem) {
    .quiz {
        flex-direction: column;
    }

    .quizleiter {
        flex-direction: row-reverse;
        justify-content: flex-end;
        overflow-x: auto;
        gap: 0.3rem;
        scrollbar-width: none;
    }

    .quizleiter::-webkit-scrollbar { display: none; }

    .quizleiter__sprosse {
        flex: 0 0 auto;
        flex-direction: column;
        align-items: center;
        gap: 0;
        padding: 0.2rem 0.45rem;
    }

    .quizleiter__sprosse--sicher {
        border-left: none;
        border-bottom: 3px solid var(--ton-gueltig);
    }
}

/* --- 50:50 --------------------------------------------------------------

   Eine Spalte, mittig: der Gegenstand steht gross in der Mitte, die beiden
   Antworten darunter. Keine Leiter wie beim Quiz -- hier gibt es keinen
   Aufstieg, nur eine Rechnung, und die steht als Zaehler oben. */
/* Siehe „.quiz“: Schriftstueck, deshalb „zoom“. */
.zweiwahl {
    zoom: var(--zoom, 1);

    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1rem;
    width: 100%;
    max-width: 44rem;
    margin: 0 auto;
    text-align: center;
    container-type: inline-size;
}

.zweiwahl__zaehler {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.8rem;
    margin: 0;
    font-size: 0.8rem;
    color: var(--ton-schrift-leise);
}

.zweiwahl__stand { font-variant-numeric: tabular-nums; }

/* Die Frage steht klein, der Gegenstand gross: bei zwanzig Fragen wiederholt
   sich der Titel oft, und was sich aendert, gehoert in die Mitte. */
/* FESTE HOEHEN AB HIER -- die Knoepfe sollen stehen bleiben.

   Alles ueber den Knoepfen aendert seine Hoehe mit dem Inhalt: „Rhabarber“
   ist einzeilig, „Johann Sebastian Bach“ zweizeilig, und die Aufloesungszeile
   kommt erst nach der Antwort dazu. Weil die Buehne ihren Inhalt senkrecht
   zentriert, wandert dann alles -- und der Knopf, auf den man gerade zielt,
   springt unter dem Finger weg.

   Gegenmittel: jede veraenderliche Zeile bekommt die Hoehe ihres schlimmsten
   Falls und zentriert ihren Inhalt darin. Das kostet etwas Luft und ist es
   wert. Die Zeilenhoehen stehen in em, damit sie der Schriftgroesse folgen --
   die waechst hier mit der Breite der Buehne. */
.zweiwahl__titel {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 2.6em;
    margin: 0;
    color: var(--ton-akzent);
    font-size: 0.9rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}

/* Zwei Zeilen Text plus Innenabstand -- laenger ist kein Gegenstand in den
   Listen, und ein dritter Zeilenumbruch waere ohnehin ein Zeichen, dass der
   Eintrag zu lang ist. */
.zweiwahl__gegenstand {
    display: grid;
    place-items: center;
    min-height: calc(2.4em + 2.2rem);
    margin: 0;
    padding: 1.1rem 1rem;
    background: rgba(0, 0, 0, 0.28);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 12px;
    font-size: clamp(1.4rem, 6cqw, 2.6rem);
    font-weight: 600;
    line-height: 1.2;
    text-wrap: balance;
}

/* Nebeneinander, gleich breit: zwei gleichwertige Moeglichkeiten sollen auch
   gleich aussehen. Uebereinander waere die obere die naheliegende. */
.zweiwahl__knoepfe {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.7rem;
}

@container (max-width: 26rem) {
    .zweiwahl__knoepfe {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Dieselbe Reserve wie bei der Quizfrage und aus demselben Grund: unter
       rund 340 Bildpunkten braucht der laengste Gegenstand ("Mecklenburgische
       Seenplatte", "Carl Ditters von Dittersdorf") drei Zeilen statt zwei. */
    .zweiwahl__gegenstand {
        min-height: calc(3.6em + 2.2rem);
    }
}

.zweiwahlknopf {
    display: grid;
    place-items: center;
    min-height: 3.2rem;
    padding: 0.7rem 0.9rem;
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 10px;
    color: var(--ton-schrift);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 90ms linear, border-color 90ms linear;
}

button.zweiwahlknopf:hover:not(:disabled) {
    background: rgba(242, 181, 68, 0.14);
    border-color: var(--ton-akzent);
}

.zweiwahlknopf--richtig {
    background: rgba(87, 217, 138, 0.2);
    border-color: var(--ton-gueltig);
    color: var(--ton-gueltig);
}

.zweiwahlknopf--daneben {
    background: rgba(255, 123, 123, 0.18);
    border-color: var(--ton-daneben);
    color: var(--ton-daneben);
}

.zweiwahlknopf--blass { opacity: 0.4; }

/* Auch wenn nichts darin steht: die Zeile ist waehrend der Frage leer und
   traegt trotzdem ihre Hoehe. Sonst schoebe die Aufloesung die Knoepfe nach
   oben, kaum dass man sie getroffen hat. */
.zweiwahl__urteil {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 0.8rem;
    min-height: 2.9rem;
}

.zweiwahl__richtig { margin: 0; color: var(--ton-gueltig); }
.zweiwahl__falsch  { margin: 0; color: var(--ton-daneben); }

.zweiwahl__endwort {
    margin: 0 0 0.3rem;
    font-size: 1.1rem;
    color: var(--ton-schrift-leise);
}

.zweiwahl__endpunkte {
    margin: 0;
    font-size: clamp(2rem, 9cqw, 3.4rem);
    font-weight: 700;
    color: var(--ton-akzent);
    line-height: 1.1;
}

.zweiwahl__endzeile {
    margin: 0.3rem 0 0;
    color: var(--ton-schrift-leise);
}

/* --- Die Zoomwippe -------------------------------------------------------

   Drei Knoepfe in einem Kasten, wie ein Schalter und nicht wie drei einzelne
   Knoepfe: Sie gehoeren zusammen, und in einer Leiste voller Knoepfe muss man
   das sehen koennen. */
.zoomwippe {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 9px;
    background: rgba(0, 0, 0, 0.3);
    flex-shrink: 0;
}

.zoomwippe__knopf,
.zoomwippe__stand {
    border: 0;
    background: transparent;
    color: var(--ton-schrift);
    font-family: inherit;
    border-radius: 7px;
    cursor: pointer;
    transition: background 90ms linear, color 90ms linear;
}

.zoomwippe__knopf {
    display: grid;
    place-items: center;
    width: 1.9rem;
    height: 1.7rem;
    font-size: 1.05rem;
    line-height: 1;
}

/* Die Stufe ist zugleich der Weg zurueck: ein Druck darauf stellt die
   gewohnte Groesse wieder her. Deshalb ist sie ein Knopf und kein Text --
   und deshalb ist sie abgeschaltet, solange es nichts zurueckzustellen gibt.

   Feste Ziffernbreite, sonst wackelt die ganze Wippe zwischen „90 %“ und
   „100 %“ -- und sie sitzt in einer Leiste, in der daneben noch etwas steht. */
.zoomwippe__stand {
    min-width: 3.4rem;
    height: 1.7rem;
    padding: 0 0.3rem;
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
    color: var(--ton-schrift-leise);
}

.zoomwippe__knopf:hover:not(:disabled),
.zoomwippe__stand:hover:not(:disabled) {
    background: rgba(242, 181, 68, 0.16);
    color: var(--ton-akzent);
}

.zoomwippe__knopf:disabled,
.zoomwippe__stand:disabled {
    opacity: 0.4;
    cursor: default;
}

.zoomwippe__knopf:focus-visible,
.zoomwippe__stand:focus-visible {
    outline: 2px solid var(--ton-akzent);
    outline-offset: 1px;
}
