/*
 * Die Aufbau-Proben — drei Entwürfe neben dem Ursprung.
 *
 * JEDER Selektor hier steht hinter einem `[data-aufbau="…"]`-Gatter am
 * <html>. Ohne gesetztes Attribut (Aufbau „klassisch") trifft keine einzige
 * Regel — das ist die Rückfahrkarte. Warum es die Proben gibt und was jede
 * will, steht in js/core/aufbau.js; die Messwerte dahinter im Entwurf
 * „Platz am Tisch" (2026-08-27).
 *
 * Rückbau: diese Datei löschen, den <link> in index.php entfernen —
 * game.css weiß von alledem nichts.
 */

/* =========================================================== Gemeinsames
 *
 * Alles in diesem Block gilt für alle drei Proben. Die Doppelnennung der
 * Attributwerte statt eines `:not([data-aufbau="klassisch"])` ist Absicht:
 * Ein künftiger vierter Wert soll leer starten, nicht versehentlich alle
 * Gemeinsamkeiten erben.
 */

/* Platz für die Handkante am unteren Rand. Sie ist fest (fixed) und läge
 * sonst über dem Impressum und der letzten Karte. Das Polster steht auch
 * dann, wenn die Leiste gerade leer und versteckt ist — eine Seite, die
 * beim Phasenwechsel um 6 rem springt, wäre schlimmer als der Leerraum.
 *
 * `--hand-hoehe` ist GEMESSEN, nicht geschätzt (ui/handkante.js, dort steht
 * die Begründung): Die Höhe hängt daran, ob die Beschriftungen der Knöpfe
 * umbrechen, und die Leiste rechnet den Sicherheitsabstand des Geräts in
 * ihre eigene Polsterung ein. Die feste Zahl war beides nicht gewachsen —
 * auf einem Handy mit Gestenleiste lag der letzte Inhalt dahinter
 * (15.09.2026). Der Rückfallwert ist der alte Wert, für die Lücke vor der
 * ersten Messung. Ein halber Schritt Luft obendrauf, damit die letzte Karte
 * die Knöpfe nicht berührt. */
[data-aufbau="handkante"] .seite,
[data-aufbau="buehne"] .seite,
[data-aufbau="ring"] .seite {
    padding-bottom: calc(var(--hand-hoehe, 6.5rem) + var(--s3));
}

/* Der Fußbereich (Impressum, Datenschutz, Spielregeln, Kodex) liegt
 * AUSSERHALB von .seite — das Polster oben half ihm nicht, und die
 * schwebende Handkante fiel über die Links (gemeldet 2026-08-28).
 * Deshalb: eigenes Polster in Leistenhöhe, damit sie am Seitenende
 * unter der Leiste hervorkommen, und eine Nummer kleiner — es sind
 * Pflichtangaben, keine Einladung. */
[data-aufbau="handkante"] .impressum,
[data-aufbau="buehne"] .impressum,
[data-aufbau="ring"] .impressum {
    font-size: var(--f-winzig);
    /* `--hand-hoehe` enthält den Sicherheitsabstand schon (er steckt in der
       Polsterung der Leiste) — er darf hier also nicht zweimal drauf. Der
       Rückfallwert behält die Fassung vom 28.08. */
    padding-bottom: var(--hand-hoehe, calc(6.5rem + env(safe-area-inset-bottom, 0px)));
}

/* Das Raster auf Schmal: zwei bis drei Spalten statt einer.
 *
 * Gemessen: `.tisch` verlangt mit minmax(10rem, …) 332 px Innenbreite für
 * die zweite Spalte, die Polster von Seite und Karte lassen auf einem
 * 375er aber nur 295 übrig — deshalb der eine bildschirmbreite Kopf. Mit
 * 6 rem Mindestbreite stehen dort zwei Spalten (ab 412 px drei), und acht
 * Spieler schrumpfen von ~2400 auf ~700 px. Der Ring hat kein Raster und
 * braucht die Regel nicht. */
@media (max-width: 48rem) {
    [data-aufbau="handkante"] .tisch,
    [data-aufbau="buehne"] .tisch {
        grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr));
    }
}

/* Die Anleitung zeigt zwei Zeilen und wächst auf Tipp.
 *
 * Der volle Text wird im selben Moment VORGELESEN — wer ihn hört, braucht
 * ihn nicht zu lesen; wer nachlesen will, tippt. Der Tipp-Umschalter hängt
 * in anleitungsKarte() (spiel.js) und ist ohne diese Regeln wirkungslos,
 * darum darf er dort ungegattert stehen. */
[data-aufbau="handkante"] .anleitung__text,
[data-aufbau="buehne"] .anleitung__text,
[data-aufbau="ring"] .anleitung__text {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    cursor: pointer;
}
[data-aufbau="handkante"] .anleitung__text--offen,
[data-aufbau="buehne"] .anleitung__text--offen,
[data-aufbau="ring"] .anleitung__text--offen {
    -webkit-line-clamp: unset;
}

/* ========================================================== Die Handkante
 *
 * Eine feste Leiste am unteren Rand. Sie baut sich nicht selbst: Nach jedem
 * Neuzeichnen sammelt ui/handkante.js die Sprechtaste und den einen
 * glühenden Knopf des Augenblicks ein und legt sie hier hinein — dieselben
 * Elemente, keine Kopien, die Klickgriffe reisen mit.
 *
 * Die Leiste dient auch Bühne und Ring: Dort verschwände die Sprechtaste
 * sonst in einer Schublade, und eine Sprechtaste, die man erst suchen muss,
 * ist keine. */
.handkante {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 40;                     /* über dem Inhalt, unter Toasts (60) */
    display: flex;
    gap: var(--s3);
    align-items: stretch;
    padding: var(--s3) var(--s4)
             calc(var(--s3) + env(safe-area-inset-bottom, 0px));
    /* KEIN Kasten. Die erste Fassung hatte hier eine dunkle, geblurte
     * Fläche mit Oberkante — auf dem Handy ein schwarzer Balken. Jetzt
     * schweben nur die Knöpfe; ein kaum sichtbarer Verlauf nach unten
     * sorgt dafür, dass durchscrollender Text sie nicht anknabbert, und
     * damit er nicht klickt, wo kein Knopf ist: pointer-events nur auf
     * den Plätzen. */
    background: linear-gradient(180deg, transparent,
                color-mix(in srgb, var(--grund) 55%, transparent) 70%);
    pointer-events: none;
}
.handkante > * { pointer-events: auto; }
.handkante .knopf,
.handkante .sprechtaste {
    box-shadow: 0 6px 20px rgba(0, 0, 0, .55);
}
.handkante[hidden] { display: none; }

/* Beide Bewohner teilen sich die Breite; allein bekommt einer alles. */
.handkante > * { flex: 1; min-width: 0; }
.handkante .sprechtaste { margin: 0; }

/* ============================================================== Die Bühne
 *
 * Erst die Gesichter, dann der Knopf: Die linke Spalte trägt im Ursprung
 * [Aktion, Tisch] — hier dreht `order` die beiden um. Der Daumen ist nach
 * dem Antippen eines Gesichts schon unten, wo der Knopf jetzt steht (bzw.
 * die Handkante ihn trägt). */
[data-aufbau="buehne"] .spielraum > .stapel > :first-child {
    order: 2;
}

/* ================================================== Schubladen (Bühne+Ring)
 *
 * Die Seitenspalte — Rolle, Ton, Chat, Verlauf — kostet auf Schmal weitere
 * 1000+ px unter dem Tisch, dauerhaft ausgeklappt. Hier verschwindet sie
 * und kommt als Bodenblatt wieder, wenn ihr Chip angetippt wird. Die Chips
 * baut ui/schubladen.js; die Karten selbst bleiben dieselben DOM-Knoten,
 * ihr Inhalt (Chat-Entwurf, Sprachchat-Zustand) übersteht das Öffnen und
 * Schließen deshalb unangetastet. */
[data-aufbau="buehne"] .spielraum__seite,
[data-aufbau="ring"] .spielraum__seite {
    display: none;
}
[data-aufbau="buehne"] .spielraum__seite.spielraum__seite--offen,
[data-aufbau="ring"] .spielraum__seite.spielraum__seite--offen {
    display: flex;
    position: fixed;
    inset: auto 0 0 0;
    z-index: 45;                              /* über der Handkante (40) */
    max-height: min(70vh, 34rem);
    overflow-y: auto;
    margin: 0;
    padding: var(--s4) var(--s4)
             calc(var(--s5) + env(safe-area-inset-bottom, 0px));
    background: var(--grund-erhoben);
    border-top: 1px solid var(--rand-hell);
    border-radius: var(--r-gross) var(--r-gross) 0 0;
    box-shadow: 0 -12px 40px rgba(0, 0, 0, .5);
}

/* Am Rechner (zweispaltig ab 62 rem) hat die Seitenspalte ihren Platz —
 * dort bleibt sie stehen, und die Chips versteckt schubladen.js. */
@media (min-width: 62rem) {
    [data-aufbau="buehne"] .spielraum__seite,
    [data-aufbau="ring"] .spielraum__seite {
        display: flex;
        position: static;
        max-height: none;
        box-shadow: none;
        border: 0;
        border-radius: 0;
        padding: 0;
        background: none;
    }
}

.schubladen {
    display: flex;
    gap: var(--s2);
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: var(--s4);
}
.schubladen[hidden] { display: none; }
@media (min-width: 62rem) {
    [data-aufbau="buehne"] .schubladen,
    [data-aufbau="ring"] .schubladen { display: none; }
}

.schubladen__chip {
    font: inherit;
    font-size: var(--f-klein);
    color: var(--text-leise);
    background: var(--flaeche);
    border: 1px solid var(--rand-hell);
    border-radius: var(--r-rund);
    padding: .3rem .8rem;
    min-height: 2.2rem;
    cursor: pointer;
}
.schubladen__chip[aria-expanded="true"] {
    color: var(--eisen-glut);
    border-color: color-mix(in srgb, var(--eisen-glut) 55%, var(--rand));
    background: color-mix(in srgb, var(--eisen-glut) 12%, var(--flaeche));
}
.schubladen__chip:focus-visible {
    outline: 2px solid var(--dorf);
    outline-offset: 2px;
}
/* Der Glutpunkt: Im Fach liegt Ungelesenes. Atmet leicht, damit er
 * auffällt, ohne zu schreien; bei reduzierter Bewegung steht er still
 * (tokens.css schaltet Animationen global ab). */
.schubladen__chip { position: relative; }
.schubladen__chip--neu::after {
    content: '';
    position: absolute;
    top: -3px;
    right: -3px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--eisen-glut);
    box-shadow: 0 0 8px color-mix(in srgb, var(--eisen-glut) 80%, transparent);
    animation: chip-glut 2s ease-in-out infinite;
}
@keyframes chip-glut {
    50% { box-shadow: 0 0 14px var(--eisen-glut); }
}

.schublade__zu {
    margin-left: auto;
    align-self: flex-start;
}
/* Am Rechner steht die Spalte offen daneben — ein „Schließen" wäre dort
 * eine Frage ohne Tür. */
@media (min-width: 62rem) {
    [data-aufbau="buehne"] .schublade__zu,
    [data-aufbau="ring"] .schublade__zu { display: none; }
}

/* =============================================================== Der Ring
 *
 * Der Bildschirm ist der Tisch: die Kacheln des Ursprungs, aber rund, klein
 * und im Kreis gestellt — spielerRing() in spiel.js rechnet die Plätze und
 * nutzt dieselbe spielerKachel() wie das Raster, damit ALLE Zustände
 * (wählbar, gewählt, tot, spricht, Wolf, verliebt) ohne zweite Pflege
 * mitkommen. In der Mitte: das Wort zum Augenblick und der Griff, in den
 * die Handkanten-Sammlung den glühenden Knopf legt. */
[data-aufbau="ring"] .tischring {
    position: relative;
    width: 100%;
    max-width: 30rem;
    margin: 0 auto;
    aspect-ratio: 1 / 1.05;
    /* Über dem Nachtschleier (z-index 1): Der dunkelt die Seite nachts
       zum unteren Rand hin um bis zu 55 % ab — Stimmung fürs Dorf, aber
       die Gesichter der LEBENDEN am Tisch soffen darin ab. Die Runde
       sitzt im Feuerschein, das Dunkel gehört der Kulisse dahinter. */
    z-index: 2;
}

[data-aufbau="ring"] .tischring__platz {
    position: absolute;
    transform: translate(-50%, -50%);
    /* Um 11 % gegenüber dem ersten Wurf angehoben (Nutzerwunsch,
       2026-08-28 in zwei Schritten): Die Gesichter sollen auch am Handy
       als Gesichter lesbar sein, nicht als Punkte. Der Doppelkranz ab
       elf behält seine eigene, gemessen kollisionsfreie Größe. */
    width: clamp(4rem, 18.9vw, 5.75rem);
}

/* Die Kachel wird zum runden Kopf: Fläche und Rahmen fallen weg, der
 * Zustand wandert an den runden Bildrand. */
[data-aufbau="ring"] .tischring .spieler {
    background: none;
    border: 0;
    padding: 0;
    gap: 2px;
}
[data-aufbau="ring"] .tischring .spieler__bild {
    border-radius: 50%;
    border-width: 2px;
    font-size: 1.6rem;
}
/* Der Name als Plakette, die über den unteren Kreisrand lappt.
 *
 * Im runden Fenster war er unlesbar: Der Kreisbeschnitt schnitt ihn an.
 * Deshalb wandert der Beschnitt vom Bild-Container auf den Bildträger
 * (der Kreis bleibt), und der Name darf hinaus — breiter als der Kopf
 * und ein Stück in ihn hineingerückt. Lange Namen kürzt das Auslassungs-
 * zeichen bei 6,5 rem, sonst träfen sich die Plaketten der Nachbarn. */
[data-aufbau="ring"] .tischring .spieler__bild {
    overflow: visible;
}
[data-aufbau="ring"] .tischring .sinnbild-traeger {
    border-radius: 50%;
    overflow: hidden;
}
[data-aufbau="ring"] .tischring .spieler__name {
    position: absolute;
    left: 50%;
    bottom: -0.4em;
    transform: translateX(-50%);
    width: max-content;
    max-width: 6.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: .05em .5em;
    border-radius: var(--r-rund);
    background: color-mix(in srgb, var(--grund) 78%, transparent);
    font-size: var(--f-winzig);
    color: var(--text);
    line-height: 1.5;
}
/* Die Rollenzeile hätte im Kreis keinen Platz — was sie trägt (eigene
 * Rolle, verliebt), steht weiterhin in der Rollen-Schublade. */
[data-aufbau="ring"] .tischring .spieler__rolle { display: none; }

/* Die bekannte Rolle lehnt als KÄRTCHEN am Rund — leicht gekippt, mit
 * Rand und Schlagschatten, wie eine Karte, die jemand ans Bild gestellt
 * hat. Sie tritt an die Stelle des Wolfs-Emojis und gilt für jede
 * bekannte Rolle. Das Gesicht bleibt daneben stehen: Man erkennt den
 * Menschen UND weiß, welche Karte er hatte.
 *
 * Sie darf über den Kreis hinausragen — .spieler__bild steht im Ring auf
 * `overflow: visible` (dieselbe Freiheit nutzt die Namensplakette). */
[data-aufbau="ring"] .tischring .spieler__karte {
    position: absolute;
    /* An der linken Flanke, NICHT am Fuß: Unten hängt die Namensplakette,
     * und beide zusammen deckten sich (nachgemessen). */
    left: -22%;
    bottom: 22%;
    width: 40%;
    height: auto;
    aspect-ratio: 640 / 936;
    object-fit: cover;
    object-position: 50% 22%;
    border-radius: 3px;
    border: 1px solid color-mix(in srgb, var(--mond) 40%, var(--rand-hell));
    background: var(--flaeche);
    box-shadow: 0 2px 7px rgba(0, 0, 0, .75);
    transform: rotate(-9deg);
}

/* Das Wolfs-Emoji hat ausgedient, wo das Kärtchen lehnt — es sagt
 * dasselbe, nur genauer, und beide nebeneinander wären ein Gedränge. */
[data-aufbau="ring"] .tischring .spieler--karte .spieler__bild::before {
    content: none;
}

/* Ausgeschiedene: Das GESICHT verblasst und ergraut, der Name nicht.
 * Die Grundregel (game.css) dämpft die ganze Kachel — im Ring hängt die
 * Namensplakette aber mit im Bild-Container und wurde unlesbar. Deshalb
 * hier: Kachel voll, nur der Bildträger gedämpft; das ✕ und der Name
 * bleiben klar. */
[data-aufbau="ring"] .tischring .spieler--tot {
    opacity: 1;
    filter: none;
}
/* Ausgeschiedene werden SCHWARZ-WEISS, nicht dunkel (Wunsch 2026-08-30):
 * Abgedunkelt verschwanden sie halb im Nachtgrund; entfärbt bleiben sie
 * erkennbar und sind trotzdem auf einen Blick draußen. Gilt fürs Gesicht
 * UND fürs Kärtchen — beide gehören zu einem, der nicht mehr mitspielt. */
[data-aufbau="ring"] .tischring .spieler--tot .sinnbild-traeger,
[data-aufbau="ring"] .tischring .spieler--tot .spieler__bild img {
    opacity: 1;
    filter: grayscale(1);
}
/* Und der Totenschleier nimmt sich zurück — das ✕ genügt als Zeichen,
 * die Entfärbung sagt den Rest. */
[data-aufbau="ring"] .tischring .spieler--tot .spieler__bild::after {
    background: rgba(13, 15, 22, .18);
    font-size: 1.3rem;
    text-shadow: 0 1px 4px rgba(0, 0, 0, .9);
}

[data-aufbau="ring"] .tischring .spieler--waehlbar .spieler__bild {
    border-color: var(--rand-hell);
}
[data-aufbau="ring"] .tischring .spieler--gewaehlt .spieler__bild {
    border-color: var(--mond);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mond) 45%, transparent);
}
[data-aufbau="ring"] .tischring .spieler--ich .spieler__bild {
    border-color: var(--dorf);
}
/* Deutlich, nicht dezent: Am kleinen runden Kopf ging der 2-px-Rand
 * unter (gemeldet 2026-08-28 — die Anzeige LIEF, im Protokoll standen
 * die Klassen sekundengenau, nur sah man sie kaum). Jetzt pulst der
 * Schein wie bei den Sprechern am Lagerfeuer; wer Bewegung reduziert
 * hat, behält den kräftigen stehenden Schein. */
[data-aufbau="ring"] .tischring .spieler--spricht .spieler__bild {
    border-color: var(--gruen);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gruen) 60%, transparent),
                0 0 18px color-mix(in srgb, var(--gruen) 70%, transparent);
    animation: tischring-spricht 1.4s ease-in-out infinite;
}
@keyframes tischring-spricht {
    50% {
        box-shadow: 0 0 0 6px color-mix(in srgb, var(--gruen) 35%, transparent),
                    0 0 28px color-mix(in srgb, var(--gruen) 80%, transparent);
    }
}

[data-aufbau="ring"] .tischring__mitte {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 46%;
    aspect-ratio: 1;
    border-radius: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--s2);
    text-align: center;
    padding: var(--s3);
    /* Die Tischplatte — Wirtshausholz von oben, mit Feuerschein von der
       Seite (Casting 2026-08-28, Wurf „leer-2"; Skript tischbilder.py im
       Scratchpad, Seed über rb.seed_fuer reproduzierbar). Darüber eine
       leichte Vignette, damit das Wort in der Mitte auf jeder Maserung
       lesbar bleibt.

       Seit 2026-09-01 bewegt: das Teelicht flackert (platte-bewegt.webp,
       animiertes WebP, 4,2 s in Endlosschleife). Bewusst WebP und nicht
       MP4 — so bleibt es ein Hintergrundbild wie zuvor, mit demselben
       Zuschnitt und ohne ein Videoelement, das sich unter die Schrift in
       der Mitte schieben müsste. Das Holz ringsum ist Bild für Bild
       identisch; es rührt sich wirklich nur die Flamme. */
    --tischplatte: url("../assets/bilder/tisch/platte-bewegt.webp");
    background:
        radial-gradient(circle at 50% 50%,
            rgba(4, 6, 12, .10), rgba(4, 6, 12, .38) 88%),
        var(--tischplatte) center / 107% 107%;
    border: 1px solid color-mix(in srgb, var(--mond) 35%, var(--rand));
    box-shadow: var(--schatten-mond);
}
/* Wer Bewegung abbestellt hat, bekommt die stehende Platte. Es wechselt nur
   die Datei — Zuschnitt, Vignette und Größe bleiben Zeichen für Zeichen
   dieselben, weil beide durch dieselbe Variable laufen. Steht direkt nach der
   Grundregel: gleiche Spezifität, die spätere gewinnt. */
@media (prefers-reduced-motion: reduce) {
    [data-aufbau="ring"] .tischring__mitte {
        --tischplatte: url("../assets/bilder/tisch/platte.webp");
    }
}

/* Beim Doppelkranz (mehr als zehn) sitzt der Innenkranz nahe der Mitte —
   sie zieht sich zusammen, damit beide Platz haben. Steht NACH der
   Grundregel: gleiche Spezifität, die spätere gewinnt. */
[data-aufbau="ring"] .tischring__mitte--eng {
    width: 32%;
}

/* ... und die Köpfe treten um ~15 % kürzer. Gemessen: Bei zwanzig in
   voller Größe überlappten die engsten Nachbarn um 9 px. Bis zehn
   Spieler gilt die volle Größe — der häufige Fall zahlt nicht für den
   seltenen. */
[data-aufbau="ring"] .tischring--doppel .tischring__platz {
    width: clamp(3.3rem, 15.6vw, 4.75rem);
}

[data-aufbau="ring"] .tischring__wort {
    margin: 0;
    font-size: var(--f-klein);
    color: var(--text-leise);
    max-width: 100%;
    overflow: hidden;
}
/* Die Phasenkarte („Nacht · Tag 1") ist im Ring entfallen (2026-08-29):
 * Die Übergangsblenden sagen jede Phase groß an, die Karte war deren
 * Wiederholung in klein — und die Uhr wohnt jetzt in der Tischmitte.
 * EINE Ausnahme: die Lese-Lage „fest". Wer lautlos mit Chat spielt, hat
 * keine Blendenstimme im Ohr — für ihn bleibt die Karte samt Untertitel
 * stehen. */
[data-aufbau="ring"]:not([data-lesen="fest"]) .phase { display: none; }

/* Die Uhr auf der Platte: groß, bernstein, blinkt rot im Endspurt (das
 * uhr--knapp-Blinken bringt game.css mit). */
[data-aufbau="ring"] .tischring__uhr {
    font-size: clamp(1.9rem, 8vw, 2.6rem);
    line-height: 1.1;
}
[data-aufbau="ring"] .tischring__uhr[hidden] { display: none; }

/* Die Meldereihenfolge unter der Sprecher-Uhr — klein und leise, die
 * Warteschlange ist Auskunft, kein Auftritt. */
[data-aufbau="ring"] .tischring__melden {
    margin: 0;
    font-size: var(--f-winzig);
    color: var(--text-leise);
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Der Griff in der Mitte ist Geschichte — Aktionsknöpfe wohnen in der
 * Handkante, ausnahmslos (siehe handkante.js). */

/* Die Kulisse des Rings: der Dielenboden der Schenke, von oben — der
 * Tisch steht auf einem Boden, nicht vor einer Dorfgasse (Casting
 * 2026-08-28, Wurf „breit-dielen", 2176×1216 wie die Szenenbilder;
 * cover beschneidet am Handy mittig). Überschreibt die Bilderwelt-
 * Kulisse (--kulisse) nur AM SPIELTISCH — spiel.js setzt dafür
 * data-boden am <html> (nicht data-tisch: die Marke des Tischgeräts
 * versteckt den Überspringen-Knopf, siehe components.css). Ohne diese Schranke lag der Wirtshausboden auch
 * auf Startseite und Lobby, und die gewählte Bilderwelt war nirgends
 * mehr zu sehen (bemerkt 2026-08-30). Die Regel ist spezifischer als die
 * Grundregel in base.css, und die Variable bleibt unangetastet. */
[data-aufbau="ring"][data-boden] .hintergrund {
    background-image: url("../assets/bilder/tisch/boden.webp");
}

/* ================================= Der Schirm ist der Tisch (12.09.2026)
 *
 * Gemessen auf 375×812: Kopf 52, Chipreihe 35, Ring 360, Knopfleiste 100 —
 * für alles andere bleiben rund 230 px. Die Tageskarten waren größer
 * (Beratung 249, Abstimmung 241, Meldeliste weit darüber), der Tisch
 * rutschte unter die Leiste. spiel.js räumt deshalb im Ring die Karten
 * aus (schlank()); hier steht, was der Ring stattdessen zeigt. */

/* Sicherheitsnetz: Bleibt in der Höhe kein Platz, schrumpft der Ring um
 * ein paar Prozent, statt dass die Seite scrollt. 19 rem sind Kopf,
 * Chips, Streifen und Leiste; 1.05 ist das Seitenverhältnis des Rings.
 * Auf gängigen Handys greift die Regel nicht — die Breite begrenzt
 * früher. */
[data-aufbau="ring"] .tischring {
    max-width: min(30rem, calc((100dvh - 19rem) / 1.05));
}

/* Die Redelage als Rand der Tischmitte: grün, wenn ich das Wort habe,
 * rot, wenn ein anderer spricht oder niemand. Ersetzt den Redekasten. */
[data-aufbau="ring"] .tischring__mitte--gruen {
    border-color: var(--gruen);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gruen) 45%, transparent),
                var(--schatten-mond);
}
[data-aufbau="ring"] .tischring__mitte--rot {
    border-color: var(--blut);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--blut) 40%, transparent),
                var(--schatten-mond);
}

/* Die Rednerfolge als Nummernplakette oben rechts am Gesicht. */
[data-aufbau="ring"] .tischring__nummer {
    position: absolute;
    top: -.2rem;
    right: -.2rem;
    min-width: 1.35rem;
    height: 1.35rem;
    padding: 0 .3rem;
    border-radius: var(--r-rund);
    background: var(--flaeche-hoch);
    border: 1px solid var(--rand-hell);
    color: var(--text);
    font-size: var(--f-winzig);
    font-weight: 700;
    line-height: 1.35rem;
    text-align: center;
    pointer-events: none;
    z-index: 2;
}
[data-aufbau="ring"] .tischring__nummer--ich {
    background: var(--mond);
    border-color: var(--mond);
    color: #1a1408;
}

/* Das Rudel am Tisch (17.10.2026): Am runden Kopf trägt das Gesicht die
   Markierung — orange, solange das Rudel uneins ist, blutrot, sobald das
   Opfer eingeloggt ist. Breiter Ring statt Rand, damit man es quer über
   den Tisch erkennt. */
[data-aufbau="ring"] .tischring .spieler--wolfswahl .spieler__bild {
    border-color: var(--wolfswahl);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--wolfswahl) 70%, transparent),
                0 0 18px color-mix(in srgb, var(--wolfswahl) 55%, transparent);
}
[data-aufbau="ring"] .tischring .spieler--wolfsopfer .spieler__bild {
    border-color: var(--blut);
    box-shadow: 0 0 0 5px color-mix(in srgb, var(--blut) 80%, transparent),
                0 0 22px color-mix(in srgb, var(--blut) 60%, transparent);
}
[data-aufbau="ring"] .tischring .spieler__wolfswahl {
    position: absolute;
    left: 50%;
    top: -1.35rem;
    transform: translateX(-50%);
    z-index: 3;
    width: max-content;
    max-width: 7.5rem;
    padding: .05em .45em;
    border-radius: var(--r-rund);
    background: color-mix(in srgb, var(--grund) 85%, transparent);
    border: 1px solid var(--wolfswahl);
    line-height: 1.5;
    pointer-events: none;
}
[data-aufbau="ring"] .tischring .spieler--wolfsopfer .spieler__wolfswahl { border-color: var(--blut); }

/* Die eigene Stimme als Plakette unter der Namensplakette. */
[data-aufbau="ring"] .tischring .spieler__wahl {
    position: absolute;
    left: 50%;
    bottom: -1.55rem;
    transform: translateX(-50%);
    z-index: 2;
    width: max-content;
    max-width: 7.5rem;
    padding: .05em .45em;
    border-radius: var(--r-rund);
    background: color-mix(in srgb, var(--grund) 82%, transparent);
    border: 1px solid color-mix(in srgb, var(--mond) 40%, var(--rand));
    line-height: 1.5;
    pointer-events: none;
}

/* Das Herz der Verliebten lehnt an der rechten Flanke — gegenüber dem
 * Rollenkärtchen, unter dem Stimmenzähler, über der Namensplakette. */
[data-aufbau="ring"] .tischring .spieler__herz {
    right: -.25rem;
    bottom: 26%;
    font-size: 1rem;
}

/* Nachtkarten ohne Kopf: Hat die Handkante den Knopf geholt und bleiben
 * nur ihre versteckten Anker, verschwindet die leere Karte samt Rahmen. */
[data-aufbau="ring"] .karte--nacht:not(:has(> :not([hidden]))) {
    display: none;
}

/* Sonderrollen der Nacht — Hexe, Mädchen, Dieb — als Bodenblatt ÜBER dem
 * Ring statt davor: Der Tisch bleibt stehen, das Blatt liegt auf ihm und
 * rollt in sich, wenn es länger ist. Die Handkante holt sich die glühenden
 * Knöpfe wie aus jeder Karte. */
[data-aufbau="ring"] .karte--blatt {
    position: fixed;
    left: 50%;
    bottom: calc(6.5rem + env(safe-area-inset-bottom, 0px));
    transform: translateX(-50%);
    z-index: 30;
    width: min(30rem, calc(100vw - 2 * var(--s4)));
    max-height: 55vh;
    overflow-y: auto;
    background: color-mix(in srgb, var(--grund-erhoben) 94%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow: 0 -8px 30px rgba(0, 0, 0, .55);
}

/* ------------------------------------------ Mitlesen als Streifen (Ring)
 *
 * Die Lage „fest" heftete Erzählung und Anleitung oben fest und schob
 * die Seite um bis zu 12 rem nach unten — der Ring lag damit immer unter
 * der Falz. Im Ring stehen beide jetzt im Fluss, zwei Zeilen hoch; ein
 * Tipp öffnet den vollen Text als Bodenblatt über dem Tisch (die
 * Umschalter setzen spiel.js: erzaehlung--offen, anleitung__text--offen). */
[data-aufbau="ring"][data-lesen="fest"] .seite {
    padding-top: 0;
}
[data-aufbau="ring"][data-lesen="fest"] .erzaehlung,
[data-aufbau="ring"][data-lesen="fest"] .anleitung {
    position: static;
    transform: none;
    width: auto;
    max-height: none;
    overflow: visible;
    margin: 0 0 var(--s3);
    padding: var(--s2) var(--s4);
    cursor: pointer;
}
[data-aufbau="ring"][data-lesen="fest"] .erzaehlung__text,
[data-aufbau="ring"][data-lesen="fest"] .anleitung__text {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    font-size: var(--f-klein);
    line-height: 1.45;
}
[data-aufbau="ring"][data-lesen="fest"] .erzaehlung--offen,
[data-aufbau="ring"][data-lesen="fest"] .anleitung:has(.anleitung__text--offen) {
    position: fixed;
    left: 50%;
    bottom: calc(6.5rem + env(safe-area-inset-bottom, 0px));
    transform: translateX(-50%);
    z-index: 34;
    width: min(30rem, calc(100vw - 2 * var(--s4)));
    max-height: 55vh;
    overflow-y: auto;
    margin: 0;
    padding: var(--s4);
    background: color-mix(in srgb, var(--grund-erhoben) 94%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow: 0 -8px 30px rgba(0, 0, 0, .55);
}
[data-aufbau="ring"][data-lesen="fest"] .erzaehlung--offen .erzaehlung__text,
[data-aufbau="ring"][data-lesen="fest"] .anleitung__text--offen {
    display: block;
    -webkit-line-clamp: unset;
    font-size: var(--f-normal);
}

/* ================================================= Schalter der Vorführung
 *
 * Der EINZIGE Block dieser Datei ohne [data-aufbau]-Gatter — mit Absicht:
 * Der Schalter muss auch im Ursprung sichtbar sein, sonst käme man von
 * „klassisch" nie zu den Proben. Er ist zugleich der einzige sichtbare
 * Unterschied, den der Ursprung durch die Proben bekommt. */
.vorfuehrung__aufbau {
    display: flex;
    align-items: center;
    gap: var(--s2);
    font-size: var(--f-klein);
    color: var(--text-leise);
    white-space: nowrap;
}
/* Das schwebende Wort der Vorführung — Nachfolger des Balkens. Es liegt
 * mittig ÜBER der Kopfzeile (die hat dort nichts), immer sichtbar, und
 * klappt auf Tipp das Blatt mit Erklärung, Mitlesen und Beenden auf. */
.vorfuehrung__schwebe {
    position: fixed;
    top: var(--s2);
    left: 50%;
    transform: translateX(-50%);
    z-index: 65;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s2);
    max-width: min(24rem, calc(100vw - 2 * var(--s4)));
}
/* Wort und Ausgang stehen nebeneinander in einer Zeile — beide immer
 * sichtbar, das Blatt klappt darunter auf. */
.vorfuehrung__zeile {
    display: flex;
    gap: var(--s2);
    align-items: center;
}

.vorfuehrung__wort {
    font: inherit;
    font-size: var(--f-klein);
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--mond);
    background: color-mix(in srgb, var(--grund-erhoben) 82%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid color-mix(in srgb, var(--mond) 45%, var(--rand));
    border-radius: var(--r-rund);
    padding: .25rem .9rem;
    cursor: pointer;
}
.vorfuehrung__wort:focus-visible {
    outline: 2px solid var(--dorf);
    outline-offset: 2px;
}
/* Der Ausgang trägt dieselbe Form, aber nicht die Glut: Er ist kein
 * Absender, sondern eine Tür — sie soll auffindbar sein, nicht locken. */
.vorfuehrung__wort--still {
    color: var(--text-leise);
    border-color: var(--rand-hell);
    font-weight: 500;
}
.vorfuehrung__blatt {
    background: var(--grund-erhoben);
    border: 1px solid var(--rand-hell);
    border-radius: var(--r-mittel);
    box-shadow: var(--schatten);
    padding: var(--s4);
    display: flex;
    flex-direction: column;
    gap: var(--s3);
}
.vorfuehrung__blatt[hidden] { display: none; }
.vorfuehrung__blatt .vorfuehrung__text {
    margin: 0;
    font-size: var(--f-klein);
    color: var(--text-leise);
}

.vorfuehrung__aufbau {
    flex-wrap: wrap;
}
.vorfuehrung__aufbauknopf {
    font: inherit;
    font-size: var(--f-winzig);
    color: var(--text-leise);
    background: var(--flaeche);
    border: 1px solid var(--rand-hell);
    border-radius: var(--r-rund);
    padding: .25rem .65rem;
    min-height: 2rem;
    cursor: pointer;
}
.vorfuehrung__aufbauknopf--aktiv {
    color: var(--eisen-glut);
    border-color: color-mix(in srgb, var(--eisen-glut) 55%, var(--rand));
    background: color-mix(in srgb, var(--eisen-glut) 12%, var(--flaeche));
}
.vorfuehrung__aufbauknopf:focus-visible {
    outline: 2px solid var(--dorf);
    outline-offset: 2px;
}

/* ============================================================== Nur hören
 *
 * [data-lesen="aus"] ist die VORGABE, sobald ein Aufbau außer „klassisch"
 * läuft und „Mitlesen" nicht gewählt ist (core/aufbau.js) — im Ursprung
 * existiert das Attribut nie.
 *
 * Der Gedanke: Erzählung und Anleitung werden GESPROCHEN. Sie zusätzlich
 * in voller Länge hinzuschreiben, kostet auf dem Handy mehr Platz als
 * alles andere. Also: Anleitung ganz hinaus, und das Erzählband schrumpft
 * zu einer schwebenden, halbdurchsichtigen Uhrpille — denn die Frage
 * „hängt das Spiel?" muss weiter beantwortet sein. Ihr Erscheinen leuchtet
 * kurz auf (die vorhandene Auf-Animation der Erzählkarte), damit ein neuer
 * Nachtschritt auch ohne Text bemerkt wird.
 */
[data-lesen="aus"] .anleitung { display: none; }

[data-lesen="aus"] .erzaehlung {
    position: fixed;
    /* --pille-oben misst handkante.js je Zeichenzyklus: die Unterkante
     * dessen, was oben klebt (Vorführband bzw. Kopfzeile). Rechts oben in
     * der Ecke, mit demselben Randabstand wie die Handkante unten. */
    top: var(--pille-oben, calc(var(--kopf-hoehe, 3.25rem) + var(--s2)));
    right: var(--s4);
    z-index: 35;
    width: max-content;
    max-width: calc(100vw - 2 * var(--s4));
    margin: 0;
    padding: var(--s1) var(--s3);
    gap: var(--s3);
    border-radius: var(--r-rund);
    background: color-mix(in srgb, var(--grund-erhoben) 62%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-color: color-mix(in srgb, var(--mond) 40%, transparent);
}
[data-lesen="aus"] .erzaehlung__text { display: none; }

/* Und selbst die Pille nur, wenn die Uhr etwas zu sagen hat: Der Takt in
 * spiel.js setzt `--endspurt` ab 30 Restsekunden UND nur, wenn gerade eine
 * eigene Handlung ansteht — fremde Countdowns sind Rauschen. Vorher ist
 * die Pille ganz weg.
 *
 * Die Lobby-Fassung stand hier bis zum 2026-08-30 ausdrücklich DOCH da:
 * Sie trug den Ton-Knopf, und ohne sie hätte man in der Lobby keinen Weg
 * gehabt, die Sprachführung abzuschalten. Der Knopf wohnt jetzt im Profil,
 * und eine leere Blase in der Ecke braucht niemand — die Ausnahme ist
 * damit ersatzlos entfallen. */
[data-lesen="aus"] .erzaehlung:not(.erzaehlung--endspurt) { display: none; }

/* ------------------------------------------------ Lage „fest" (Mitlesen)
 *
 * Wer die Texte dazuschaltet, soll lesen können — ohne zu scrollen.
 * Erzählung und Anleitung heften sich an den oberen Rand; die Seite rückt
 * um die gemessene Gesamthöhe nach (Variablen misst handkante.js je
 * Zeichenzyklus, denn die Anleitung ist mal zwei, mal zwanzig Zeilen).
 *
 * Bis zum 2026-08-30 kam diese Lage nicht durch Wahl zustande, sondern
 * automatisch, sobald die Sprachführung aus war — was am Probetisch elf
 * stumme Plätze mit Text zupflasterte. Jetzt entscheidet allein der
 * Schalter im Profil. */
[data-lesen="fest"] .erzaehlung {
    position: fixed;
    top: var(--pille-oben, 3.6rem);
    left: 50%;
    transform: translateX(-50%);
    z-index: 35;
    width: min(38rem, calc(100vw - 2 * var(--s4)));
    margin: 0;
    background: color-mix(in srgb, var(--grund-erhoben) 92%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
[data-lesen="fest"] .anleitung {
    position: fixed;
    top: calc(var(--pille-oben, 3.6rem) + var(--lese-versatz, 5rem));
    left: 50%;
    transform: translateX(-50%);
    z-index: 35;
    width: min(38rem, calc(100vw - 2 * var(--s4)));
    max-height: 34vh;
    overflow-y: auto;
    background: color-mix(in srgb, var(--grund-erhoben) 92%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-radius: var(--r-mittel);
    padding: var(--s3) var(--s4);
}
/* Beim Lesen wird nichts geklemmt — die zwei Zeilen der Hör-Lage wären
 * hier genau falsch. */
[data-lesen="fest"] .anleitung__text {
    display: block;
    -webkit-line-clamp: unset;
    cursor: default;
}
/* Die Seite rückt unter den festen Texten nach — nichts wird verdeckt. */
[data-lesen="fest"] .seite {
    padding-top: var(--lese-platz, 12rem);
}
[data-lesen="aus"] .erzaehlung .uhr { font-size: var(--f-gross); }

/* Das Band nimmt oben keinen Fluss-Platz mehr ein — der Inhalt rückt auf. */
[data-lesen="aus"] .erzaehlung + * { margin-top: 0; }

/* ================================================= Glut auf der Handkante
 *
 * „Der Knopf ist sehr dunkel — der Orangeton, in dem er leuchtet, soll
 * durchschimmern." Die Glut liegt als durchscheinender Verlauf ÜBER der
 * Eisenplatte, statt sie zu ersetzen: Der Werkstoff bleibt, die Hitze
 * scheint durch. Gilt für die Leiste und den Griff in der Ringmitte —
 * die Knöpfe im Fluss der Seite bleiben, wie sie sind.
 */
/* Alles, was in der Leiste GEDRÜCKT werden kann, trägt die Glut — auch
 * die Sprechtaste. Nur der Hauptknopf atmet zusätzlich (weiter unten);
 * eine gesperrte Taste („Gerade stumm") bleibt dunkles Eisen. */
.handkante .knopf:not(:disabled),
.handkante .sprechtaste:not(:disabled) {
    /* Boden, Deckung, Mitte — ausdrücklich: Der stille Bereit-Knopf
     * brachte keine eigene Plattengröße mit, und die Textur ließ auf
     * breiten Knöpfen Flecken frei (gemeldet 2026-08-28 am Handy).
     * `cover` spannt die Platte über die volle Fläche, das dunkle Eisen
     * darunter fängt jede Restlücke. */
    background-color: var(--eisen);
    background-image:
        linear-gradient(180deg,
            color-mix(in srgb, var(--eisen-glut) 42%, transparent),
            color-mix(in srgb, var(--eisen-glut) 14%, transparent) 55%,
            color-mix(in srgb, var(--eisen-glut) 30%, transparent)),
        var(--platte);
    background-size: cover;
    background-position: center;
    border: 1px solid color-mix(in srgb, var(--eisen-glut) 65%, var(--rand));
    box-shadow: 0 0 16px color-mix(in srgb, var(--eisen-glut) 30%, transparent),
                0 6px 20px rgba(0, 0, 0, .55),
                inset 0 1px 0 color-mix(in srgb, var(--eisen-glut) 45%, transparent);
    color: var(--eisen-schrift);
}

/* Der Verbindungszähler an der Sprechtaste — dezent: winzig am unteren
 * Tastenrand, leise, und nur da, wenn der Sprachchat läuft (rtc.js baut
 * ihn dann mit ein). Absolut gelegt, damit Symbol und Tastenwort in
 * ihrer Zeile bleiben. */
.handkante .sprechtaste { position: relative; }
.sprechtaste__zaehler {
    position: absolute;
    bottom: .15rem;
    left: 0;
    right: 0;
    text-align: center;
    font-size: .65rem;
    font-weight: 400;
    color: var(--text-still);
    line-height: 1;
    pointer-events: none;
    /* „4/6" wird zu „10/12", ohne dass die Zeile springt: Ziffern gleich
       breit. Ohne das wandert der Zähler bei jedem Verbindungswechsel um
       ein bis zwei Pixel — auffälliger als die Zahl selbst. */
    font-variant-numeric: tabular-nums;
}
.sprechtaste__zaehler.marke--gut { color: var(--text-leise); }

/* -------------------------------------------------- Die Taste am Handy
 *
 * Gemeldet am 2026-08-31 mit Bild: Am Telefon brach „Zum Sprechen gedrückt
 * halten" auf zwei Zeilen um, und der Zähler am unteren Tastenrand saß der
 * zweiten Zeile im Nacken — beides eng, beides klein.
 *
 * Drei Griffe, in dieser Reihenfolge:
 *
 *  1. Der lange Vorsatz entfällt. „Gedrückt halten" sagt dasselbe und passt
 *     in eine Zeile — und eine Zeile ist der ganze Punkt: Erst dadurch wird
 *     unten Platz frei.
 *  2. Die Taste bekommt unten Raum FÜR den Zähler, statt ihn auf den Text
 *     zu legen. Er liegt absolut; ohne Polsterung überlagert er einfach.
 *  3. Beide Schriften eine Spur größer. Am Schreibtisch passte es (dort
 *     bleibt alles, wie es war) — in der Hand ist der Abstand zum Auge ein
 *     anderer.
 */
@media (max-width: 34rem) {
    .sprechtaste__lang { display: none; }

    .handkante .sprechtaste {
        min-height: 4rem;
        padding: .55rem .9rem 1.4rem;
        font-size: 1.0625rem;
        line-height: 1.2;
    }

    .sprechtaste__zaehler {
        bottom: .4rem;
        font-size: .74rem;
    }
}

.handkante .knopf--haupt {
    background-image:
        linear-gradient(180deg,
            color-mix(in srgb, var(--eisen-glut) 42%, transparent),
            color-mix(in srgb, var(--eisen-glut) 14%, transparent) 55%,
            color-mix(in srgb, var(--eisen-glut) 30%, transparent)),
        var(--platte);
    border: 1px solid color-mix(in srgb, var(--eisen-glut) 65%, var(--rand));
    box-shadow: 0 0 16px color-mix(in srgb, var(--eisen-glut) 30%, transparent),
                0 6px 20px rgba(0, 0, 0, .55),
                inset 0 1px 0 color-mix(in srgb, var(--eisen-glut) 45%, transparent);
    /* Das gewollte Blinken: „Hier musst du gleich drücken." Der Knopf
     * bleibt, wo er ist, und atmet zwischen dunklem Eisen und Glut —
     * über filter statt background, weil die Eisenplatte ein Bild ist
     * und Verläufe nicht weich ineinander übergehen. Bei reduzierter
     * Bewegung schaltet tokens.css die Animation ohnehin ab. */
    animation: handkante-glut 2.2s ease-in-out infinite;
}
@keyframes handkante-glut {
    50% {
        filter: brightness(1.3) saturate(1.45);
        box-shadow: 0 0 26px color-mix(in srgb, var(--eisen-glut) 55%, transparent),
                    0 6px 20px rgba(0, 0, 0, .55),
                    inset 0 1px 0 color-mix(in srgb, var(--eisen-glut) 60%, transparent);
    }
}

/* Das Feuer zeigt die aufgerufene Rolle.
 *
 * Nachts liegt die Rollenkarte des öffentlichen Nachtschritts in der Mitte
 * — jeder sieht, die Seherin ist dran, so wie es der Erzähler ohnehin
 * gerade sagt. Das Bild liegt gedämpft UNTER Wort und Griff: Es ist
 * Kulisse des Augenblicks, keine Konkurrenz zum Knopf. */
/* Die aufgerufene Rolle liegt als KARTE auf dem Tisch — schräg, wie
 * hingelegt, mit Schatten auf dem Holz. Vorher füllte sie den ganzen
 * Kreis als Schimmer; jetzt ist sie ein Gegenstand auf der Platte. Die
 * kleine Drehung nimmt die Steifheit, die Lege-Animation den harten
 * Schnitt beim Schrittwechsel. */
[data-aufbau="ring"] .tischring__karte {
    position: absolute;
    left: 50%;
    top: 46%;
    width: 44%;
    aspect-ratio: 832 / 1216;
    transform: translate(-50%, -50%) rotate(8deg);
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid color-mix(in srgb, var(--mond) 40%, var(--rand-hell));
    box-shadow: 0 6px 16px rgba(0, 0, 0, .6),
                0 1px 3px rgba(0, 0, 0, .5);
}
/* Gelegt wird nur beim Schrittwechsel (--frisch setzt spiel.js anhand
 * des gemerkten letzten Schritts) — die übrigen Neuzeichnungen tauschen
 * die Karte unsichtbar aus, ohne die Animation neu zu starten. */
[data-aufbau="ring"] .tischring__karte--frisch {
    animation: tischkarte-legen .5s var(--kurve);
}
@keyframes tischkarte-legen {
    from {
        opacity: 0;
        transform: translate(-50%, -62%) rotate(15deg) scale(1.08);
    }
}
[data-aufbau="ring"] .tischring__bild {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
/* Das Wort rückt unter die liegende Karte an den unteren Kreisrand —
   eine Beschriftung, keine Überschreibung des Gesichts. */
[data-aufbau="ring"] .tischring__mitte--rolle .tischring__wort {
    position: relative;
    z-index: 1;
    margin-top: auto;
    font-weight: 600;
    color: var(--text);
    text-shadow: 0 1px 6px rgba(0, 0, 0, .8);
}
/* Der Hund des Hundeführers (2026-09-02) — sitzt auf der Platte zu Füßen
 * seines Herrn, zwischen den beiden Nachbarn, die der Morgenbericht nennt.
 * Ort rechnet hundPlatz() in core/aufbau.js; die Breite hier ist auf
 * dessen Radien abgestimmt (9 % im Kranz, 7 % im Doppelkranz). Über der
 * Platte (Mitte ohne z-index) und unter den Köpfen (die Plätze folgen im
 * Baum nach ihm). Das Bild ist freigestellt (werkzeuge/hund.py), mit
 * einem Schatten, damit es auf dem Holz steht statt darauf zu kleben. */
[data-aufbau="ring"] .tischring__hund {
    position: absolute;
    /* 14 % (Nutzerwunsch 3.9., zweimal angehoben): Der echte Hund ist ein dunkles Tier auf dunklem Holz
       und war bei 45 px kaum zu finden. Die Ecken seines Kastens sind
       durchsichtig, deshalb darf er die Kopfränder daneben berühren. */
    width: 14%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    pointer-events: none;
    /* Über den Köpfen: Liegt zwischen den beiden Lebenden ein Toter, fällt
       die Lücke auf dessen Platz — dort soll der Hund zu sehen sein, nicht
       das entfärbte Gesicht darüber. */
    z-index: 1;
    /* Ein schwacher Mondsaum hebt das dunkle Fell vom Holz ab; die Glut
       kommt erst mit dem Knurren. */
    filter: drop-shadow(0 0 3px color-mix(in srgb, var(--mond) 35%, transparent))
            drop-shadow(0 2px 3px rgba(0, 0, 0, .7));
}
[data-aufbau="ring"] .tischring--doppel .tischring__hund {
    width: 9%;
}
[data-aufbau="ring"] .tischring__hundbild {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}
/* Fehlt das Bild einer Welt (bildEbene() nimmt es beim Ladefehler heraus),
 * bleibt ein Zeichen statt einer Lücke. */
[data-aufbau="ring"] .tischring__hund-ersatz {
    display: none;
    font-size: clamp(1.2rem, 5.5vw, 1.8rem);
    line-height: 1;
}
[data-aufbau="ring"] .tischring__hund:not(:has(.tischring__hundbild)) .tischring__hund-ersatz {
    display: block;
}
/* Die Lücken, die der Hundeführer nachts antippen kann: ein rundes,
 * gestricheltes Tippziel auf dem Kranz zwischen zwei Köpfen. Der Hund darin
 * ist die Vorschau, erst die gewählte Lücke zeigt ihn deckend. Als <button>,
 * damit Tastatur und Vorleser sie erreichen. */
[data-aufbau="ring"] .tischring__luecke {
    position: absolute;
    width: 11%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    padding: 0;
    border-radius: 50%;
    border: 2px dashed color-mix(in srgb, var(--mond) 55%, transparent);
    background: color-mix(in srgb, var(--grund) 55%, transparent);
    cursor: pointer;
    display: grid;
    place-items: center;
    z-index: 1;   /* wie der Hund: über einem toten Platz dazwischen */
}
[data-aufbau="ring"] .tischring--doppel .tischring__luecke { width: 7.5%; }
[data-aufbau="ring"] .tischring__luecke:focus-visible {
    outline: 2px solid var(--mond);
    outline-offset: 2px;
}
[data-aufbau="ring"] .tischring__luecke .tischring__hund--vorschau {
    position: static;
    transform: none;
    width: 78%;
    opacity: .35;
    filter: none;
}
[data-aufbau="ring"] .tischring__luecke--gewaehlt {
    border-style: solid;
    border-color: var(--mond);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mond) 45%, transparent);
}
[data-aufbau="ring"] .tischring__luecke--gewaehlt .tischring__hund--vorschau { opacity: 1; }

/* Knurrt er, glüht er und zittert leise — die Glut ist die Nachricht,
 * das Zittern nur Nachdruck; wer Bewegung abbestellt, behält die Glut. */
[data-aufbau="ring"] .tischring__hund--knurrt {
    filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .7))
            drop-shadow(0 0 5px color-mix(in srgb, var(--mond) 90%, transparent))
            drop-shadow(0 0 12px color-mix(in srgb, var(--mond) 45%, transparent));
    animation: tischring-knurrt 1.1s ease-in-out infinite;
}
@keyframes tischring-knurrt {
    0%, 100% { transform: translate(-50%, -50%) rotate(-2deg); }
    50%      { transform: translate(-50%, -50%) rotate(2deg); }
}
@media (prefers-reduced-motion: reduce) {
    [data-aufbau="ring"] .tischring__hund--knurrt { animation: none; }
}

/* Die drei festen Plätze der Handkante — siehe belege() in handkante.js.
 *
 * Mit Obergrenze und mittig gebündelt: Am Rechner liefen die Knöpfe sonst
 * über die halbe Bildbreite — ein Knopf, der breiter ist als seine
 * Eisenplatte, franst hell aus und ist auch kein Tippziel mehr, sondern
 * eine Fläche. */
.handkante { justify-content: center; }
.handkante__platz { flex: 1; min-width: 0; max-width: 20rem; display: flex; }
.handkante__platz[hidden] { display: none; }
.handkante__platz > * { flex: 1; min-width: 0; }
