/* =========================================================
   PUMPLING – NEUES SPIELLAYOUT

   Gehoert zu spiel-neu.html, das tools/spiel-neu.js aus game.html
   erzeugt. Diese Datei wird ZULETZT eingehaengt und ueberschreibt die
   Regeln aus game.html - dort wird nichts angefasst. Damit laeuft die
   alte Seite unveraendert weiter, und beide teilen sich denselben
   Spielcode.

   Die Gestaltung stammt aus dem Layout-Labor (Stufen A/B/C) und wird
   hier NICHT weiterentwickelt, nur uebertragen.
   ========================================================= */

:root {
    /* Grundflaechen: neutrales Graphit, Ton 210, Saettigung unter 20 %.
       Kein Lila - siehe die Designlinie im Labor. */
    --n-bg:     #0C0F13;
    --n-bg2:    #080A0D;
    --n-panel:  #151A20;
    --n-panel2: #1D242C;
    --n-line:   #2B343F;

    /* Vier Akzente, vier Reiter. Jeder hat genau eine Bedeutung. */
    --n-zug:    #00E5FF;   /* was man druecken soll · Reiter Alltag      */
    --n-lime:   #9BFF5A;   /* lebendig, Gym-Bro · Reiter Versorgung      */
    --n-gold:   #FFD84D;   /* Geld und Erfolg · Reiter Wettkampf         */
    --n-stahl:  #8FB2CE;   /* Ruhe, Information · Reiter Ich             */

    --n-fg:     #E9EEF3;
    --n-dim:    #96A4B2;
    --n-dim2:   #8B99A7;

    --n-krit:   #FF4D5E;
    /* DAS GEGENSTUECK ZU --n-krit: der gute Ausgang.

       Es fehlte. Benutzt wurde es trotzdem - an der Sieg-Pille der
       Titelkarte (.mk-urteil.gut) und an der guten Zeile im Akt-Fenster.
       Eine leere Variable macht die ganze color-Angabe ungueltig, also
       stand "DU HAST GEWONNEN" in gewoehnlichem Weiss (nachgemessen:
       rgb(233,238,243)), waehrend "DU HAST VERLOREN" sauber rot leuchtete:
       die Niederlage war das staerkere Signal. Der Wert ist das --gut der
       Designlinie (layout-labor/assets/designlinie.css); die Flaechen und
       Raender an der Pille rechnen ohnehin schon mit 53,208,127. */
    --n-gut:    #35D07F;
    --n-feder:  cubic-bezier(.34, 1.6, .5, 1);
}

/* ---------- RAHMEN ----------
   game.html zentriert eine Karte mit gelbem Rand in der Bildmitte. Das
   neue Layout fuellt den Bildschirm. */
body {
    background: var(--n-bg) !important;
    color: var(--n-fg) !important;
    padding: 0 !important;
    align-items: stretch !important;
    min-height: calc(100 * var(--sh, 1dvh));
}
.game-container {
    background: var(--n-bg) !important;
    border: 0 !important;
    border-radius: 0 !important;
    padding: 0 !important;
    box-shadow: none !important;
    height: calc(100 * var(--sh, 1dvh));
    display: flex;
    flex-direction: column;
    text-align: left !important;
}

/* enterGame() setzt display ueber das style-Attribut. Ein schlichtes
   !important hier wuerde auch das VERSTECKEN aushebeln - der
   Spielbildschirm laege dann schon im Anmeldebild. Die Regel greift
   deshalb nur, wenn im Attribut kein "none" steht. */
#game-screen:not([style*="none"]) {
    display: flex !important;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* Der Titel wird nicht mehr gezeigt - die Kopfzeile traegt den Namen.
   Er bleibt im Markup, weil Vorleseprogramme eine Ueberschrift
   erwarten. */
.nur-fuer-vorleser {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ---------- KOPFZEILE ---------- */
.kopfleiste {
    flex: 0 0 auto;
    display: grid;
    /* Beide Aussenspalten bekommen dasselbe Mindestmasz, damit sie
       gleich breit sind - sonst sitzt der Name nicht auf der Achse,
       sondern um die halbe Differenz daneben. */
    --rand: 89px;
    grid-template-columns: minmax(var(--rand), 1fr) auto minmax(var(--rand), 1fr);
    align-items: center; gap: 10px;
    height: 50px; padding: 0 14px;
    background: var(--n-bg2);
    border-bottom: 1px solid var(--n-line);
}
.kopfleiste .wm {
    justify-self: start;
    font: 800 15px "Arial Black", sans-serif;
    background: linear-gradient(92deg, var(--n-stahl), var(--n-zug) 58%, var(--n-gold));
    -webkit-background-clip: text; background-clip: text; color: transparent;
}
.kopfleiste .spieler {
    display: inline-flex; align-items: center; gap: 7px;
    max-width: 100%; min-width: 0;
    padding: 4px 12px 4px 4px; border-radius: 999px;
    background: var(--n-panel); box-shadow: inset 0 0 0 1px var(--n-line);
    font: 800 12.5px system-ui, sans-serif; color: var(--n-fg);
}
.kopfleiste .spieler .initial {
    width: 21px; height: 21px; border-radius: 50%; flex: 0 0 auto;
    display: grid; place-items: center;
    background: linear-gradient(135deg, var(--n-zug), var(--n-stahl));
    color: #04171C; font: 900 11px system-ui, sans-serif; font-style: normal;
}
.kopfleiste .spieler .txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Waehrend einer Sperre laeuft am Boden der Pille derselbe Fortschritt
   wie im Knopf - der Seitenkopf spiegelt --cd hierher. */
.kopfleiste .spieler { position: relative; overflow: hidden; }
.kopfleiste .spieler::after {
    content: ""; position: absolute; left: 0; bottom: 0; height: 2px;
    width: var(--cd, 0%);
    background: linear-gradient(90deg, var(--n-stahl), var(--n-zug));
    box-shadow: 0 0 8px rgba(0,229,255,.6);
    opacity: 0; transition: opacity .2s;
}
.kopfleiste .spieler.laedt::after { opacity: 1; }
.kopfleiste .spieler.leer { color: var(--n-dim); }
.kopfleiste .spieler.leer .initial {
    background: none; box-shadow: inset 0 0 0 1px var(--n-line); color: var(--n-dim2);
}
.kopfknoepfe { justify-self: end; display: flex; gap: 6px; }
.kopfknopf {
    width: 34px; height: 34px; border-radius: 10px;
    display: grid; place-items: center;
    background: none !important; border: 1px solid var(--n-line);
    color: var(--n-dim); cursor: pointer; padding: 0; text-decoration: none;
    transition: color .2s, border-color .2s, background .2s;
}
.kopfknopf:hover { color: var(--n-fg); border-color: var(--n-zug); background: var(--n-panel) !important; }
.kopfknopf svg { width: 18px; height: 18px; display: block; }

/* Die drei schwebenden Abzeichen aus game.html sind hier ueberfluessig -
   Anleitung und Einladung stehen in der Kopfzeile. */
.help-badge, .invite-badge { display: none !important; }

/* ---------- BLAETTERBEREICH ---------- */
.blaettern {
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto; overscroll-behavior: contain;
    scrollbar-width: thin; scrollbar-color: var(--n-line) transparent;
}

/* ---------- COCKPIT ---------- */
.cockpit {
    position: sticky; top: 0; z-index: 20;
    background: linear-gradient(180deg, var(--n-bg) 78%, rgba(12,15,19,.94));
    border-bottom: 1px solid var(--n-line);
    padding: 8px 12px;
    backdrop-filter: blur(8px);
}

/* DIE BUEHNE.

   Der Athlet ueber die volle Breite, die Instrumente DARUEBER in den
   Ecken - dort, wo neben der Figur ohnehin nur Raum ist. So kosten die
   Ringe null zusaetzliche Hoehe. */
.buehne {
    position: relative;
    /* Behaeltermass: 1cqw ist ein Prozent der BUEHNENBREITE. Der
       Deckenbeschnitt unten rechnet damit - mit vw rechnete er mit der
       FENSTERbreite, und im Browser (Fenster 1280, Buehne 514) schnitt
       er 282 px von 411 px Leinwand weg: die Buehne war fast weg. */
    container-type: inline-size;
}
/* HIER STAND EIN FESTES LEINWANDMASS (290 px hoch, eigener Verlauf).
   Groesse und Lage rechnet jetzt setupCanvas() in 06a-engine.js aus der
   Buehne; die einzige Regel dazu steht im Abschnitt BUEHNE ZUERST am
   Dateiende. Der Verlauf faellt weg - die Szene malt ihren Hintergrund
   selbst, seit sie den ganzen Schirm fuellt. */

/* DIE RINGE ALS MITTIGE REIHE UNTEN - OHNE EINGRIFF IN DEN SPIELCODE.

   36-kopfwerte.js baut .ringreihe mit vier .ring darin und danach die
   .bestand-Zeile. Beides bleibt unveraendert; hier wird nur umgelegt.

   HIER STANDEN SIE IN DEN VIER ECKEN. Das kostete zwar keine Hoehe,
   zerlegte den Blick aber auf vier Punkte, und die Figur stand zwischen
   ihnen wie in einem Rahmen. Als Reihe unter den Fuessen liegen sie auf
   einer Achse mit der Figur, auf Daumenhoehe, und lassen die Buehne
   darueber frei. Mittig, nicht links angeschlagen: sie sind das
   Hauptinstrument, kein Randvermerk.

   Der Schublade weicht sie per transform aus, nicht ueber diesen Wert -
   siehe ".schiebt" im Abschnitt BUEHNE ZUERST am Dateiende. */
.kopfwerte { position: absolute; inset: 0; pointer-events: none; }
.kopfwerte .ringreihe {
    position: absolute; left: 0; right: 0;
    bottom: 10px;
    display: flex !important;
    justify-content: center !important;
    align-items: flex-end;
    gap: 6px !important;
}
.kopfwerte .ring {
    pointer-events: auto;
    /* 66 px: der Ring selbst misst 2*(23+2,5)+2 = 53 px, die
       Beschriftung darunter braucht den Rest. Vier davon plus Abstaende
       ergeben 4*66 + 3*6 = 282 und passen auch auf 320 px
       Geraetebreite in eine Zeile. */
    width: 66px !important;
    background: none !important;
    border: 0 !important;
    padding: 0 !important;
}
/* Die Beschriftung im Mass des Entwurfs: klein, versal, gesperrt -
   ein Etikett, kein Fliesstext. */
.kopfwerte .ring-label {
    font: 800 8px system-ui, sans-serif !important;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--n-dim2) !important;
    margin-top: 3px !important;

    /* DERSELBE DUNKLE GRUND WIE UNTER DER ZAHL.

       Die Scheibe im Ring (36-kopfwerte.js) loeste das Problem nur zur
       Haelfte: bei offener Schublade wandert die Figur so weit hoch,
       dass auch die Beschriftung auf Schuhen und Boden liegt - kleine
       graue Versalien auf hellem Leder. Derselbe Farbwert wie dort,
       damit Zahl und Wort als ein Etikett gelesen werden.

       inline-block, damit der Grund nur den Text umschliesst: als Block
       waere er 66 px breit, und vier solche Balken nebeneinander waeren
       eine Leiste unter den Ringen statt vier Etiketten. Der Knopf
       zentriert bereits (text-align: center aus game.html).

       Rechts 1 px weniger Polster: letter-spacing haengt auch hinter
       dem LETZTEN Buchstaben, sonst sitzt das Wort sichtbar links. */
    display: inline-block;
    background: rgba(6, 9, 13, .82);
    border-radius: 5px;
    padding: 2px 4px 2px 5px !important;
}
.kopfwerte .ring-zahl { font: 800 13px/1 ui-monospace, Menlo, monospace !important; }

/* DIE MASSE STEHT UNTER DEN FUESSEN.

   Sie ist die Zahl, um die es im ganzen Spiel geht, und stand in der
   Bestandszeile gleichberechtigt neben Konto und Karma. Hier wird sie
   aus der Zeile herausgeloest (position:absolute nimmt sie aus dem
   Flussl) und unter die Figur gelegt. Konto, Pokale und Karma bleiben
   als Zeile darunter stehen. */
/* bottom: 26px, nicht -4. Der Behaelter .kopfwerte spannt sich ueber die
   GANZE Buehne - und dazu gehoert die Statuszeile mit Rang und Bro unter
   dem Bild. Bei -4 lag die Masse genau darauf: "5 kg" und
   "Anfaenger-Lauch" uebereinander. 26 haelt sie im freien Streifen unter
   den Fuessen, den die Zeichenroutine ohnehin reserviert. */
.kopfwerte .bestand {
    /* bottom: 4px. Bei 26 stand die Zahl mitten in dem Streifen, den
       sich die Zustandskacheln mit ihr teilen mussten - beides passte
       nicht uebereinander. Ganz unten hat jedes seinen Platz: Kacheln
       unter den Sohlen, Zahl darunter. Die Statuszeile mit Rang und Bro
       steht ausserhalb der Leinwand und wird nicht mehr getroffen. */
    position: absolute; left: 0; right: 0; bottom: 14px;
    margin: 0 !important; padding: 0 !important; border: 0 !important;
    pointer-events: none;
}
.kopfwerte .bestand > div { display: none; }
/* Die Masse als PLAKETTE: umrandet, dunkler Grund, Goldsaum - ein
   Messinstrument der Buehne, kein loser Text. Schrift eine Stufe
   kleiner (19 statt 22): die Fassung traegt die Betonung. Die alte
   22px-Nachzuegler-Regel weiter unten ist entfernt - die Groesse
   steht nur noch hier. */
.kopfwerte .bestand .masse {
    display: table !important;
    /* .bestand ist flex, die Basisregel gibt jedem Kind flex:1 - das
       zog die Plakette auf volle Breite, egal was width sagte. */
    flex: 0 0 auto !important;
    width: max-content !important;
    margin: 0 auto !important;
    text-align: center;
    pointer-events: auto; cursor: pointer;
    padding: 3px 14px 4px;
    border: 1px solid rgba(255, 216, 77, 0.5);
    border-radius: 999px;
    background: rgba(8, 11, 15, 0.66);
    box-shadow: 0 0 18px rgba(255, 216, 77, 0.22), 0 4px 12px rgba(0, 0, 0, 0.5);
}
.kopfwerte .bestand .masse .wert {
    font: 800 16px/1 ui-monospace, Menlo, monospace !important;
    color: var(--n-gold) !important;
    text-shadow: 0 0 14px rgba(255,216,77,.45), 0 2px 8px rgba(6,9,12,.9);
}
/* Der Tipp zur Masse: ein Kaestchen ueber der Zahl, das den
   Entwicklungsstand nennt - die Rangzeile selbst ist aus der
   Statuszeile gewichen (dort stehen jetzt die Bestaende). */
.stufen-tipp {
    position: absolute; left: 50%; transform: translateX(-50%);
    bottom: 78px; width: max-content; max-width: 216px;
    background: var(--n-panel2); border: 1px solid var(--n-line);
    border-radius: 10px; padding: 8px 14px; text-align: center;
    box-shadow: 0 10px 26px rgba(0,0,0,.55);
    pointer-events: auto; cursor: pointer; z-index: 6;
}
.stufen-tipp .kopf {
    font: 800 9px system-ui, sans-serif; color: var(--n-dim2);
    text-transform: uppercase; letter-spacing: .08em;
}
.stufen-tipp .wert { font: 800 14px system-ui, sans-serif; color: var(--n-gold); }
/* Die Beschriftung "MASSE" faellt weg: die Zahl traegt ihr "kg" bereits,
   und darunter noch einmal das Wort waere dieselbe Auskunft zweimal -
   an der Stelle, an der es am wenigsten Platz gibt. */
.kopfwerte .bestand .masse .kopf { display: none; }

.buehne-fuss { position: relative; }
.status-row {
    display: flex; justify-content: center; align-items: baseline; gap: 12px;
    font-size: 11px; font-weight: 700; margin-top: 2px;
}
/* DER RANG STEHT WIEDER IN DER ZEILE.

   Er war versteckt, weil dort Konto, Pokale und Karma lagen und kein
   Platz mehr war. Die sind als Chips in die obere linke Ecke gezogen;
   die Zeile traegt jetzt wie im Entwurf genau zwei Pillen - Rang und
   Bro. Der Tipp beim Antippen der Masse zeigt ihn weiterhin. */
#stat-rank { color: var(--n-dim2) !important; }
#stat-bro-status { color: var(--n-lime) !important; }
/* Konto, Pokale und Karma ziehen aus der eigenen Zeile hierher um -
   der Seitenkopf verschiebt die fertigen Bausteine aus .bestand. */
.status-row > div { display: inline-flex; align-items: baseline; gap: 4px; }
.status-row .wert {
    font: 700 12.5px ui-monospace, Menlo, monospace;
    font-variant-numeric: tabular-nums; color: var(--n-fg);
}
/* Konto und Karma stehen als Chips oben links (siehe weiter unten) und
   erklaeren sich dort auf Antippen. Der Kasten .bestand-tipp, der hier
   bis v6.62 stand, gehoerte zu einem Mechanismus, der nie ausgeloest
   hat - er lauerte auf ".status-row .konto", und dort landen die beiden
   nicht. */
.status-row .konto .wert { color: var(--n-gold); }

/* ---------- MELDUNGSBOX MIT VERLAUF ----------

   Sie soll wie eine NACHRICHT aussehen, nicht wie noch eine Kachel:
   gehobener Grund, ein Sprechbalken links, ein Schatten, der sie von
   der Buehne abhebt - und ein kleiner Punkt als Absender-Licht.

   DER BALKEN SAGT, WAS FUER EINE NACHRICHT ES IST. Er stand fest auf
   Tuerkis, egal was drinstand - damit sah eine verdorbene Mahlzeit
   genauso dringlich aus wie ein Spruch, und die Farbe sagte nichts.
   Jetzt gilt hier dasselbe wie auf den Zetteln und im Protokoll:
   gruen fuer Gewinne, rot fuer Verluste, FARBLOS fuer alles andere -
   und das ist die Mehrheit. Den Ton setzt setLog() an die Box. */
.log {
    position: relative;
    background: linear-gradient(180deg, var(--n-panel2), var(--n-panel)) !important;
    border: 1px solid var(--n-line);
    border-left: 3px solid var(--n-line) !important;
    border-radius: 12px !important;
    color: var(--n-fg) !important;
    font-size: 13px !important;
    text-align: left !important;
    padding: 10px 14px 10px 30px !important;
    margin-top: 8px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
}
.log::before {
    content: "";
    position: absolute; left: 13px; top: 17px;
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--n-dim2);
    box-shadow: none;
}
/* Gruen fuer Gewinne, rot fuer Verluste - Balken und Absenderlicht
   zusammen, sonst widersprechen sich zwei Zeichen an derselben Box. */
.log[data-ton="gut"] { border-left-color: var(--n-lime) !important; }
.log[data-ton="gut"]::before {
    background: var(--n-lime); box-shadow: 0 0 8px rgba(155, 255, 90, .6);
}
.log[data-ton="schlecht"] { border-left-color: var(--n-krit) !important; }
.log[data-ton="schlecht"]::before {
    background: var(--n-krit); box-shadow: 0 0 8px rgba(255, 77, 94, .6);
}
.log-jetzt { color: var(--n-fg); }
.log-alt { color: var(--n-dim); }
.log-schalter { background: none !important; color: var(--n-dim2) !important; }

/* ---------- REITER-BLAETTER ---------- */
.panels { padding: 10px 12px 16px; }
.panel[hidden] { display: none !important; }
.gruppe + .gruppe { margin-top: 16px; }
.gruppe > .lbl {
    display: block; margin-bottom: 8px;
    font: 800 10px system-ui, sans-serif; color: var(--n-dim2);
    letter-spacing: .2em; text-transform: uppercase;
}
.knopfgitter { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }

/* Version und Buildnummer, ganz unten im Reiter "Ich" (renderStand in
   02-net-auth.js). Leise - man sucht sie, wenn man sie braucht. Kam ein
   neuer Stand nicht an, steht darunter der Hinweis in Gold. */
.ich-stand {
    margin: 20px 0 2px; text-align: center;
    font: 600 11px system-ui, sans-serif; color: var(--n-dim2);
    letter-spacing: .03em; font-variant-numeric: tabular-nums;
}
.ich-stand-neu { display: block; margin-top: 8px; color: var(--n-gold); }
.ich-stand-neu button {
    display: inline-flex; width: auto; margin-left: 8px; padding: 5px 12px;
    border: 1px solid var(--n-gold); border-radius: 999px; background: none;
    color: var(--n-gold); font: 800 11px system-ui, sans-serif;
}

/* ---------- KNOEPFE ----------
   Eine Flaeche, drei Bedeutungen: Hauptzug, normal, Gefahr. Die
   Farbwerte aus game.html (btn-action blau, btn-shop gruen, ...) werden
   hier bewusst eingeebnet - sie waren die Farb-Kirmes, gegen die das
   neue Layout gebaut ist. */
.knopfgitter button {
    background: var(--n-panel) !important;
    color: var(--n-fg) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 12px !important;
    padding: 12px !important;
    font: 800 13px system-ui, sans-serif !important;
    text-align: left !important;
    width: auto !important;
    transition: transform .13s var(--n-feder), border-color .2s, background .2s;
}
.knopfgitter button:hover:not([disabled]) {
    border-color: #3A4855 !important; background: var(--n-panel2) !important;
}
.knopfgitter button:active:not([disabled]) { transform: translateY(1px) scale(.99); }
.knopfgitter button[disabled] { opacity: .42; }
/* ... AUSSER dem gedrueckten: waehrend der Sperre sind alle Knoepfe
   deaktiviert und damit blass - dann ist auch die laufende Fuellung
   kaum zu sehen, und die gehoert genau dorthin. Der gedrueckte Knopf
   ist deshalb heller als die uebrigen, aber NICHT voll: er ist ja
   ebenfalls gesperrt, und volle Deckkraft liess ihn wie ein drueckbarer
   Knopf aussehen. */
.knopfgitter button[disabled].is-cooling { opacity: .72; }

/* Der Hauptzug: die eine Sache, die man tun soll. */
.knopfgitter #btn-train {
    grid-column: span 2;
    background: var(--n-zug) !important;
    border-color: #7DF2FF !important;
    color: #04171C !important;
    box-shadow: 0 6px 26px -10px rgba(0,229,255,.95);
}
.knopfgitter #btn-train:hover:not([disabled]) { background: #5BEDFF !important; }

/* DAS OFFENE OVERLOAD-FENSTER.

   Fuenf Sekunden lang bringt ein sofort nachgelegter Satz einen Bonus.
   Der Hinweis dazu hing bisher nur an der Kachel auf der Buehne - und
   die sieht niemand, waehrend die Schublade offen ist und die Hand
   ueber dem Knopf steht. 05-cooldown.js setzt die Klasse.

   Violett wie die Kachel (#e879f9), damit beide erkennbar dasselbe
   meinen. Der Trainingsknopf traegt sonst das Zug-Cyan; das Violett
   legt sich fuer die fuenf Sekunden darueber und faellt gerade deshalb
   auf.

   Der Puls ist bewusst langsam (900 ms) und schwingt nur im Schein, nicht
   in der Groesse: ein wachsender Knopf verschiebt die Nachbarn im
   Gitter, und ein zappelndes Ziel trifft man schlechter - bei einer
   Mechanik, die genau vom Treffen lebt, waere das das Gegenteil von
   hilfreich. */
.knopfgitter #btn-train.overload-offen {
    background: #e879f9 !important;
    border-color: #f5d0fe !important;
    color: #2a0736 !important;
    animation: overload-puls .9s ease-in-out infinite;
}
.knopfgitter #btn-train.overload-offen:hover:not([disabled]) {
    background: #f0abfc !important;
}
@keyframes overload-puls {
    0%, 100% { box-shadow: 0 6px 26px -10px rgba(232, 121, 249, .95); }
    50%      { box-shadow: 0 6px 34px -6px rgba(232, 121, 249, 1); }
}
/* Wer Bewegung im Bild nicht will oder nicht vertraegt, bekommt
   dieselbe Auskunft ohne Puls - die Farbe allein sagt es auch. */
@media (prefers-reduced-motion: reduce) {
    .knopfgitter #btn-train.overload-offen { animation: none; }
}

/* Gefahr traegt Rot - und nur sie. */
.knopfgitter .btn-illegal {
    border-color: rgba(255,77,94,.42) !important;
    background: #201416 !important;
    color: #FFB4BA !important;
}
.knopfgitter .btn-illegal[data-braucht="halo"] { grid-column: span 2; }
.knopfgitter button[onclick*="deleteAccount"] { color: var(--n-krit) !important; }

/* Breite Knoepfe: alles, was allein in seiner Zeile stehen soll. */
.knopfgitter button[onclick*="enterCompetition"],
.knopfgitter button[onclick*="openMatch"],
.knopfgitter button[onclick*="peakWeek"] { grid-column: span 2; }

/* DER SATZ: UEBUNG UND WECHSEL IN EINER ZEILE.

   Der Trainingsknopf ist die Hauptsache und bekommt rund 70 Prozent,
   das Umschalten steht als schmale Spalte daneben statt in einer
   eigenen Zeile. Das Gitter dieser einen Gruppe wird dafuer umgestellt;
   erkannt wird sie daran, dass der Trainingsknopf darin steht. */
.knopfgitter:has(#btn-train) { grid-template-columns: 7fr 3fr; }
.knopfgitter #btn-train,
.knopfgitter .wechsel-knopf { grid-column: auto; }
/* Im schmalen Knopf ist wenig Platz: kleinere Schrift, und der Inhalt
   sitzt mittig statt oben - sonst haengt der dreizeilige Untertext
   unter einer einsamen Kopfzeile. */
.knopfgitter .wechsel-knopf { justify-content: center; }
.knopfgitter .wechsel-knopf .t { font-size: 12px; line-height: 1.15; }
.knopfgitter .wechsel-knopf .s { font-size: 9.5px; line-height: 1.25; }

/* DIE SPERRE STEHT IM KNOPF - einzige Anzeige, so im Labor entschieden.

   ZWEI FEHLER STAKEN IN DER ERSTEN FASSUNG, beide stumm:

   1. Sie lief ueber ::after - dasselbe Pseudo-Element, das auf den
      Preisknoepfen die Marke traegt (content: attr(data-preis)). Ein
      Element hat genau EIN ::after: auf jedem Knopf mit Preis gewann
      die Marke, und die Fuellung gab es schlicht nicht.
   2. Sie rechnete mit scaleX(var(--cd)) - aber 05-cooldown.js schreibt
      --cd als PROZENT-Zeichenkette ("35.0%"), und scaleX() nimmt nur
      Zahlen. Die Transformation war ungueltig, der Browser verwarf sie
      kommentarlos.

   Jetzt ::before (die Marke behaelt ::after) und width in Prozent -
   dieselbe Semantik wie in game.html, gleiche Quelle 05-cooldown.js. */
.knopfgitter .action-btn.is-cooling::before {
    content: ""; position: absolute;
    top: 0; bottom: 0; left: 0;
    width: var(--cd, 0%);
    /* Dunkler als zuvor (.5 -> .62) und eine breitere, leuchtende
       Laufkante - die Fuellung war dem Spieler zu unauffaellig. */
    background: linear-gradient(90deg, rgba(6,9,12,.62), rgba(6,9,12,.5));
    border-right: 3px solid var(--n-zug);
    box-shadow: 6px 0 16px rgba(0,229,255,.55);
    pointer-events: none; z-index: 0;
    transition: width .12s linear;
}
.knopfgitter button { position: relative; overflow: hidden; }
/* Beschriftung und Marke liegen UEBER der Fuellung. */
.knopfgitter button > * { position: relative; z-index: 1; }
.knopfgitter button[data-preis]::after { z-index: 2; }

/* ---------- AUFGABEN ---------- */
.ziel-box {
    background: var(--n-panel) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 12px !important;
    margin-top: 8px;
}
.ziel-tuer { background: none !important; color: var(--n-fg) !important; }
.daily-head { color: var(--n-gold) !important; }
.weekly-box .daily-head { color: var(--n-lime) !important; }

/* ---------- FUSSZEILE ---------- */
.footer-line {
    display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
    margin-top: 18px; padding-top: 12px;
    border-top: 1px solid var(--n-line);
    font-size: 10px; color: var(--n-dim2);
}
.footer-link { color: var(--n-dim2) !important; }

/* ---------- REITERLEISTE ---------- */
.tabs {
    flex: 0 0 auto;
    display: grid; grid-template-columns: repeat(4, 1fr);
    border-top: 1px solid var(--n-line); background: var(--n-bg2);
    padding-bottom: env(safe-area-inset-bottom, 0px);
}
.tab {
    background: none !important; border: 0 !important;
    color: var(--n-dim2) !important;
    padding: 8px 2px 9px !important; min-height: 58px;
    /* flex-start, nicht center: bricht eine Beschriftung um, waechst
       ihr Reiter sonst nach oben und unten - und das Zeichen wandert
       mit, waehrend die drei Nachbarn stehenbleiben. */
    display: flex !important; flex-direction: column; align-items: center;
    justify-content: flex-start; gap: 3px;
    position: relative; cursor: pointer;
    font: inherit !important; width: auto !important;
    transition: color .2s;
}
.tab span { font-size: 10px; font-weight: 800; letter-spacing: .03em; }
.tab svg { display: block; flex: 0 0 auto; }

/* Jeder Reiter fuehrt einen der vier Akzente - denselben, der ohnehin
   zu ihm gehoert. Gesetzt ueber --ton, damit Schrift, Balken und Schein
   aus EINER Angabe kommen. */
.tab { --ton: var(--n-zug); }
#t-versorgung { --ton: var(--n-lime); }
#t-wettkampf  { --ton: var(--n-gold); }
#t-ich        { --ton: var(--n-stahl); }

.tab[aria-selected="true"] { color: var(--ton) !important; }
.tab[aria-selected="true"]::before {
    content: ""; position: absolute; top: 0; left: 22%; right: 22%; height: 2px;
    background: var(--ton); border-radius: 0 0 3px 3px; box-shadow: 0 0 12px var(--ton);
}
/* Auch der geschlossene Reiter zeigt seine Farbe gedaempft im Zeichen -
   so ist die Zuordnung schon vor dem Antippen sichtbar. Die
   Beschriftung bleibt neutral, sonst wird die Leiste bunt. */
.tab[aria-selected="false"] svg { color: color-mix(in srgb, var(--ton) 42%, var(--n-dim2)); }

/* ---------- BANNER ---------- */
.weather-banner, .season-banner, .announce-box {
    background: var(--n-panel) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 10px !important;
    color: var(--n-dim) !important;
    font-size: 11.5px !important;
}

/* ---------- ZWEIZEILIGE KNOEPFE ----------
   Name oben, was er tut darunter, Preis als Marke oben rechts. Der
   Preis kommt aus data-preis (preisAnKnopf in 13-weather-market.js) -
   hier steht keine Zahl. */
.knopfgitter button {
    display: flex !important; flex-direction: column; align-items: flex-start;
    gap: 2px; line-height: 1.25;
}
/* ---------- GEZEICHNETE ZEICHEN STATT EMOJI ----------

   Der Vorrat liegt als <symbol>-Sammlung im Dokument (siehe
   ikoneVorrat() in tools/spiel-neu.js), die Knoepfe holen sich daraus
   per <use>. Aus dem Blick genommen wird er ueber Groesse null und
   overflow, NICHT ueber display:none - ein verstecktes <svg> wird von
   aelteren Browsern samt seiner Symbole uebersprungen, und dann fehlen
   alle Zeichen auf einmal. */
.ic-vorrat { position: absolute; width: 0; height: 0; overflow: hidden; }

/* currentColor ist der ganze Grund fuer den Vorrat: dasselbe Zeichen
   liegt dunkel auf dem cyanfarbenen Hauptzug, hell auf den grauen
   Knoepfen und rot auf der Gefahr - ohne dass es dreimal existieren
   muesste. Genau das koennen die data-URIs im Stylesheet nicht. */
.knopf-ic {
    width: 19px; height: 19px;
    flex: 0 0 auto;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.1;
    stroke-linecap: round;
    stroke-linejoin: round;
    /* Etwas leiser als die Schrift: das Zeichen soll den Knopf
       benennen, nicht ihn anfuehren. Auf dem Hauptzug voll, weil dort
       dunkel auf hell ohnehin weniger traegt. */
    opacity: .82;
}
.knopfgitter #btn-train .knopf-ic { opacity: 1; }

/* Zeichen links ueber beide Zeilen, Text rechts. Nur bei Knoepfen, die
   ein Zeichen haben - die Marke setzt der Erzeuger. */
.knopfgitter button.hat-ic {
    display: grid !important;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: 10px;
    row-gap: 2px;
}
/* ALLE DREI PLAETZE AUSDRUECKLICH SETZEN, nicht der Selbstverteilung
   ueberlassen.

   Der Trainingsknopf hat ein VIERTES Kind: die Uebungsmarke
   ("SCHULTERDRUECKEN"). Von selbst verteilt landete sie in Zeile 3,
   Spalte 1 - und weil diese Spalte auf "auto" steht, zog die 133 px
   breite Marke die Spalte des Zeichens mit auf 133 px. Das Zeichen sass
   dann allein links, der Text begann in der Mitte des Knopfes.
   Gemessen, nicht vermutet.

   Zeichen und Text stehen deshalb fest, und alles Weitere laeuft unter
   beide Spalten - was auch fuer jedes kuenftige vierte Kind stimmt. */
.knopfgitter button.hat-ic > .knopf-ic { grid-area: 1 / 1 / span 2 / span 1; }
.knopfgitter button.hat-ic > .t { grid-area: 1 / 2; }
.knopfgitter button.hat-ic > .s { grid-area: 2 / 2; }
.knopfgitter button.hat-ic > :not(.knopf-ic):not(.t):not(.s) { grid-column: 1 / -1; }

.knopfgitter .t { font: 800 13.5px system-ui, sans-serif; }
.knopfgitter .s { font: 600 11px system-ui, sans-serif; color: var(--n-dim); }
.knopfgitter #btn-train .s { color: rgba(4,23,28,.72); }
.knopfgitter .btn-illegal .s { color: rgba(255,180,186,.75); }

/* Der Preis als Marke. ::after statt eines eigenen Elements: das Spiel
   setzt nur das Attribut, und ein Knopf ohne Preis bekommt so auch
   keine leere Marke. */
.knopfgitter button[data-preis]::after {
    content: attr(data-preis);
    position: absolute; right: 10px; top: 9px;
    font: 800 11px ui-monospace, Menlo, monospace;
    color: var(--n-gold);
    background: rgba(8,11,15,.55); border-radius: 5px; padding: 2px 6px;
}
.knopfgitter #btn-train[data-preis]::after { color: #04333D; background: rgba(4,35,42,.16); }
.knopfgitter button.preis-teuer::after    { color: var(--n-krit) !important; }
.knopfgitter button.preis-guenstig::after { color: var(--n-lime) !important; }
/* Waehrend der Sperre verschwindet die Preismarke des gedrueckten
   Knopfes: die Restzeit steht als Uhr auf dem Knopf, und beides
   nebeneinander drueckte sich gegenseitig aus der Ecke. */
.knopfgitter button[data-preis]::after { transition: opacity .18s ease; }
.knopfgitter .action-btn.is-cooling[data-preis]::after { opacity: 0; }

/* DIE RESTZEIT ALS RUNDE UHR MITTEN AUF DEM GEDRUECKTEN KNOPF.

   Sie haengt im Knopfgitter, nicht im Knopf: der hat overflow:hidden
   fuer die Sperr-Fuellung, und ein Kreis waere daran beschnitten. Die
   Lage setzt der Seitenkopf aus offsetLeft/offsetTop des Knopfes. */
/* Das versteckte Feld, in das der Cooldown seine Restzeit schreibt -
   siehe knopfBeschriftung im Seitenkopf. */
.knopfgitter .cd-quelle { display: none; }

.knopfgitter .cd-uhr {
    position: absolute;
    transform: translate(-50%, -50%);
    min-width: 30px; height: 30px; padding: 0 6px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 999px;
    background: var(--n-bg2);
    border: 2px solid var(--n-zug);
    /* Auf dem Knopf statt darueber: der Grund deckt, der Schein bleibt
       knapp - ein weiter Hof wuerde die Beschriftung daneben aufweichen. */
    box-shadow: 0 0 10px rgba(0,229,255,.45), 0 2px 8px rgba(0,0,0,.7);
    font: 800 13px/1 ui-monospace, Menlo, monospace;
    color: var(--n-fg);
    pointer-events: none; z-index: 4;
}

/* Die Marke mit der laufenden Uebung am Workout-Knopf. Sie ersetzt das
   Auswahlfenster: was gerade dran ist, steht dort, wo man drueckt. */
.knopfgitter .chip {
    align-self: flex-start; margin-top: 4px;
    font: 800 10px system-ui, sans-serif; letter-spacing: .06em;
    text-transform: uppercase;
    background: rgba(4,35,42,.18); color: #04333D;
    border-radius: 6px; padding: 3px 8px;
}
.knopfgitter .chip:empty { display: none; }

/* ---------- WEG DAMIT ---------- */
/* Die Fusszeile ist raus; save-indicator und game-version bleiben nur
   im Dokument, weil der Spielcode sie beschreibt. */
.verborgen { display: none !important; }
.rechtszeile {
    display: flex; gap: 14px; margin-top: 18px; padding-top: 12px;
    border-top: 1px solid var(--n-line); font-size: 10px;
}
.rechtszeile a { color: var(--n-dim2) !important; text-decoration: none; }

/* Die Sperrfuellung liegt UNTER dem Text, nicht darueber. */
.knopfgitter button > * { position: relative; z-index: 1; }

/* =========================================================
   DIE BUEHNE RANDLOS UND BIS UNTER DIE KOPFZEILE
   ========================================================= */

/* Das Cockpit hatte ringsum 12 px Polsterung. Damit sass die Buehne in
   einem Rahmen und begann erst ein Stueck unter der Kopfzeile. Jetzt
   traegt nur noch die Meldungsbox ihren eigenen Rand - die Buehne geht
   von Kante zu Kante und stoesst oben an die Kopfzeile. */
.cockpit { padding: 0 0 8px !important; }
.log { margin: 8px 12px 0 !important; }

/* (Das feste 330-px-Mass der Leinwand ist entfallen - siehe
   BUEHNE ZUERST am Dateiende.) */

/* DIE MELDUNGSBANNER LIEGEN AUF DER BUEHNE.

   Als eigene Zeilen unter der Kopfzeile schoben sie die Figur nach
   unten und kosteten dauerhaft Hoehe - auch wenn nichts anlag. Als
   Auflage am oberen Rand kosten sie nichts.

   pointer-events: none, damit sie den Ringen darunter nicht den Klick
   wegnehmen; die Banner selbst sind reine Auskunft. */
/* IN DEN MITTELSTREIFEN, NICHT UEBER DIE RINGE.

   Bei left/right 8px lag das Banner quer ueber Energie und Magen. Die
   Ringspalten sind 84 px breit; dazwischen bleibt derselbe freie
   Streifen, in dem auch die Zustandskacheln stehen. */
.buehne-banner {
    position: absolute; top: 8px; left: 88px; right: 88px; z-index: 3;
    display: flex; flex-direction: column; gap: 4px;
    pointer-events: none;
}
.buehne-banner .weather-banner {
    margin: 0 !important;
    background: rgba(8,11,15,.28) !important;
    border: 1px solid rgba(43,52,63,.9) !important;
    backdrop-filter: blur(6px);
    border-radius: 999px !important;
    padding: 5px 12px !important;
    font-size: 11px !important;
    text-align: center;
    /* Eine Zeile, sonst wandert die Figur bei langen Meldungen unter
       einem wachsenden Kasten. */
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Randlos heisst randlos: der Blaetterbereich zeigt keine Bildlaufleiste
   mehr. Sie nahm 6 px, und die Buehne war damit 369 statt 375 breit.
   Auf dem Handy gibt es ohnehin keine dauerhafte Leiste. */
.blaettern { scrollbar-width: none; }
.blaettern::-webkit-scrollbar { width: 0; height: 0; }

/* =========================================================
   NACHBESSERUNGEN
   ========================================================= */

/* GLEICHMAESSIG SKALIEREN - DIE WURZEL MEHRERER FEHLER.

   Die Leinwand ist 300x240 Einheiten gross; das Stylesheet zog sie auf
   375x330. Waagerecht mal 1,25, senkrecht mal 1,375 - also VERZERRT.
   Sichtbar wurde das an allem, was der Zeichner als Quadrat anlegt:
   die Zustandskacheln wurden zu Rechtecken, und die Erklaerungskaesten,
   die beim Klick auf Ring oder Kachel aufgehen, standen schief und an
   der falschen Stelle.

   aspect-ratio haelt 300:240 ein. Bei 375 px Breite sind das 300 px
   Hoehe - die Buehne wird etwas flacher, dafuer stimmen die Formen. */
/* HIER ERZWANG EINE REGEL width:100% UND aspect-ratio 300/240.

   Sie hielt die Formen gerade, solange der Zeichner in einem festen
   Koordinatensystem rechnete und das Stylesheet die Leinwand streckte.
   Beides gibt es nicht mehr: setupCanvas() setzt Breite und Hoehe
   selbst und richtet die Transformation danach aus. Ein !important
   hier gewann gegen diese Rechnung - gemessen 434x347 statt der
   gesetzten 564x791, die Figur sass angeschnitten in der Ecke. */

/* DIE BUEHNE UEBER DIE GANZE BREITE.

   Die Bildlaufleiste des Blaetterbereichs nahm 6 px - gemessen 369
   statt 375. scrollbar-width allein reichte nicht, weil die Regel
   weiter oben mit "thin" dagegenhielt; hier steht sie zuletzt. */
.blaettern { scrollbar-width: none !important; }
.blaettern::-webkit-scrollbar { width: 0 !important; height: 0 !important; }

/* Das Fehler-melden-Abzeichen schwebte ueber der Buehne. */
.report-badge { display: none !important; }

/* HIER HOBEN ZWEI REGELN DIE UNTEREN ECKRINGE AN.

   Sie sind mit der Eckanordnung weggefallen - alle vier Ringe stehen
   jetzt in einer Reihe auf gleicher Hoehe, und die Beschriftung liegt
   bei jedem gleich unter dem Kreis. */

/* DER ERKLAERUNGSKASTEN STEHT AM GEKLICKTEN RING.

   Ein Zwischenstand legte ihn in den Fluss unter die Buehne - dort
   war er weit weg von dem Ring, um den es geht. Jetzt haengt er als
   kompakter Kasten NEBEN dem Ring: bei den oberen beiden darunter,
   bei den unteren darueber, jeweils auf der Seite des Rings. Die
   Klassen (oben/unten/links/rechts) setzt der Seitenkopf beim Klick -
   der Spielcode zeigt und fuellt den Kasten unveraendert selbst. */
.ring-tipp {
    position: absolute !important;
    width: 216px; max-width: 64%;
    margin: 0 !important; z-index: 6;
    top: 92px; left: 10px;
    background: var(--n-panel) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 12px !important;
    color: var(--n-fg) !important;
    font-size: 12px !important;
    box-shadow: 0 10px 30px -12px rgba(0,0,0,.8);
}
/* Die Lage setzt der Seitenkopf beim Klick als Pixelwert (gemessen am
   angeklickten Ring) - die beiden Eckklassen von frueher gibt es nicht
   mehr, seit alle vier Ringe in einer Reihe stehen. */

/* ---------- AUFGABEN- UND AUSWAHLKAESTEN IM NEUEN LAYOUT ---------- */
.ziel-box {
    background: var(--n-panel) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 12px !important;
    margin: 0 0 8px !important;
    overflow: hidden;
}
.ziel-tuer {
    background: none !important; color: var(--n-fg) !important;
    width: 100% !important; padding: 12px !important;
    display: flex !important; align-items: center; gap: 8px;
    font: 800 13px system-ui, sans-serif !important;
}
.ziel-tuer .ziel-stand { margin-left: auto; color: var(--n-dim2); font-weight: 700; }
.ziel-tuer .pfeil { color: var(--n-dim2); }
.ziel-liste { padding: 0 12px 12px; font-size: 12px; color: var(--n-dim); }
.daily-head { color: var(--n-gold) !important; }
.weekly-box .daily-head { color: var(--n-lime) !important; }

/* Das Liga-Auswahlfeld sah aus wie aus einem anderen Spiel. */
.league-select {
    width: 100% !important;
    background: var(--n-panel) !important;
    color: var(--n-fg) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 12px !important;
    padding: 12px !important;
    font: 700 16px system-ui, sans-serif !important;   /* 16: sonst zoomt iOS hinein */
    margin-bottom: 8px !important;
    appearance: none; -webkit-appearance: none;
    /* Eigener Pfeil, weil appearance:none den vom System entfernt. */
    background-image: linear-gradient(45deg, transparent 50%, var(--n-dim2) 50%),
                      linear-gradient(135deg, var(--n-dim2) 50%, transparent 50%) !important;
    background-position: right 16px center, right 11px center !important;
    background-size: 5px 5px, 5px 5px !important;
    background-repeat: no-repeat !important;
}
.league-select option { background: var(--n-panel); color: var(--n-fg); }


/* =========================================================
   MASSE UND KACHELN TEILEN SICH KEINEN STREIFEN MEHR

   Unter den Fuessen liegen nur 26 Leinwandeinheiten frei (GROUND_Y 214
   von 240), nach dem Umstellen auf gleichmaessige Skalierung sind das
   32 CSS-Pixel. Kachel (34) und Zahl (30) passen dort nicht
   uebereinander - jeder Versuch schob das eine ueber das andere.

   Die Kacheln bleiben auf der Leinwand, direkt unter den Sohlen. Die
   Zahl bekommt eigenen Platz DARUNTER: die Buehne traegt unten 38 px
   Polsterung, und die Zahl sitzt darin. Die Statuszeile mit Rang und
   Bro rutscht entsprechend nach unten.
   ========================================================= */
/* BEIDE FEST GESETZT, NICHT IM FLUSS GESTAPELT.

   Erster Versuch gab der Buehne unten Polsterung und liess die Zahl
   darin schweben. Das ging schief, weil .kopfwerte mit inset:0 den
   POLSTERKASTEN abdeckt - die Zahl sass damit wieder auf der
   Statuszeile, gemessen 21 px Ueberlappung.

   Jetzt bekommt die Buehne unten 52 px Platz, und beide werden darin
   fest gesetzt: die Statuszeile ganz unten, die Zahl darueber. Damit
   haengt nichts mehr von der Reihenfolge im Fluss ab. */
/* DIE BUEHNE IST FLACHER.

   Volle Breite bei festem Seitenverhaeltnis heisst 300 px Leinwand-
   hoehe - zu hoch. Zwei Griffe holen zusammen 26 px heraus, ohne das
   Verhaeltnis anzutasten (sonst kommt die Verzerrung zurueck):

   1. Oben werden 12 px BESCHNITTEN (margin-top negativ, overflow
      hidden am Behaelter). Dort ist Studiodecke; die Banner liegen als
      DOM darueber und sind nicht betroffen. Bei den ganz grossen
      Monsterstufen kann die oberste Hornspitze den Beschnitt streifen -
      der Kopf selbst beginnt tiefer.
   2. Der Streifen darunter schrumpft von 58 auf 44: Zahl (bottom 26)
      und Statuszeile (bottom 0) stehen dichter, beruehren sich aber
      nicht - die Zahl darf dafuer ein paar Pixel in den leeren Boden
      der Leinwand hineinragen. */
.buehne { padding-bottom: 44px; overflow: hidden; }
/* !important, weil game.html die Zeile selbst schon positioniert -
   ohne Nachdruck blieb sie im Fluss stehen und die Zahl rutschte
   darunter statt darueber.

   DIE HOEHE STEHT NICHT MEHR HIER. Seit die Ringe als Reihe unten
   liegen, muss die Zeile ueber sie steigen - der Wert kommt aus dem
   Abschnitt BUEHNE ZUERST am Dateiende. */
.buehne-fuss {
    position: absolute !important; left: 0 !important; right: 0 !important;
    top: auto !important;
}
.kopfwerte .bestand {
    top: auto !important;
    bottom: 26px !important;
}

/* =========================================================
   FEINSCHLIFF: SCHRIFTEN, FENSTER, BUEHNENMASS
   ========================================================= */

/* Tages- und Wochenplan in den Schriftgroessen des neuen Layouts -
   die Koepfe kamen mit 14-px-Regeln aus game.html und wirkten neben
   den 13er-Knoepfen zu wuchtig. */
.ziel-tuer { font-size: 12.5px !important; padding: 11px 12px !important; }
.daily-head { font-size: 12.5px !important; }
.ziel-tuer .ziel-stand { font-size: 11px !important; }
.ziel-liste { font-size: 11.5px !important; line-height: 1.5; }
.ziel-liste .ziel-zeile, .ziel-liste li { font-size: 11.5px !important; }

/* DIE SPIELFENSTER (showModal & Co.) IM NEUEN LAYOUT.

   Sie kamen mit dunkelblauem Kasten und gelbem Rand aus game.html -
   das alte Farbschema mitten im neuen Bildschirm. Nur Flaechen,
   Raender und Knoepfe; Inhalt und Verhalten bleiben Sache des
   Spielcodes. */
.modal-overlay { background: rgba(6,9,12,.78) !important; backdrop-filter: blur(4px); }
.modal-box {
    background: var(--n-panel) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 16px !important;
    box-shadow: 0 18px 50px -18px rgba(0,0,0,.9) !important;
    color: var(--n-fg) !important;
}
.modal-box h3 { color: var(--n-gold) !important; }
.modal-box p { color: var(--n-dim) !important; }
.modal-btn {
    background: var(--n-panel2) !important;
    color: var(--n-fg) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 12px !important;
    font: 800 13px system-ui, sans-serif !important;
}
.modal-btn:hover { border-color: var(--n-zug) !important; }

/* ---------------------------------------------------------
   DIE VIER GROSSEN FENSTER IM NEUEN GEWAND

   „Dein Pumpling", „Dein Studio", „Gegner suchen" und die Hall of Fame
   bringen ihre Farben aus game.html mit: gruene Auswahlpillen, gelbe
   Markierung, gelbe Reiter. Mitten im Graphit-Bildschirm sah das aus
   wie ein zweites Spiel.

   Umgefaerbt wird nur - Aufbau, Text und Verhalten bleiben Sache des
   Spielcodes. Die Regel: Graphit als Grund, Tuerkis fuer das Gewaehlte,
   Gold nur noch fuer Preise.
   --------------------------------------------------------- */
.studio-knopf,
.vorschau-knopf {
    background: var(--n-panel2) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 999px !important;
    color: var(--n-fg) !important;
    font: 800 12.5px system-ui, sans-serif !important;
    transition: border-color .18s, background .18s, color .18s;
}
.studio-knopf:hover,
.vorschau-knopf:hover { border-color: var(--n-stahl) !important; }
.studio-knopf.knopf-gewaehlt,
.studio-knopf[disabled].knopf-gewaehlt {
    background: rgba(0,229,255,.14) !important;
    border-color: var(--n-zug) !important;
    color: var(--n-zug) !important;
}
/* Gesperrte Stuecke bleiben lesbar, aber zurueckgenommen. */
.studio-knopf[disabled]:not(.knopf-gewaehlt) {
    background: var(--n-panel) !important;
    color: var(--n-dim2) !important;
    opacity: .75;
}
.studio-gruppe { border-color: var(--n-line) !important; }
.studio-kopf { color: var(--n-fg) !important; }
.studio-text { color: var(--n-dim) !important; }
.studio-preis { color: var(--n-gold) !important; }
.studio-teil.drin { border-color: var(--n-zug) !important; }

/* Hall of Fame: Reiter wie die Reiter unten im Spiel. */
.board-tab {
    background: var(--n-panel2) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 999px !important;
    color: var(--n-dim) !important;
    font: 800 12px system-ui, sans-serif !important;
}
.board-tab.is-active {
    background: rgba(0,229,255,.14) !important;
    border-color: var(--n-zug) !important;
    color: var(--n-zug) !important;
}
.board-list {
    color: var(--n-fg) !important;
    background: var(--n-bg2) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 12px !important;
}
.board-list li, .board-list tr { border-color: var(--n-line) !important; }
.board-me, #board-me, .board-eigen {
    background: rgba(0,229,255,.10) !important;
    border: 1px solid rgba(0,229,255,.4) !important;
    border-radius: 10px !important;
    color: var(--n-fg) !important;
}

/* Gegner suchen: die Quiz-Uhr. */
.quiz-frage { color: var(--n-fg) !important; }
.quiz-zeit { background: var(--n-panel2) !important; border-radius: 999px !important; }
.quiz-zeit-fuell { background: linear-gradient(90deg, var(--n-stahl), var(--n-zug)) !important; }

/* HIER STAND DER DECKENBESCHNITT DER LEINWAND.

   Eine clamp()-Rechnung in cqw zog die Leinwand oben und unten mit
   negativen Raendern ins Bild, damit von einem festen 300:240-Bild
   moeglichst viel Figur uebrig blieb - dazu "position:static" mit
   Nachdruck, um einen Versatz aus game.html zu neutralisieren.

   Beides ist mit dem Vollbild-Zeichner gegenstandslos geworden und war
   aktiv schaedlich: das erzwungene "position:static" hob die
   Positionierung der neuen Regel auf, die Leinwand klebte in der
   linken oberen Ecke. */
/* HIER STANDEN VIER REGELN AUS DEM ECKENLAYOUT.

   Ein Polster von 40 px unter der Buehne, eine Feinstellung der
   Massezahl und zwei, die die Ringe paarweise gegeneinander
   verschoben (oben 10 px runter, unten 32 px hoch). Solange die Ringe
   in den vier Ecken sassen, war das richtig. In einer Reihe stellten
   sie die vier Ringe auf vier verschiedene Hoehen und liessen sie der
   Figur ins Bild rutschen - nachgesehen im ersten Anlauf.

   Der Streifen unter der Buehne steht jetzt in EINER Regel im
   Abschnitt BUEHNE ZUERST am Dateiende. */

/* DIE BANNER OBEN SIND ANKLICKBAR.

   Sie zeigen nur eine Zeile und schneiden lange Meldungen ab - ein
   Klick zeigt den ganzen Text in einer Infobox in Ringkastengroesse.
   pointer-events lag vorher auf none, damit die Banner den Ringen den
   Klick nicht stehlen; jetzt faengt das Banner selbst, die Luecken
   dazwischen bleiben durchlaessig. */
.buehne-banner { pointer-events: none; }
.buehne-banner .weather-banner { pointer-events: auto; cursor: pointer; }
.banner-tipp {
    position: absolute; top: 46px; left: 50%; transform: translateX(-50%);
    width: 240px; max-width: 78%; z-index: 7;
    background: var(--n-panel); border: 1px solid var(--n-line);
    border-radius: 12px; padding: 10px 12px;
    color: var(--n-fg); font-size: 12px; line-height: 1.5;
    box-shadow: 0 10px 30px -12px rgba(0,0,0,.8);
}
.banner-tipp[hidden] { display: none; }


/* DER PREIS AUF DEM HAUPTKNOPF BLEIBT LESBAR, AUCH GEFAERBT.

   preis-teuer setzt die Markenfarbe auf Rot, preis-guenstig auf
   Limette - auf dunklem Knopfgrund in Ordnung, auf dem TUERKISEN
   Hauptknopf unleserlich (Rot auf Tuerkis). Fuer den Hauptknopf
   bekommt die Marke deshalb einen deckenden Grund in der
   Bedeutungsfarbe und dunkle Schrift darauf. Die ID schlaegt die
   Klassenregeln nur zusammen mit !important auf beiden Seiten. */
.knopfgitter #btn-train.preis-teuer::after {
    color: #4A0910 !important;
    background: rgba(255,120,132,.85) !important;
}
.knopfgitter #btn-train.preis-guenstig::after {
    color: #143D06 !important;
    background: rgba(155,255,90,.75) !important;
}

/* =========================================================
   DER STARTBILDSCHIRM IM NEUEN STIL

   game.html bringt ihn mit Inline-Farben aus dem alten Layout mit
   (gelber Titel, blaue Kaesten). Hier wird nur UMGEFAERBT und
   angeordnet - jede Kennung, jeder Knopf und jeder Ablauf bleibt
   unangetastet, deshalb braucht fast alles !important gegen die
   Inline-Angaben.
   ========================================================= */
#setup-screen {
    /* DIE BREITE STEHT, EGAL WAS DRINSTEHT.

       Ohne width:100% ist dieser Bildschirm ein Flex-Kind, das sich auf
       die Breite seines laengsten Textes zusammenzieht - und damit auch
       jeden Kasten darin. Gemessen auf 375 px: im Reiter "Anmelden"
       war das Formular 238 px breit, im Reiter "Konto anlegen" 305,
       weil dort ein Satz mehr stand. Beim Umschalten sprang die halbe
       Seite.

       max-width haelt die Spalte auf grossen Schirmen weiterhin bei
       420; width:100% sorgt nur dafuer, dass sie darunter nicht
       schmaler wird als der Platz, den sie hat. */
    width: 100%;
    max-width: 420px; margin: 0 auto; padding: 28px 16px 40px;
    display: flex; flex-direction: column; gap: 10px;
}
#setup-screen h2#setup-title {
    color: transparent !important;
    background: linear-gradient(92deg, var(--n-stahl), var(--n-zug) 58%, var(--n-gold));
    -webkit-background-clip: text; background-clip: text;
    font: 800 26px "Arial Black", sans-serif;
    letter-spacing: 0 !important; padding: 0 !important;
    text-align: center;
}
#setup-screen > p { text-align: center; color: var(--n-dim) !important; }
#setup-screen .login-box {
    /* VOLLE BREITE, NICHT INHALTSBREITE.

       Ohne diese Zeile richtet sich jeder Kasten nach seinem laengsten
       Text. Gemessen auf 375 px: die Anmeldebox war im Reiter
       "Anmelden" 276 px breit und im Reiter "Konto anlegen" 343 -
       weil dort ein Hinweissatz stand, der sie auseinanderzog. Beim
       Umschalten sprang also das ganze Formular in der Breite.

       Es faellt nur dort nicht auf, wo ein breiter Kasten daneben
       steht - im Testaufbau etwa der Kasten "Testumgebung". Live gibt
       es den nicht, und genau dort ist es aufgefallen. */
    width: 100%;
    background: var(--n-panel) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 16px !important;
    padding: 16px !important;
    box-shadow: none !important;
    text-align: left;
}
#setup-screen .login-box p { color: var(--n-dim) !important; }
#setup-screen .login-box p[style*="f1c40f"] { color: var(--n-gold) !important; }
#setup-screen input[type="text"],
#setup-screen input[type="email"],
#setup-screen input[type="password"] {
    background: var(--n-bg2) !important; color: var(--n-fg) !important;
    border: 1px solid var(--n-line) !important; border-radius: 10px !important;
    /* 16px, nicht 13: darunter zoomt Safari auf dem iPhone beim
       Antippen hinein (siehe Abschnitt am Dateiende). */
    padding: 10px 12px !important; font: 600 16px system-ui, sans-serif !important;
    width: 100%;
}

/* ---------- DIE ANMELDUNG: ZWEI WEGE, EINE BOX ----------

   Aufbau von oben nach unten: Reiter (Anmelden | Konto anlegen),
   Formular, kleiner Textknopf, Trennlinie, Google. Die Reihenfolge
   ist die Haeufigkeit - wer wiederkommt, tippt oben; wer neu ist,
   braucht einen Klick; Google steht als gleichwertiger zweiter Weg
   darunter, nicht als Hauptzug.

   Hier stand vorher ein Kaestchen mit Einwilligung, ein Hinweis
   darauf und Googles Knopf - drei Elemente fuer einen Weg. */
#setup-screen .auth-reiter {
    display: flex; gap: 4px; width: 100%;
    background: var(--n-bg2); border: 1px solid var(--n-line);
    border-radius: 12px; padding: 3px; margin-bottom: 14px;
}
#setup-screen .auth-reiter button {
    /* Der Rahmen ist IMMER da, nur meistens durchsichtig. Bekaeme ihn
       allein der aktive Reiter, wuerde die Beschriftung beim Umschalten
       um einen Punkt wandern - sichtbar genug, um zu stoeren, zu klein,
       um den Grund zu erkennen. */
    flex: 1 1 0; border: 1px solid transparent !important; background: none !important;
    color: var(--n-dim2) !important; cursor: pointer;
    font: 800 12.5px system-ui, sans-serif !important;
    padding: 8px 6px !important; border-radius: 9px !important;
    letter-spacing: .01em;
}
/* Der aktive Reiter traegt die Zugfarbe als Rahmen - dieselbe, die
   unten der Hauptknopf traegt. Damit gehoeren Auswahl und Ausfuehrung
   sichtbar zusammen: was oben leuchtet, macht der Knopf unten. */
#setup-screen .auth-reiter button.an {
    background: var(--n-panel2) !important; color: var(--n-fg) !important;
    border-color: var(--n-zug) !important;
}

#setup-screen #auth-form { width: 100%; display: flex; flex-direction: column; gap: 8px; }
#setup-screen .auth-feld { display: flex; flex-direction: column; gap: 4px; text-align: left; }
#setup-screen .auth-feld > span {
    font: 800 9.5px system-ui, sans-serif; letter-spacing: .14em;
    text-transform: uppercase; color: var(--n-dim2);
}

/* Der Hauptknopf traegt die Zugfarbe - es ist der eine Zug, der von
   diesem Bildschirm wegfuehrt. */
#setup-screen .auth-haupt {
    background: var(--n-zug) !important; color: #04171C !important;
    border: 0 !important; border-radius: 12px !important;
    font: 900 14px system-ui, sans-serif !important;
    padding: 12px !important; cursor: pointer; width: 100%;
    margin-top: 2px;
}
.auth-haupt[disabled] { opacity: .55; cursor: default; }

/* Textknoepfe, kein Kasten: sie sind Nebenwege und sollen nicht
   neben dem Hauptknopf um Aufmerksamkeit ringen. */
#setup-screen .auth-klein {
    background: none !important; border: 0 !important;
    color: var(--n-dim2) !important; cursor: pointer;
    font: 700 11.5px system-ui, sans-serif !important;
    padding: 9px 4px 2px !important; width: auto !important;
    text-decoration: underline; text-underline-offset: 3px;
}
.auth-klein:hover { color: var(--n-fg) !important; }

#setup-screen .auth-tipp {
    margin: 0 !important; min-height: 0;
    font: 600 11px system-ui, sans-serif; color: var(--n-dim2) !important;
    text-align: left;
}
#setup-screen .auth-status {
    /* KEINE MINDESTHOEHE. Sie hielt fuenfzehn Punkte frei, die meistens
       leer blieben - auf einem 667er Schirm genau der Rand, an dem der
       Datenschutzhinweis abgeschnitten wurde. Steht nichts da, nimmt
       die Zeile auch keinen Platz. */
    margin: 8px 0 0 !important;
    font: 700 11.5px system-ui, sans-serif; color: var(--n-krit) !important;
    text-align: center;
}
.auth-status.gut { color: var(--n-gut) !important; }

/* Waagerechte Linie mit einem Wort darin. */
#setup-screen .auth-oder {
    display: flex; align-items: center; gap: 10px;
    width: 100%; margin: 10px 0 9px;
    color: var(--n-dim2); font: 800 9.5px system-ui, sans-serif;
    letter-spacing: .18em; text-transform: uppercase;
}
#setup-screen .auth-oder::before, #setup-screen .auth-oder::after {
    content: ""; flex: 1 1 auto; height: 1px; background: var(--n-line);
}

/* Googles Knopf in Googles Farben - ein fremder Dienst soll auch
   aussehen wie einer, damit klar ist, wohin man geht. */
#setup-screen .auth-google {
    display: flex; align-items: center; justify-content: center; gap: 10px;
    width: 100%; cursor: pointer;
    background: #FFFFFF !important; color: #1F1F1F !important;
    border: 1px solid #DADCE0 !important; border-radius: 12px !important;
    font: 800 13.5px system-ui, sans-serif !important; padding: 11px !important;
}
#setup-screen .auth-google .g-mark {
    font: 900 15px "Arial Black", sans-serif;
    background: conic-gradient(from -45deg, #EA4335 0 25%, #FBBC05 0 50%, #34A853 0 75%, #4285F4 0);
    -webkit-background-clip: text; background-clip: text; color: transparent;
}
#g-signin { margin-top: 10px; display: flex; justify-content: center; }

#setup-screen .auth-fuss {
    margin: 10px 0 0 !important; text-align: center;
    font: 600 10.5px/1.5 system-ui, sans-serif !important;
    color: var(--n-dim2) !important; max-width: 34ch;
}
.auth-fuss a { color: var(--n-stahl); }
#setup-screen button {
    border-radius: 12px !important;
    font: 800 13.5px system-ui, sans-serif !important;
    border: 1px solid var(--n-line) !important;
    background: var(--n-panel2) !important; color: var(--n-fg) !important;
}
/* Weiterspielen ist der Hauptzug des Bildschirms. */
#setup-screen #continue-btn {
    background: var(--n-zug) !important; color: #04171C !important;
    border-color: #7DF2FF !important;
    box-shadow: 0 6px 26px -10px rgba(0,229,255,.95);
}
/* DIE ATHLETENWAHL TRAEGT IHRE FARBE.

   Blau fuer maennlich, Rosa fuer weiblich - dieselben zwei Toene wie im
   Namenskreis auf der Buehne, damit die Wahl hier und die Anzeige dort
   dasselbe sagen. Der weibliche Knopf trug vorher Gold; das war ein
   dritter Ton ohne Bedeutung.

   Das Zeichen selbst ist gezeichnet, nicht geschrieben: als Text setzt
   iOS ♂ und ♀ in Apple Color Emoji und ignoriert jede Schriftfarbe -
   einfaerben ginge dort gar nicht. Als SVG sieht es ueberall gleich
   aus, dieselbe Loesung wie bei den Bestandschips und der Plakette.

   Rand und Icon teilen sich den Farbwert bewusst nicht als Variable:
   die Randfarbe ist halbdurchsichtig, das Icon voll deckend. */
#setup-screen [onclick*="startGame('m')"] { border-color: rgba(56,189,248,.55) !important; }
#setup-screen [onclick*="startGame('w')"] { border-color: rgba(244,114,182,.55) !important; }
/* Der Knopf ist ein Flex-Kasten (display:flex aus game.html), das
   Zeichen also ein eigenes Element neben dem Namen - der Abstand
   gehoert deshalb an das Icon, nicht in den Text. */
#setup-screen .gsym {
    flex: 0 0 auto;
    width: 16px; height: 16px;
    margin-right: 7px;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 16px 16px;
}
#setup-screen .gsym.m {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2338bdf8' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9.5' cy='14.5' r='5.5'/%3E%3Cpath d='M14 10L20.5 3.5'/%3E%3Cpath d='M15 3.5h5.5V9'/%3E%3C/svg%3E");
}
#setup-screen .gsym.w {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f472b6' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8.5' r='5.5'/%3E%3Cpath d='M12 14v7'/%3E%3Cpath d='M8.5 17.5h7'/%3E%3C/svg%3E");
}
#setup-screen .name-edit-icon { background: none !important; border: 0 !important; }

/* =========================================================
   DER STARTBILDSCHIRM ALS BUEHNE

   Nicht mehr nur umgefaerbte Kaesten: der erste Bildschirm ist ein
   Auftritt. Scheinwerfer oben, Goldschein unten, der Titel schimmert
   einmal quer durch seine drei Akzentfarben, und ueber den Karten
   schwebt eine Hantel. Alles Zierde - jede Kennung, jeder Knopf und
   jeder Ablauf bleibt unangetastet, und wer weniger Bewegung wuenscht
   (prefers-reduced-motion), bekommt alles in Ruhe.
   ========================================================= */
/* ---------- DER WILLKOMMEN-KOPF ----------

   Derselbe Schnitt wie der eigene Athlet in der Gegnersuche: Zeichen im
   Kreis, Name, darunter die Lage. Wer zurueckkommt, sieht in einer Zeile,
   wo er steht - statt es aus einem Knopftext zu lesen. */
#wk-kopf {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px; margin-bottom: 14px;
    background: var(--n-bg2); border: 1px solid var(--n-line);
    border-radius: 12px;
}
#wk-kopf .wk-zeichen {
    width: 38px; height: 38px; border-radius: 50%; flex: none;
    display: grid; place-items: center; font-size: 17px;
    background: var(--n-panel2); border: 2px solid var(--n-zug);
}
#wk-kopf .wk-text { display: flex; flex-direction: column; text-align: left; min-width: 0; flex: 1 1 auto; }
#wk-kopf .wk-text b { font: 800 14px system-ui, sans-serif; color: var(--n-fg);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#wk-kopf .wk-text i {
    font: 400 11.5px system-ui, sans-serif; font-style: normal; color: var(--n-dim2);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#wk-kopf .name-edit-icon { flex: none; }

/* Die leisen Wege: Hall of Fame, Neuanfang, Abmelden. Sie stehen als
   Text da, nicht als Knopf - auf diesem Bildschirm gibt es genau einen
   Zug, und der ist "Weiterspielen". */
#setup-screen .wk-klein {
    background: none !important; border: 0 !important;
    color: var(--n-dim2) !important; cursor: pointer;
    font: 700 11.5px system-ui, sans-serif !important;
    padding: 4px !important; width: auto !important;
    text-decoration: underline; text-underline-offset: 3px;
}
#setup-screen .wk-klein:hover { color: var(--n-fg) !important; }
/* EIN SANFTER HINWEIS, KEIN ALARM.

   Hier stand derselbe Satz in fettem Rot, mit "Achtung:" davor. Rot ist
   in diesem Spiel die Farbe fuer "kaputt" (Toxin, Absagen, Fehler) - hier
   geht aber nichts kaputt, hier wird nur etwas ueberschrieben, und zwar
   erst nach einer Rueckfrage. Gold ist die Farbe fuer "aufgepasst".

   Das Zeichen traegt die Warnung, deshalb faellt das Wort "Achtung"
   weg: beides zusammen sagt dasselbe zweimal. */
#setup-screen .wk-warnung {
    /* KEIN !important AUF display.

       Mit "display: flex !important" stand der Hinweis auch dort, wo er
       nichts zu suchen hat: beim neuen Spieler, der noch gar keinen
       Fortschritt hat. 04-lifecycle.js versteckt ihn per Inline-Stil
       (style.display='none') - und !important schlaegt genau den. Die
       Schriftangabe darunter braucht es weiterhin, weil #setup-screen
       button/p-Regeln sonst gewinnen; display darf es nicht. */
    display: flex; align-items: flex-start; gap: 8px;
    margin: 2px 0 10px !important; padding: 9px 11px;
    background: rgba(255, 216, 77, .07);
    border: 1px solid rgba(255, 216, 77, .26);
    border-radius: 10px;
    font: 600 11.5px/1.5 system-ui, sans-serif !important;
    color: var(--n-dim) !important;
    text-align: left;
}
#setup-screen .wk-warnung > span:first-child { font-size: 13px; line-height: 1.35; }

/* Auch beim Rueckkehrer ist die Bestenliste ein Angebot am Rand, kein
   Hauptzug. Vorher trug sie dort einen vollbreiten Knopf und stand damit
   gleichberechtigt neben "Weiterspielen".

   NICHT ueber .startaktionen ansprechen: der Umbau in tools/spiel-neu.js
   haengt den Knopf in eine der beiden Karten um, danach steckt er nicht
   mehr in .startaktionen und jede Regel darueber greift ins Leere
   (gemessen: der Knopf blieb vollbreit). Der Zustand "Rueckkehrer" steht
   als FEHLENDE Klasse neu-hier am Bereich selbst. */
#character-select:not(.neu-hier) #hof-btn {
    background: none !important;
    color: var(--n-dim2) !important;
    font: 700 11.5px system-ui, sans-serif !important;
    text-decoration: underline; text-underline-offset: 3px;
    padding: 4px !important; width: auto !important;
    border: 0 !important;
}

/* WAS NICHT PASST, WIRD SCROLLBAR - NICHT ABGESCHNITTEN.

   body, #main-container und #setup-screen sind ineinandergeschachtelte
   Flex-Behaelter mit Fensterhoehe. Ist der Inhalt hoeher, staucht jeder
   von ihnen sein Kind (flex-shrink steht per Vorgabe auf 1), und die
   Anmeldebox schneidet den Rest ab. Gemessen auf 375x667: Inhalt
   487 px, Box 422 px - die 65 Punkte, die fehlten, waren der Hinweis
   mit dem Verweis auf die Datenschutzerklaerung.

   Genau der darf nicht verschwinden: eine Einwilligung, deren Text man
   nicht sieht, ist keine. Also darf dieser Bildschirm scrollen.

   NUR VOR DER ANMELDUNG. Sobald body.angemeldet steht, gilt wieder das
   Vollbild-Layout der Buehne, das nicht scrollen soll und darf. */
body:not(.angemeldet),
body:not(.angemeldet) #main-container { overflow-y: auto; }
body:not(.angemeldet) #setup-screen,
body:not(.angemeldet) #setup-screen > * { flex-shrink: 0; }
#setup-screen .login-box { overflow: visible; }

#setup-screen {
    position: relative;
    /* KEIN justify-content: center. Der Inhalt ist hoeher als das
       Fenster, und ein zentrierter Flex-Behaelter schiebt dann seinen
       ANFANG ueber die Oberkante hinaus - unerreichbar, kein Scrollen
       fuehrt dorthin. Genau da steckte die Hantel: bei top -53. */
    justify-content: flex-start;
    min-height: calc(100 * var(--sh, 1dvh) - 2px);
    padding-top: 22px;
    background:
        radial-gradient(70% 42% at 50% -6%, rgba(0,229,255,.13), transparent 70%),
        radial-gradient(56% 34% at 50% 104%, rgba(255,216,77,.10), transparent 72%),
        repeating-linear-gradient(0deg, transparent 0 46px, rgba(43,52,63,.14) 46px 47px);
}
#setup-screen h2#setup-title {
    font-size: 34px;
    background: linear-gradient(92deg,
        var(--n-stahl), var(--n-zug) 30%, var(--n-gold) 60%, var(--n-stahl) 90%);
    background-size: 220% 100%;
    -webkit-background-clip: text; background-clip: text;
    animation: start-schimmer 7s linear infinite;
}
@keyframes start-schimmer { to { background-position: -220% 0; } }

/* DIE HALL OF FAME TRAEGT DENSELBEN SCHIMMER wie das Wortzeichen im
   Kopf und der Titel des Startbildschirms: ein Verlauf durch Stahl,
   Tuerkis und Gold, der einmal quer durchlaeuft. Eine Marke, ein
   Auftritt - und die Bestenliste ist die Buehne, auf der man landen
   will. */
#board-modal h3.hof-titel {
    background: linear-gradient(92deg,
        var(--n-stahl), var(--n-zug) 30%, var(--n-gold) 60%, var(--n-stahl) 90%);
    background-size: 220% 100%;
    -webkit-background-clip: text; background-clip: text;
    color: transparent !important;
    animation: start-schimmer 7s linear infinite;
    letter-spacing: .04em;
}
@media (prefers-reduced-motion: reduce) {
    #board-modal h3.hof-titel { animation: none; }
}

/* Weiterspielen atmet - der eine Knopf, um den es geht. */
#setup-screen #continue-btn { animation: start-puls 3.2s ease-in-out infinite; }
@keyframes start-puls {
    0%, 100% { box-shadow: 0 6px 26px -10px rgba(0,229,255,.95); }
    50%      { box-shadow: 0 6px 34px -8px rgba(0,229,255,1), 0 0 0 4px rgba(0,229,255,.10); }
}

@media (prefers-reduced-motion: reduce) {
    #setup-screen h2#setup-title,
    #setup-screen #continue-btn { animation: none !important; }
}


/* HIER STAND .box-kopf - DIE UEBERSCHRIFT DER ANMELDEBOX.

   Sie wurde nur an einer einzigen Stelle vergeben: tools/spiel-neu.js
   ersetzte damit "Einmal anmelden, dann Ruhe" durch "Rein ins Studio".
   Seit die Box Reiter traegt, gibt es weder die Ersetzung noch die
   Ueberschrift - und eine Klasse, die nirgends mehr steht, wird beim
   naechsten Lesen fuer benutzt gehalten. */
/* DER WILLKOMMENSBEREICH: ZWEI KAESTEN, GETRENNT DURCH "ODER".

   Oben die Rueckkehr (Begruessung, Weiterspielen, Hall of Fame), unten
   der Neuanfang - dazwischen ein "oder" zwischen zwei Strichen. Der
   Seitenkopf baut die beiden Kaesten (.start-karte) und die Zeile; hier
   steht nur, wie sie aussehen. Der Bereich selbst ist bloss Behaelter.

   flex:0 0 auto ueberall: der Startbildschirm ist eine Flex-Spalte, und
   ohne die Zeile schrumpfen die Kaesten bei Platzmangel und schneiden
   ihr letztes Kind ab (gemessen: 8 px vom Abmelden-Knopf fehlten).
   Dieselbe Falle wie beim Hantel-Bild in v4.72. */
#setup-screen #character-select {
    flex: 0 0 auto;
    margin-top: 16px !important;
}
#setup-screen .start-karte {
    position: relative; overflow: hidden;
    flex: 0 0 auto;
    background: linear-gradient(180deg, var(--n-panel2), var(--n-panel) 55%);
    border: 1px solid var(--n-line);
    border-radius: 18px;
    padding: 18px 16px 16px;
}
#setup-screen .start-karte::before {
    content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
    background: linear-gradient(90deg, var(--n-stahl), var(--n-zug), var(--n-gold));
}
/* Der zweite Kasten ist die leisere Wahl: keine Verlaufslinie, etwas
   zurueckgenommener Grund. */
#setup-screen .start-karte.leise { background: var(--n-panel); }
#setup-screen .start-karte.leise::before { display: none; }
/* Die alte Trennlinie ueber dem Neuanfang stammt aus game.html - im
   eigenen Kasten waere sie ein zweiter Strich ohne Aufgabe. */
#setup-screen .start-karte.leise #start-box {
    border-top: 0 !important; padding-top: 0 !important; margin-top: 0 !important;
}
/* Die Hall of Fame ist das Angebot am Rand, nicht die zweite Haelfte
   des Weiterspielens - sie bekommt Luft nach oben. */
#setup-screen .start-karte #hof-box { margin-top: 10px; }
/* Das Abmelden steht frei unter beiden Kaesten - und sieht auch so aus.

   Es trug die Knopfgestalt aus #setup-screen button (Grund, Rahmen,
   13,5 px hell) und war damit der auffaelligste Schalter des ganzen
   Bildschirms, obwohl es die einzige Handlung ist, die vom Spiel
   wegfuehrt. Jetzt eine graue Zeile. */
#setup-screen > #character-select > #logout-box {
    margin-top: 14px; text-align: center;
}
#setup-screen > #character-select > #logout-box button {
    background: none !important;
    border: 0 !important;
    color: var(--n-dim2) !important;
    font: 400 11.5px system-ui, sans-serif !important;
    padding: 6px 10px !important;
    /* Der Knopf ist ein Flex-Kasten (aus #setup-screen button), also
       ein Block: das text-align:center des Kastens darueber greift an
       ihm nicht - er stand am linken Rand. Zentriert wird er ueber
       seine eigenen Aussenabstaende. */
    width: auto !important;
    margin-left: auto !important; margin-right: auto !important;
    text-decoration: underline;
    text-underline-offset: 3px;
}
#setup-screen > #character-select > #logout-box button:hover { color: var(--n-fg) !important; }

/* "oder" zwischen zwei Strichen. */
#setup-screen .oder-zeile {
    display: flex; align-items: center; gap: 12px;
    margin: 14px 4px;
    font: 800 10px system-ui, sans-serif;
    letter-spacing: .16em; text-transform: uppercase;
    color: var(--n-dim2);
}
#setup-screen .oder-zeile::before,
#setup-screen .oder-zeile::after {
    content: ""; flex: 1 1 auto; height: 1px;
    background: var(--n-line);
}

/* DIE WILLKOMMENSZEILE IST DER AUFTRITT DES SPIELERS.

   Gross, mittig, mit einem kurzen Verlaufsbalken darunter - derselbe
   Dreiklang wie unter dem aktiven Reiter. Der NAME behaelt sein Gold
   (eigener span mit eigener Inline-Farbe aus dem Spielcode). */
#user-welcome {
    display: block;
    color: var(--n-fg) !important;
    font: 800 19px system-ui, sans-serif !important;
    text-align: center;
    letter-spacing: -.01em;
    margin: 4px 0 14px !important;
    position: relative;
    padding-bottom: 12px;
}
#user-welcome::after {
    content: ""; position: absolute; left: 50%; bottom: 0;
    transform: translateX(-50%);
    width: 64px; height: 3px; border-radius: 3px;
    background: linear-gradient(90deg, var(--n-stahl), var(--n-zug), var(--n-gold));
    box-shadow: 0 0 12px rgba(0,229,255,.5);
}

/* DER ANMELDEKASTEN ("Rein ins Studio") ALS MODERNE KARTE.

   Verlaufslinie oben wie im Kopf der Textseiten, leicht gehobener
   Grund, der Kopf groesser und mittig, der Datenschutz-Haken in
   Akzentfarbe. Nur #auth-section - die uebrigen Kaesten bleiben
   schlicht, sonst konkurriert alles um Aufmerksamkeit. */
#setup-screen #auth-section {
    position: relative; overflow: hidden;
    background: linear-gradient(180deg, var(--n-panel2), var(--n-panel) 55%) !important;
    border-radius: 18px !important;
    padding: 20px 18px 18px !important;
    text-align: center;
}
#setup-screen #auth-section::before {
    content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
    background: linear-gradient(90deg, var(--n-stahl), var(--n-zug), var(--n-gold));
}
/* HIER STAND EINE VERGROESSERUNG FUER DIE GANZE ANMELDEBOX.

   "#auth-section > p:not(.box-kopf) { font-size: 14px !important }" -
   gedacht fuer den alten Aufbau, in dem unter einer Ueberschrift zwei
   Erklaerzeilen mit 12px-Inline-Stil standen. Zwei Kennungen im
   Selektor, dazu !important: damit schlug sie jede Klassenregel, die
   spaeter dazukam. Gemessen hat der Fusstext der neuen Box deshalb
   14px getragen statt der gesetzten 10,5.

   Die Box hat seit v6.42 keine Ueberschrift und keine Erklaerzeilen
   mehr, sondern Reiter, ein Formular und einen Fuss - jedes mit
   eigener Groesse. Was hier stand, hatte nichts mehr zu regeln. */
#setup-screen #auth-section > p { text-align: center; }
#setup-screen #consent-row {
    justify-content: center !important;
    font-size: 14px !important;
}
#setup-screen #consent-box {
    accent-color: var(--n-zug);
    width: 20px !important; height: 20px !important;
}
#setup-screen #auth-section a { color: var(--n-zug) !important; }
#setup-screen #g-signin { display: flex; justify-content: center; }
/* Der Stift zum Namenaendern ist ein Zeichen, kein Emoji. */
.name-edit-icon {
    background: none !important; border: 0 !important;
    color: var(--n-dim2) !important; font-size: 14px !important;
    cursor: pointer; padding: 0 4px !important; width: auto !important;
}
.name-edit-icon:hover { color: var(--n-zug) !important; }


/* =========================================================
   DER NAMENS-EDITOR IM STARTBILDSCHIRM

   Oeffnet sich ueber den Stift an der Willkommenszeile. Kam bisher
   mit den alten Inline-Farben; jetzt eine Karte wie der Anmeldekasten,
   nur ruhiger - sie ist Werkzeug, kein Auftritt.
   ========================================================= */
#setup-screen #name-edit {
    background: var(--n-panel) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 14px !important;
    padding: 14px !important;
    text-align: left;
}
#setup-screen #name-edit label { color: var(--n-dim) !important; font-size: 12px; }
#setup-screen #name-edit .optin-row {
    display: flex; align-items: center; gap: 8px;
    margin: 10px 0 0; color: var(--n-dim);
}
#setup-screen #name-edit input[type="checkbox"] { accent-color: var(--n-zug); }
#setup-screen #name-save-btn {
    background: var(--n-zug) !important; color: #04171C !important;
    border-color: #7DF2FF !important;
    width: 100%;
}
#setup-screen #athlete-name-status { color: var(--n-dim2) !important; }
/* Solange nichts zu sagen ist, nimmt der Hinweis keinen Platz: die
   min-height aus game.html hielt eine leere Zeile frei, damit der
   Aufbau beim Erscheinen nicht springt. Seit der Hinweis ein Kasten
   ist, sind die reservierten 14 px ohnehin zu wenig - sie hielten nur
   eine Luecke ueber dem Trennstrich offen. */
#setup-screen #athlete-name-status:empty {
    min-height: 0 !important; margin: 0 !important;
}

/* =========================================================
   DER "NEU HIER"-BILDSCHIRM

   Rueckkehrer bekamen zwei Kaesten und eine klare Hauptsache; wer zum
   ERSTEN Mal kam, sah fuenf gleich laute Bloecke untereinander und vier
   Knoepfe in voller Breite - zwei davon (Hall of Fame, Abmelden) haben
   mit dem Anfangen nichts zu tun. Der eigentliche Weg (Name, dann
   Athlet) war darin nicht zu erkennen.

   Jetzt: alles zum Anfangen in EINER Karte, die zwei Schritte
   nummeriert, darunter der leise Kasten mit der Hall of Fame und ganz
   unten das Abmelden. Der Seitenkopf haengt .neu-hier an
   #character-select und baut die Kaesten; hier steht nur das Aussehen.

   Die Nummern sind ::before an den vorhandenen Beschriftungen - kein
   zusaetzliches Markup, das die Vorlesehilfe zweimal ansagen wuerde.
   ========================================================= */
/* Die Begruessung ist im Neu-Fall kein Auftritt, sondern der Kopf der
   Karte: sie steht IN ihr und darf sie nicht ueberstrahlen. */
#character-select.neu-hier #user-welcome {
    font-size: 16px !important;
    margin: 0 0 16px !important;
    padding-bottom: 10px;
}
#character-select.neu-hier #user-welcome::after { width: 48px; height: 2px; }

/* Schritt 1 und 2: die Nummer sitzt vor der Beschriftung, gleich gross
   in beiden Zeilen. Die Marke traegt sie, nicht der Kasten - so bleibt
   sie auch dann daneben, wenn der Text umbricht. */
#character-select.neu-hier #name-edit > label[for="athlete-name-input"],
#character-select.neu-hier #start-label {
    display: flex; align-items: center; gap: 8px;
    font: 700 12.5px system-ui, sans-serif !important;
    color: var(--n-fg) !important;
    letter-spacing: .01em;
}
#character-select.neu-hier #name-edit > label[for="athlete-name-input"]::before,
#character-select.neu-hier #start-label::before {
    flex: 0 0 auto;
    width: 19px; height: 19px; border-radius: 50%;
    display: grid; place-items: center;
    background: rgba(0,229,255,.14);
    border: 1px solid rgba(0,229,255,.5);
    color: var(--n-zug);
    font: 800 11px system-ui, sans-serif;
}
#character-select.neu-hier #name-edit > label[for="athlete-name-input"]::before { content: "1"; }
#character-select.neu-hier #start-label::before { content: "2"; }

/* Das Namensfeld ist innerhalb der Karte kein zweiter Kasten mehr -
   ein Rahmen im Rahmen macht die Karte zur Schachtel. Nur ein Strich
   trennt die beiden Schritte. */
#character-select.neu-hier #name-edit {
    background: none !important;
    border: 0 !important;
    padding: 0 !important;
}
#character-select.neu-hier #start-box {
    margin-top: 16px !important;
    padding-top: 16px !important;
    border-top: 1px solid var(--n-line) !important;
}
#character-select.neu-hier #start-label { margin: 0 0 10px !important; }

/* Die beiden Athletenknoepfe sind DIE Handlung: nebeneinander, gross
   genug zum Treffen, mit ihrer jeweiligen Randfarbe (steht weiter
   oben). Die Zeile darunter sagt in einem Satz, was der Klick tut -
   vorher war "Gains-Gerd" ein Knopf ohne Folge, die man erraten musste. */
#character-select.neu-hier #start-box .btn-group {
    display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
    margin-top: 0 !important;
}
#character-select.neu-hier #start-box .btn-group button {
    padding: 15px 8px !important;
    font-size: 14px !important;
}
#character-select.neu-hier #start-box::after {
    content: "Der Klick legt deinen Spielstand an. Umbenennen geht später.";
    display: block; margin-top: 10px;
    color: var(--n-dim2); font: 400 11px/1.45 system-ui, sans-serif;
    text-align: center;
}

/* Die Hall of Fame im leisen Kasten: ein Angebot zum Umsehen, kein
   Schritt des Starts - deshalb ohne Knopfgewicht. */
#character-select.neu-hier .start-karte.leise {
    margin-top: 12px;
    padding: 12px 14px !important;
}
#character-select.neu-hier .start-karte.leise #hof-box { margin-top: 0; }
#character-select.neu-hier #hof-btn {
    /* Ohne eigenen Rahmen: der Kasten hat schon einen, zwei ineinander
       sind ein Rahmen zu viel. */
    background: none !important;
    border: 0 !important;
    color: var(--n-dim) !important;
    font: 600 12.5px system-ui, sans-serif !important;
    text-decoration: none !important;
    width: 100%;
}
#character-select.neu-hier #hof-btn:hover { color: var(--n-fg) !important; }

/* =========================================================
   DIE BESTANDSZEILE UNTER DEM COCKPIT

   Konto, Pokale und Karma - aus der Buehne hierher verschoben (siehe
   Seitenkopf in spiel-neu.js). Sie scrollt mit dem Inhalt weg: die
   drei Zahlen aendern sich nicht im Sekundentakt und muessen nicht
   dauerhaft im Bild stehen. Wert und Beschriftung nebeneinander, wie
   im Laborentwurf - eine zweite Textzeile kostete dort 65 statt 31
   Pixel.
   ========================================================= */
.bestandszeile {
    display: flex; gap: 4px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--n-line);
}
.bestandszeile > div {
    flex: 1; display: flex; align-items: baseline;
    justify-content: center; gap: 5px;
}
.bestandszeile .wert {
    font: 700 14px ui-monospace, Menlo, monospace;
    font-variant-numeric: tabular-nums;
    color: var(--n-fg);
}
.bestandszeile .kopf {
    font: 800 9.5px system-ui, sans-serif;
    color: var(--n-dim2);
    text-transform: uppercase; letter-spacing: .07em;
    white-space: nowrap;
}
/* Gold fuer das Konto - die Farbe, die im ganzen Spiel "Geld" heisst. */
.bestandszeile .konto .wert, .bestandszeile .cash .wert { color: var(--n-gold); }

/* =========================================================
   DER ERSTE RUNDGANG

   Fuenf Schritte durch den echten Bildschirm. Das Ziel bleibt hell,
   alles andere liegt unter einem riesigen Schlagschatten - so braucht
   es keine zweite Ebene und keinen Ausschnitt, und das Ziel sieht aus
   wie es ist, nicht wie eine Nachbildung.
   ========================================================= */
/* DER NAMENSHINWEIS ALS WARNKASTEN.

   Vorher eine schmale rote Zeile unter dem Knopf. Jetzt ein Kasten mit
   Rand und Zeichen, dazu ein roter Rahmen am Eingabefeld - der Grund
   steht dort, wo man ihn sucht. */
#setup-screen #athlete-name-status.name-fehler {
    display: block;
    margin: 10px 0 0 !important;
    padding: 9px 12px 9px 32px;
    position: relative;
    background: rgba(255, 77, 94, .10);
    border: 1px solid rgba(255, 77, 94, .55);
    border-radius: 10px;
    color: #FFB4BA !important;
    font: 700 12.5px/1.45 system-ui, sans-serif !important;
    text-align: left;
}
#setup-screen #athlete-name-status.name-fehler::before {
    content: "!";
    position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
    width: 16px; height: 16px; border-radius: 50%;
    display: grid; place-items: center;
    background: var(--n-krit); color: #1a0508;
    font: 900 11px system-ui, sans-serif;
}
#setup-screen #athlete-name-input.feld-fehler {
    border-color: var(--n-krit) !important;
    box-shadow: 0 0 0 3px rgba(255,77,94,.16) !important;
}
@keyframes name-wink {
    0%, 100% { transform: translateX(0); }
    25%      { transform: translateX(-4px); }
    75%      { transform: translateX(4px); }
}
#setup-screen #athlete-name-status.name-wink { animation: name-wink .28s ease-in-out 2; }
@media (prefers-reduced-motion: reduce) {
    #setup-screen #athlete-name-status.name-wink { animation: none; }
}



/* =========================================================
   VOLLBILD-SZENEN LEEREN DIE BUEHNE

   Schlafen, Sauna, Restday spielen als Szene auf der Leinwand. Ringe,
   Gewicht, Statuszeile und Banner sind DOM-Auflagen und wuerden sonst
   mitten im Schlafzimmer stehen. Die Klasse setzt der Seitenkopf im
   Takt; die Uebergaenge passen zur Blendrampe der Szene.
   ========================================================= */
.buehne .kopfwerte,
.buehne .buehne-banner,
.buehne .buehne-fuss { transition: opacity .65s ease; }
.buehne.szene-laeuft .kopfwerte,
.buehne.szene-laeuft .buehne-banner,
.buehne.szene-laeuft .buehne-fuss {
    opacity: 0;
    pointer-events: none !important;
}


/* =========================================================
   BUEHNE ZUERST – VOLLBILD-BUEHNE MIT SCHUBLADE

   Der Umbau aus dem Layout-Labor (layout-labor/buehne.html, Layout 1
   "Schublade" + Meldungsweg C "Flugzahl + Bon", gewaehlt am
   09.08.2026).

   VORHER: Die Buehne war rund 330 px hoch, darunter die Meldungsbox,
   darunter die Knopfblaetter - alles zusammen ein Blaetterbereich, in
   dem man staendig scrollte. Die Figur, um die es geht, bekam ein
   Drittel des Bildschirms.

   NACHHER: Die Buehne bekommt alles, was Kopfzeile und Reiterleiste
   uebrig lassen. Die Knopfblaetter fahren als Schublade darueber und
   sind zu, solange man sie nicht braucht.

   Dieser Abschnitt steht am DATEIENDE, weil er die Anordnung zuletzt
   festlegt: die Regeln weiter oben stammen aus dem Eckenlayout und
   tragen an vielen Stellen !important. Sie einzeln aufzudroeseln haette
   den Umbau in 40 Einzelaenderungen zerlegt, von denen jede fuer sich
   nicht nachvollziehbar waere.
   ========================================================= */

/* ---------- 1. DER BLAETTERBEREICH SCROLLT NICHT MEHR ----------
   Er ist jetzt der Rahmen, in dem Buehne und Schublade liegen. Gescrollt
   wird nur noch IN der Schublade. */
.blaettern {
    position: relative;
    overflow: hidden !important;
    flex: 1 1 auto; min-height: 0;
}

/* ---------- 2. DIE BUEHNE FUELLT DEN RAHMEN ---------- */
.cockpit {
    position: absolute !important; inset: 0;
    display: flex; flex-direction: column;
    /* KEIN POLSTER FUER DIE SCHUBLADE.

       Hier stand "padding-bottom: var(--schub-hoch)". Das verkleinerte
       die Buehne, der Zeichner rechnete daraufhin neu, und die Figur
       sprang beim Oeffnen des Menues auf eine andere Groesse. Jetzt
       behaelt die Buehne ihre Hoehe - was ausweichen muss, WANDERT
       (siehe .schiebt weiter unten). Der Zeichner merkt vom Menue
       nichts mehr. */
    padding: 0 !important;
    /* z-index 1 statt der 20 aus der alten Sticky-Regel. Solange das
       Polster die Buehne verkuerzte, lag die Schublade in einem
       Bereich, in dem das Cockpit gar nicht malte - der zu hohe Wert
       fiel nicht auf. Seit die Buehne die volle Hoehe fuellt, deckte
       sie die Schublade (z-index 12) vollstaendig zu: gemessen lag an
       der Stelle, wo die Knoepfe stehen sollten, .buehne obenauf. */
    z-index: 1 !important;
    border-bottom: 0 !important;
    background: none !important;
    backdrop-filter: none !important;
}

/* ---------- WAS DER SCHUBLADE AUSWEICHT, WANDERT NACH OBEN ----------

   Drei Dinge liegen unten und wuerden sonst hinter dem Menue
   verschwinden: die Leinwand mit der Figur, die Ringreihe und die
   Statuszeile. Sie werden um die Schubladenhoehe angehoben - dieselbe
   Strecke, dieselbe Kurve, damit sie als ein Bild wandern.

   Die Auflagen am OBEREN Rand (Bestandschips, runde Zeichen, Banner,
   Meldungszettel) bleiben stehen: sie haben mit der Schublade nichts zu
   tun, und mitzuwandern hiesse, aus dem Bild zu laufen. */
.kopfwerte .ringreihe,
.buehne-fuss {
    transform: translateY(calc(var(--schub-hoch, 0px) * -1));
    /* opacity faehrt mit, weil beide beim Oeffnen zurueckgehen: die
       Statuszeile ganz, die Ringreihe ein Stueck. Ohne diese Angabe
       spraengen sie hart um, waehrend sie weich wandern. Kuerzer als
       die Fahrt (.35s gegen .45s): das Licht soll vor der Bewegung
       stehen, nicht hinterherlaufen. */
    transition: transform .45s cubic-bezier(.34,1.6,.5,1), opacity .35s ease;
}
/* Die Leinwand wandert mit - ihre Angabe steht unten bei
   ".buehne > canvas", weil dort auch die waagerechte Zentrierung
   sitzt und zwei transform-Regeln einander ausloeschen wuerden. */
.buehne {
    flex: 1 1 auto; min-height: 0;
    position: relative;
    overflow: hidden;
    /* DER STREIFEN UNTEN GEHOERT NICHT DER LEINWAND.

       Darin liegen Ringreihe (unten) und Statuszeile (darueber). Ohne
       ihn endet die Leinwand am Buehnenboden - und weil die Figur dort
       nur 26 von 240 Zeichen-Einheiten ueber der Unterkante steht,
       standen die Ringe ihr bis zur Huefte im Bild. Nachgesehen im
       ersten Anlauf, nicht gerechnet.

       KEIN POLSTER MEHR HIER. Der Streifen steckt jetzt im Zeichner
       (BODEN_RESERVE_PX in 06a-engine.js): er setzt GROUND_Y so, dass
       die Figur ueber der Ringreihe steht. Ein Polster am Behaelter
       wuerde die Leinwand verkleinern, statt die Figur zu heben - und
       damit wieder einen Kasten erzeugen.

       Der Grund traegt den Wandton der Szene, nicht den Seitengrund:
       bei offener Schublade wird die Leinwand schmaler als die Buehne
       (sonst passte die Figur nicht mehr hinein), und ein dunklerer
       Rand darum haette sie wieder als Kasten gerahmt. */
    background: #151c25;
}

/* DIE LEINWAND BEHAELT IHR SEITENVERHAELTNIS.

   06a-engine.js rechnet in einem festen Koordinatensystem
   (VIEW = 300x240) und setzt die Leinwand per Inline-Stil auf genau
   dieses Mass. Sie auf die freie Hoehe zu ziehen wuerde die Figur
   verzerren - und alles mit ihr, was der Zeichner als Quadrat anlegt
   (Zustandskacheln, Erklaerungskaesten). Die Leinwand sitzt deshalb
   unten in der Buehne, der Rest der Flaeche ist Studioraum. */
/* DIE LEINWAND FUELLT DIE BUEHNE - RANDLOS.

   Hoehe und Breite setzt setupCanvas() in 06a-engine.js selbst (Breite
   = 130 % der Buehne, damit die Figur gross genug wird; der Ueberhang
   wird hier abgeschnitten). Deshalb steht hier KEINE Groesse: jedes
   width/height mit Nachdruck wuerde die Rechnung des Zeichners
   ueberschreiben, und genau daran haben Figur und Trefferflaechen
   vorher nicht mehr zusammengepasst.

   Keine Maske mehr, kein Seitenverhaeltnis, kein eigener Hintergrund:
   die Szene IST der Bildschirm. */
.buehne > canvas {
    /* MIT NACHDRUCK: spiel-basis.html setzt #avatarCanvas per
       ID-Selektor auf position:relative und top:-22px (Versatz aus dem
       alten gerahmten Layout). Eine ID schlaegt jede Klassenregel -
       ohne !important saesse die Leinwand 22 px zu hoch und im Fluss. */
    position: absolute !important;
    top: 0 !important; left: 50% !important;
    /* Die Waagerechte zentriert, die Senkrechte weicht der Schublade
       aus. BEIDES IN EINER ANGABE: eine zweite transform-Regel weiter
       oben wuerde diese hier nicht ergaenzen, sondern von ihr
       ueberschrieben - genau das ist beim ersten Anlauf passiert, die
       Buehne blieb stehen.

       DEN BETRAG RECHNET DER SEITENKOPF (--buehne-hoch). Hier standen
       zwei feste Anteile der Schubladenhoehe - 0,7 fuer die Figur und
       0,3 waehrend einer Szene. Zwei Zahlen fuer denselben Zweck, und
       bei 0,3 lag das Bett der Schlafszene unterhalb des sichtbaren
       Streifens: die Animation war bei offenem Menue nicht zu sehen.

       Die Regel dahinter steht bei buehneHochPx(): der Boden wird an die
       Unterkante des sichtbaren Streifens gelegt. Daran haengt alles -
       die Figur steht darauf, Bett, Weg und Bank liegen knapp darueber.
       Skaliert wird weiterhin nichts. */
    transform: translate(-50%, calc(var(--buehne-hoch, 0px) * -1));
    transition: transform .45s cubic-bezier(.34,1.6,.5,1);
    margin: 0 !important;
    max-width: none !important;
    background: none !important;
}

/* Die Auflagen spannen ueber die GANZE Buehne, nicht nur ueber die
   Leinwand - sonst klebten Ringe und Masse am oberen Rand der
   Zeichenflaeche statt an den Raendern des Bildschirms. */
.kopfwerte { position: absolute !important; inset: 0; }

/* ---------- 3. DIE BESTAENDE ALS CHIPS IN DER ECKE ----------

   Aus dem Laborentwurf: Masse, Konto und Karma stehen als kleine
   Plaketten oben links auf der Buehne - was man HAT, getrennt von den
   Ringen, die LAUFEN. Unter den Fuessen ist jetzt die Ringreihe.

   POKALE SIND RAUS. Vier Chips waren einer zu viel, und die Pokalzahl
   steht ohnehin in der Hall of Fame; Karma dagegen aendert sich beim
   Spielen und traegt ein eigenes Symbol.

   Die Beschriftungen (.kopf) bleiben weg: "84 kg" und "70k €" sagen
   ihre Einheit selbst, Karma sein Symbol. Ein Wort daneben waere
   dieselbe Auskunft zweimal - an der Stelle mit dem wenigsten Platz. */
.kopfwerte .bestand > div > .kopf,
.kopfwerte .bestand > button > .kopf { display: none !important; }
.kopfwerte .bestand {
    position: absolute !important;
    left: 10px !important; right: auto !important;
    top: 10px !important; bottom: auto !important;
    display: flex !important; flex-direction: column;
    align-items: flex-start; gap: 5px;
    width: max-content;
}
/* Karma und Konto sind <button> (36-kopfwerte.js), nicht <div>: sie
   tragen einen Erklaerkasten. Beide Regeln hier standen auf "div" und
   liessen die Knoepfe deshalb durchrutschen - die Beschriftung "KARMA"
   stand danach im Chip, wo nur Zeichen und Zahl hingehoeren. */
.kopfwerte .bestand > div,
.kopfwerte .bestand > button { display: none !important; }
.kopfwerte .bestand > .masse,
.kopfwerte .bestand > .konto,
.kopfwerte .bestand > .karma {
    display: inline-flex !important; align-items: center;
    flex: 0 0 auto !important;
    width: max-content !important;
    margin: 0 !important;
    padding: 3px 12px 4px;
    border-radius: 999px;
    background: rgba(8, 11, 15, 0.7);
    border: 1px solid rgba(43, 52, 63, 0.9);
    backdrop-filter: blur(6px);
    pointer-events: auto;
}
/* JEDER CHIP TRAEGT SEIN ZEICHEN - wie im Entwurf.

   Als SVG im Hintergrund, nicht als Emoji: Emoji sind laut Designlinie
   als Bedienzeichen raus, und der Spielcode baut die Chips selbst, also
   kaeme Markup dafuer nur ueber einen Eingriff dort. Karma ist die
   Ausnahme - sein Symbol liefert karmaTier() und traegt die Stufe, das
   ist Spielinhalt und kein Dekor. */
.kopfwerte .bestand > .masse,
.kopfwerte .bestand > .konto {
    padding-left: 30px;
    background-repeat: no-repeat;
    background-position: 10px center;
    background-size: 14px 14px;
}
.kopfwerte .bestand > .masse {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFD84D' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M4 9v6M20 9v6M7.5 6.5v11M16.5 6.5v11M7.5 12h9'/%3E%3C/svg%3E");
}
.kopfwerte .bestand > .konto {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300E5FF' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='8'/%3E%3Cpath d='M12 8v8M9.5 10h5M9.5 14h5'/%3E%3C/svg%3E");
}

/* KARMA STEHT AUF DERSELBEN LINIE.

   Masse und Konto tragen ihr Zeichen als Hintergrundbild an fester
   Stelle (10 px) und lassen ihm 30 px Innenabstand. Karma bekommt sein
   Zeichen vom Spielcode - als SVG MITTEN IM WERT, weil es die
   Karmastufe traegt und damit Inhalt ist, kein Dekor. Es lief deshalb
   im Textfluss mit: das Zeichen sass bei 23 statt 10, die Zahl bei 23
   statt 41, und der Chip war schmaler als die beiden darueber.
   Gemessen, nicht geschaetzt.

   Das Zeichen wird jetzt an dieselbe Stelle gelegt wie die beiden
   Hintergrundbilder - aus dem Fluss genommen, nicht ersetzt: welches
   Symbol es ist, entscheidet weiterhin karmaTier(). */
.kopfwerte .bestand > .karma {
    position: relative;
    padding-left: 30px;
}
.kopfwerte .bestand > .karma .wert .txt-ic {
    position: absolute; left: 10px; top: 50%;
    transform: translateY(-50%);
    width: 14px; height: 14px;
}

/* Die Masse traegt als einzige den Goldsaum: sie ist der Wert, um den es
   im ganzen Spiel geht. Konto und Karma bleiben neutral - dieselbe
   Staffelung wie bei den Knoepfen, wo auch nur drei Bedeutungen Farbe
   bekommen. */
.kopfwerte .bestand > .masse {
    border-color: rgba(255, 216, 77, 0.5);
    box-shadow: 0 0 18px rgba(255, 216, 77, 0.18), 0 4px 12px rgba(0, 0, 0, 0.5);
    /* NICHT anklickbar: der Rang steht in der Fusszeile, das Kaestchen
       am Massechip ist entfallen. Ein Zeigefinger-Mauszeiger auf etwas,
       das nichts tut, ist ein Versprechen ohne Deckung. */
    cursor: default;
}
.kopfwerte .bestand > .konto .wert,
.kopfwerte .bestand > .karma .wert {
    font: 800 13px/1 ui-monospace, Menlo, monospace !important;
    color: var(--n-fg) !important;
}
.kopfwerte .bestand > .konto .wert { color: var(--n-gold) !important; }

/* KONTO UND KARMA SIND ANTIPPBAR, MASSE NICHT.

   Der Unterschied muss am Chip zu sehen sein, sonst ist die Erklaerung
   ein Geheimnis. Die Beschriftung taugt nicht dafuer, sie ist hier
   ausgeblendet; also der Rand, in derselben Zugfarbe, die im ganzen
   Bildschirm "hier passiert etwas" heisst. */
.kopfwerte .bestand > button { cursor: pointer; transition: border-color .15s; }
@media (hover: hover) and (pointer: fine) {
    .kopfwerte .bestand > button:hover { border-color: rgba(0, 229, 255, 0.55) !important; }
}
.kopfwerte .bestand > button.is-offen { border-color: var(--n-zug) !important; }
.kopfwerte .bestand > button:focus-visible {
    outline: 2px solid var(--n-zug); outline-offset: 2px;
}

/* ---------- 3b. DIE WERKZEUGE IN DER ECKE ----------
   Seit die Kopfzeile weg ist, schweben Hilfe und Einladung als runde
   Zeichen oben rechts auf der Buehne. */
/* UNTEREINANDER, wie im Entwurf: Hilfe oben, Protokoll darunter.
   Seit die Meldung ganz oben ueber die volle Breite faehrt, liegt sie
   waehrend ihrer Standzeit darueber - siehe .bonstapel. */
.werkzeuge {
    position: absolute; top: 10px; right: 10px; z-index: 7;
    display: flex; flex-direction: column; gap: 7px;
}
.rundknopf {
    width: 38px; height: 38px; border-radius: 50% !important;
    display: grid; place-items: center;
    background: rgba(8, 11, 15, 0.7) !important;
    border: 1px solid rgba(43, 52, 63, 0.9) !important;
    color: var(--n-dim) !important;
    cursor: pointer; padding: 0 !important; width: 38px !important;
    backdrop-filter: blur(6px);
    transition: color .2s, border-color .2s, transform .13s cubic-bezier(.34,1.6,.5,1);
}
.rundknopf:hover { color: var(--n-fg) !important; border-color: var(--n-stahl) !important; transform: translateY(-2px); }
.rundknopf svg { width: 18px; height: 18px; display: block; }

/* Die Kopfzeile gibt es nicht mehr - die Regeln dazu koennen keinen
   Verwender mehr finden, aber ein Rest im Dokument soll auch nichts
   umbrechen koennen. */
.kopfleiste { display: none !important; }

/* ---------- 4. DIE MELDUNG ALS KARTE VON OBEN ----------
   Der Text faehrt oben ueber die volle Breite ein und geht nach ein
   paar Sekunden wieder hoch - die Benachrichtigung, die jedes Telefon
   zeigt. Der Verlauf geht dabei nicht verloren: er haengt am Schalter,
   den 14-ui.js ohnehin schon fuellt.

   ENTSCHIEDEN IM LAYOUT-LABOR (meldungen.html, Weg A mit Stapel): die
   Karte liegt ganz oben statt unter der Kopfzeile, und hoechstens zwei
   stehen gleichzeitig. #game-log selbst ist unsichtbar - es bleibt nur
   das Schreibziel von setLog(), von dem der Seitenkopf die Karten
   abliest. Die Klassennamen (.bonstapel, .bon) bleiben, damit der
   Zusammenhang mit bonZeigen() lesbar bleibt. */
#game-log { display: none !important; }
/* Nur in der eingebetteten Fassung (itch.io, Game Jolt; app/huelle.js zeigt es, v7.17). */
.nur-eingebettet { display: none; }

.bonstapel {
    /* GANZ OBEN UND UEBER DIE VOLLE BREITE - wie die Benachrichtigung
       auf dem Telefon. Vorher sass der Stapel als schmale Spalte bei
       104 px am rechten Rand, also genau dort, wo der Blick beim
       Athleten gerade NICHT ist; gemeldet als "die Nachrichten gehen
       unter".

       z-index 8 liegt ueber Werten, Namenspille und den beiden
       Rundzeichen (die haben 7). Das ist der Preis dieses Weges und er
       ist bewusst bezahlt: waehrend eine Meldung steht, sind Masse,
       Konto und der Name verdeckt. Seit v6.72 steht immer nur EINE
       Karte (Warteschlange in tools/spiel-neu.js), je nach Textlaenge
       3,8 bis 8 s; ein Fingertipp raeumt sie sofort weg. */
    position: absolute; top: 8px; left: 10px; right: 10px; z-index: 8;
    /* 4 px Abstand, nicht 6: im Spalt zwischen zwei Karten blitzten
       sonst die Werte darunter durch - ein halber Kontostand zwischen
       zwei Meldungen sieht aus wie ein Fehler. */
    display: flex; flex-direction: column; gap: 4px; align-items: stretch;
    pointer-events: none;
}
.bon {
    background: rgba(8, 11, 15, 0.97);
    border: 1px solid var(--n-line);
    border-left: 3px solid var(--n-line);
    border-radius: 14px;
    padding: 9px 13px;
    /* RUHIGER ALS DER ZETTEL: ueber die volle Breite ist fetter Text
       ein Schild. Normale Staerke, etwas groesser, hellere Grundfarbe -
       gelesen wird das hier, nicht ueberflogen. */
    font: 400 12.5px/1.35 system-ui, sans-serif;
    color: var(--n-fg);
    backdrop-filter: blur(6px);
    box-shadow: 0 12px 30px -14px #000;
    animation: bon-rein .3s cubic-bezier(.34,1.5,.5,1);
    transition: opacity .45s ease, transform .45s cubic-bezier(.4,0,.2,1);
}
/* HINEIN UND HINAUS GEHT ES NACH OBEN. Die Fahrt von rechts gehoerte
   zum Zettel am Rand; oben waere sie eine Bewegung ohne Bezug. */
@keyframes bon-rein { from { opacity: 0; transform: translateY(-140%); } }
.bon.weg { opacity: 0; transform: translateY(-140%); }
/* ANTIPPEN SCHLIESST DEN ZETTEL.

   .bonstapel hat pointer-events: none, damit die Zettel nicht die
   Buehne darunter blockieren - der Athlet laesst sich auch antippen,
   wenn gerade eine Meldung steht. Die Annahme wird deshalb hier auf
   den einzelnen Zettel zurueckgegeben, nicht auf den Stapel: nur der
   Zettel selbst faengt Klicks, der Zwischenraum bleibt durchlaessig.

   Das Wegwischen von Hand ist schneller als das automatische
   Verblassen (.55 s): wer tippt, will es weghaben und nicht dabei
   zusehen. */
.bon { pointer-events: auto; cursor: pointer; }
.bon.weg-klick {
    transition: opacity .16s ease, transform .16s ease;
    opacity: 0; transform: translateY(-120%);
}
/* GUTE NACHRICHT GRUEN, SCHLECHTE ROT.

   Gemeldet: "die eingeblendeten Nachrichten sind nicht zu
   unterscheiden" - und so war es, jeder Zettel war grau.

   DIE FARBE SITZT IN DER KANTE UND IM TEXT, NICHT IN DER FLAECHE. Ein
   gruen hinterlegter Kasten neben einem roten waere im Bild lauter als
   die Buehne dahinter; die Zettel sollen die Aufmerksamkeit kurz
   holen, nicht behalten. Die 3 Pixel Kante links gab es ohnehin schon,
   sie bekommt nur eine Bedeutung.

   Gruen ist --n-lime, das lebendige Gruen der Designlinie. Rot ist
   --n-krit, dasselbe wie bei der Warnung - eine dritte Rotnuance waere
   nur eine weitere Farbe ohne eigene Bedeutung.

   Wer keinen Ton hat, bleibt grau. Das ist die Mehrheit, und das soll
   so sein: faerbte man auch Sprueche und Studiozustaende ein, waeren
   die echten Nachrichten wieder nicht zu finden. */
.bon.gut {
    border-left-color: var(--n-lime);
    color: #d8ffc2;
}
.bon.schlecht {
    border-left-color: var(--n-krit);
    color: #ffd3d7;
}

/* Dringlichkeit steckt in der Kante, nicht im Blinken. */
.bon.warn { border-left-color: var(--n-krit); color: #ffd3d7; }

/* MEHRERE MELDUNGEN AUF EINER KARTE (v6.75). Kommen sie dicht
   hintereinander, buendelt bonZeigen() sie - jede als eigene Zeile,
   getrennt durch eine feine Linie statt durch eine zweite Karte. */
.bon > div + div {
    margin-top: 5px; padding-top: 5px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}

/* =========================================================
   FLUGZAHLEN AN IHREM WERT

   Gemeldet: "bei der Punktevergabe dem entsprechenden Kreis zuweisen,
   sodass besser erkennbar ist, was fuer Punkte dazugekommen sind oder
   abgezogen wurden". Vorher stiegen alle Zahlen aus der Mitte des
   Athleten auf, und die Zuordnung steckte allein in der Farbe.

   Die Schicht liegt FEST ueber allem und faengt keine Klicks - eine
   Zahl, die eine Sekunde lang ueber einem Ring steht, darf ihn nicht
   unbedienbar machen.

   z-index 60: ueber Buehne, Zetteln und Schublade, aber unter den
   Fenstern (Modal, Protokoll) - waehrend ein Fenster offen ist, hat
   eine fliegende Zahl dort nichts zu suchen. */
.flugschicht {
    position: fixed; inset: 0; z-index: 60;
    pointer-events: none; overflow: hidden;
}
.flugzahl {
    position: absolute;
    transform: translate(-50%, -100%);
    --flug-x: -50%;
    --flug-y: -100%;
    white-space: nowrap;
    font: 900 13px/1 ui-monospace, Menlo, monospace;
    letter-spacing: -0.02em;
    /* Dunkler Rand: die Zahl steht ueber Ringen, Bühne und Kulisse -
       auf hellem Grund waere Gruen allein nicht zu lesen. */
    text-shadow: 0 1px 0 rgba(2,6,23,0.9), 0 0 6px rgba(2,6,23,0.8);
    animation: flug-auf 1.1s cubic-bezier(.22,.9,.3,1) forwards;
}
/* Gruen hoch, rot runter - dieselbe Aussage wie bei den Meldungen, und
   dieselben zwei Farben. Eine dritte Deutung derselben Sache waere eine
   zu viel. */
.flugzahl.plus  { color: var(--n-lime); }
.flugzahl.minus { color: var(--n-krit); }
/* NEBEN DER BESTANDSZEILE STATT DARUEBER. Sie steht am oberen
   Bildrand; dort war kein Platz nach oben, die Zahl lag auf dem Wert,
   den sie erklaeren soll. Die Bewegung bleibt dieselbe, nur der
   Ankerpunkt wandert nach rechts neben den Chip. */
.flugzahl.rechts { --flug-x: 0%; --flug-y: -50%; }

@keyframes flug-auf {
    0%   { opacity: 0; transform: translate(var(--flug-x), var(--flug-y)) scale(0.85); }
    18%  { opacity: 1; transform: translate(var(--flug-x), var(--flug-y)) scale(1.06); }
    30%  { transform: translate(var(--flug-x), calc(var(--flug-y) + var(--flug-hoch) * 0.35)) scale(1); }
    72%  { opacity: 1; }
    100% { opacity: 0; transform: translate(var(--flug-x), calc(var(--flug-y) + var(--flug-hoch))) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    /* Ohne Bewegung, aber nicht ohne Aussage: sie steht kurz da und
       geht wieder. */
    .flugzahl { animation: flug-still 1.1s linear forwards; }
    @keyframes flug-still { 0%,80% { opacity: 1; } 100% { opacity: 0; } }
}

/* Der Zaehler am Protokollknopf. */
.rundknopf { position: relative; }
.rundknopf .zaehler {
    position: absolute; top: -4px; right: -4px;
    min-width: 16px; height: 16px; padding: 0 4px;
    border-radius: 999px;
    background: var(--n-zug); color: #04171c;
    font: 900 9px/16px system-ui, sans-serif; text-align: center;
}
.rundknopf .zaehler[hidden] { display: none; }

/* ---------- DAS PROTOKOLL ---------- */
.protokoll {
    position: absolute; inset: 0; z-index: 40;
    display: flex; flex-direction: column;
    background: rgba(6, 8, 11, 0.94);
    backdrop-filter: blur(10px);
}
.protokoll[hidden] { display: none; }
.protokoll header {
    flex: 0 0 auto;
    display: flex; align-items: center; gap: 10px;
    padding: 14px 16px; border-bottom: 1px solid var(--n-line);
}
.protokoll header h2 { font: 900 15px system-ui, sans-serif; margin: 0; color: var(--n-fg); }
.protokoll header button {
    margin-left: auto; background: none !important; border: 0 !important;
    color: var(--n-dim) !important; font: 800 12px system-ui, sans-serif !important;
    width: auto !important; padding: 4px !important; cursor: pointer;
}
.protokoll ol { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 8px 16px 20px; margin: 0; list-style: none; }
.protokoll li {
    display: flex; gap: 10px; padding: 9px 0;
    border-bottom: 1px solid rgba(43, 52, 63, 0.5);
    font: 400 12.5px/1.4 system-ui, sans-serif; color: var(--n-dim);
}
.protokoll li time {
    flex: 0 0 40px;
    font: 700 11px ui-monospace, Menlo, monospace; color: var(--n-dim2);
}
.protokoll li.leer { color: var(--n-dim2); font-style: italic; border: 0; }
/* Dieselbe Unterscheidung wie auf den Zetteln - wer eine rote Meldung
   verpasst hat, sucht sie hier und soll sie am selben Merkmal
   wiederfinden. Nur der Text faerbt sich: eine Liste mit farbigen
   Kanten je Zeile waere ein Zebrastreifen. */
.protokoll li.gut span:not(.nadel) { color: #cdf5b4; }
.protokoll li.schlecht span:not(.nadel) { color: #ffc9cf; }
/* Angeheftet: was gerade GILT, nicht was passiert ist. Steht oben,
   traegt eine Nadel statt einer Uhrzeit und hebt sich leicht ab. */
.protokoll li.angeheftet {
    color: var(--n-fg);
    background: rgba(0, 229, 255, 0.05);
    border-bottom-color: rgba(0, 229, 255, 0.22);
    margin: 0 -16px; padding-left: 16px; padding-right: 16px;
}
.protokoll li.angeheftet .nadel { flex: 0 0 40px; font-size: 12px; }

/* Die alte Meldungsbox-Gestaltung - sie greift nur noch, falls
   #game-log doch einmal sichtbar gemacht wird. */
.log {
    position: absolute !important;
    /* 66 px: unter der Zeile mit den beiden runden Zeichen (10 + 38 +
       Luft). Er darf beliebig hoch werden, darunter ist frei. */
    top: 66px; right: 10px; left: auto;
    max-width: 62%; width: max-content;
    margin: 0 !important;
    padding: 7px 12px !important;
    z-index: 6;
    font-size: 12px !important;
    line-height: 1.35 !important;
    color: var(--n-dim) !important;
    background: rgba(8,11,15,.86) !important;
    border: 1px solid var(--n-line) !important;
    border-left: 3px solid var(--n-line) !important;
    border-radius: 4px 12px 12px 4px !important;
    box-shadow: 0 8px 22px -12px #000;
    backdrop-filter: blur(6px);
    transition: opacity .5s ease;
}
.log::before { content: none !important; }
.log-jetzt { color: inherit !important; }
/* Dringlichkeit steckt in der Kante, nicht im Blinken. is-warn setzt
   14-ui.js ohnehin schon - hier bekommt es endlich eine ruhige Form. */
.log.is-warn {
    border-left-color: var(--n-krit) !important;
    color: #ffd3d7 !important;
    animation: none !important;
}
/* Verblasst, sobald eine Weile nichts kam. Die Klasse setzt der
   Seitenkopf; ohne JS bleibt der Bon einfach stehen. */
.log.bon-weg { opacity: 0; pointer-events: none; }
/* Aufgeklappter Verlauf darf nicht verblassen - man liest gerade. */
.log.verlauf-offen { opacity: 1 !important; max-width: 78%; }

/* Die Statuszeile (Rang, Bro, Konto) liegt auf der Buehne statt
   darunter - unter der Buehne ist jetzt die Reiterleiste. */
/* Die Statuszeile (Konto, Karma, Bro) sitzt im reservierten Streifen
   zwischen Leinwand und Ringreihe. 122 px, nicht 100: bei 100 lag sie
   quer auf den Ring-Beschriftungen ("70k €" ueber "Energie"). Die Reihe
   ist mit Beschriftung rund 100 px hoch und beginnt 10 px ueber dem
   Boden - darueber ist frei. */
.buehne-fuss {
    position: absolute !important; left: 0; right: 0;
    /* !important, weil die Regel aus dem Eckenlayout weiter oben
       bottom:0 mit Nachdruck setzt - dort lag die Zeile richtig, hier
       laege sie quer auf den Ring-Beschriftungen ("70k €" ueber
       "Energie"). Nachgemessen: Ringreihe 711..781, Zeile 762..791. */
    /* 99 statt 84: die Zeile stand den Ringen zu dicht auf dem Kopf und
       las sich als deren Ueberschrift statt als eigene Auskunft. Fuenf-
       zehn Punkte hoeher steht sie frei im Streifen zwischen Figur und
       Ringen - der Abstand nach unten ist damit ungefaehr so gross wie
       der Ring selbst hoch ist. */
    bottom: 99px !important;
    pointer-events: none;
    transition: opacity .2s;
}
/* Rang und Bro als PILLEN, wie im Entwurf: versal, gesperrt, auf
   halbdurchsichtigem Grund. Als loser Text auf der Szene waren sie
   je nach Bildinhalt mal lesbar, mal nicht.

   KEIN BALKEN DAHINTER. .buehne-fuss brachte aus dem alten Layout
   einen Verlauf ueber die ganze Breite mit (rgba(2,6,23,.92) nach
   oben) - dort lag die Zeile am unteren Bildrand und brauchte ihn.
   Mitten auf der Buehne ist er ein Streifen, den der Entwurf nicht
   hat: die beiden Pillen tragen ihren Grund selbst. */
.buehne-fuss { background: none !important; }
.buehne-fuss .status-row {
    gap: 8px !important;
    align-items: center !important;
    background: none !important;
    padding: 0 !important;
}
.buehne-fuss .status-row > span {
    background: rgba(8, 11, 15, 0.6);
    padding: 3px 10px;
    border-radius: 999px;
    font: 800 9px system-ui, sans-serif !important;
    letter-spacing: .12em;
    text-transform: uppercase;
}

/* DIE BANNER SIND UNSICHTBAR.

   Wetter und Welt-Ereignis standen hier als ein bis zwei Zeilen auf der
   Buehne. Sie melden sich jetzt beim Wechsel als Zettel und stehen im
   Protokoll oben angeheftet - eine dauerhafte Zeile quer ueber dem Bild
   braucht es dafuer nicht mehr.

   NUR VERSTECKT, NICHT ENTFERNT: der Spielcode schreibt weiter hinein,
   und der Seitenkopf liest die Texte von genau dort ab. Wer die
   Elemente entfernt, kappt die Quelle. */
.buehne-banner { display: none !important; }

/* An ihrer Stelle steht der Spielername - in der Luecke zwischen den
   Bestandschips links und den runden Zeichen rechts. */
.spieler-pille {
    position: absolute; z-index: 5;
    left: 50%; top: 12px; transform: translateX(-50%);
    max-width: calc(100% - 200px);
    display: inline-flex; align-items: center; gap: 7px;
    padding: 4px 12px 4px 5px;
    border-radius: 999px;
    background: rgba(8, 11, 15, 0.7);
    border: 1px solid rgba(43, 52, 63, 0.9);
    backdrop-filter: blur(6px);
    font: 800 12px system-ui, sans-serif;
    color: var(--n-fg);
}

/* Der Aufnahmepunkt der Studio-Doku: eine Stufe kleiner als der Name,
   direkt darunter, in derselben Sprache (dunkle Pille, heller Text).
   Der rote Punkt blinkt - das ist das Zeichen, an dem man REC erkennt. */
.doku-rec {
    position: absolute; z-index: 5;
    left: 50%; top: 42px; transform: translateX(-50%);
    display: inline-flex; align-items: center; gap: 4px;
    padding: 2px 7px 2px 6px;
    border-radius: 999px;
    background: rgba(8, 11, 15, 0.7);
    border: 1px solid rgba(43, 52, 63, 0.9);
    font: 800 9px/1 system-ui, sans-serif;
    letter-spacing: .04em;
    color: #f8fafc;
    pointer-events: none;
}
.doku-rec[hidden] { display: none; }
.doku-rec::before {
    content: ""; width: 6px; height: 6px; border-radius: 50%;
    background: #ef4444;
    animation: doku-rec-blink 1.2s steps(1) infinite;
}
@keyframes doku-rec-blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .doku-rec::before { animation: none; } }

/* DER PLATZ DER FIGUR, SOLANGE SIE LAEDT ODER NICHT LADEN KANN (06p,
   figurZustandZeigen). Mitte der Buehne, etwas ueber halber Hoehe - dort
   stuende sonst der Rumpf der Figur. Der Ring in der Farbe dessen, was man
   druecken soll; bei reduzierter Bewegung pulsiert er nur. */
.figur-zustand {
    position: absolute; z-index: 4; left: 50%; top: 42%;
    transform: translate(-50%, -50%);
    display: flex; flex-direction: column; align-items: center; gap: 10px;
    max-width: 76%; text-align: center; pointer-events: none;
    font: 700 13px system-ui, sans-serif; color: var(--n-dim);
}
.figur-zustand[hidden] { display: none; }
.figur-zustand .fz-ring {
    width: 34px; height: 34px; border-radius: 50%;
    border: 3px solid rgba(0, 229, 255, .18); border-top-color: var(--n-zug);
    animation: fz-dreh .9s linear infinite;
}
@keyframes fz-dreh { to { transform: rotate(360deg); } }
@keyframes fz-puls { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
    .figur-zustand .fz-ring { animation: fz-puls 1.6s ease-in-out infinite; }
}
.figur-zustand.fehler { color: var(--n-fg); }
.figur-zustand.fehler .fz-ring { display: none; }
.figur-zustand .fz-knopf {
    pointer-events: auto; display: inline-flex; width: auto;
    padding: 7px 16px; border-radius: 999px; border: 1px solid var(--n-zug);
    background: none; color: var(--n-zug); font: 800 12px system-ui, sans-serif;
}
.figur-zustand .fz-knopf[hidden] { display: none; }

/* DIE LAUFENDE SPERRE IN DER PLAKETTE.

   Dieselbe Sprache wie im Knopf (siehe .action-btn.is-cooling::before):
   eine dunkle Flaeche laeuft von links auf, vorn eine leuchtende Kante.
   Wer beides einmal gesehen hat, muss es kein zweites Mal lernen.

   overflow und position sind noetig, weil die Fuellung ein ::before
   ist - ohne sie liefe sie ueber den runden Rand hinaus. Der Inhalt
   bekommt z-index 1, damit Name und Zahl darueber bleiben. */
.spieler-pille { position: absolute; overflow: hidden; }
.spieler-pille > * { position: relative; z-index: 1; }
.spieler-pille.laeuft::before {
    content: ""; position: absolute;
    top: 0; bottom: 0; left: 0;
    width: var(--cd, 0%);
    background: linear-gradient(90deg, rgba(6,9,12,.62), rgba(6,9,12,.42));
    border-right: 2px solid var(--n-zug);
    box-shadow: 5px 0 14px rgba(0,229,255,.5);
    pointer-events: none; z-index: 0;
    transition: width .14s linear;
}
/* Die Restsekunden rechts, in derselben Ziffernschrift wie die Ringe -
   und mit fester Zeichenbreite, damit die Plakette beim Wechsel von
   10s auf 9s nicht zuckt. */
.spieler-pille .cd {
    font: 800 11px/1 ui-monospace, Menlo, monospace;
    color: var(--n-zug);
    font-variant-numeric: tabular-nums;
}
/* Leer nimmt sie keinen Platz - sonst stuende hinter dem Namen im
   Ruhezustand eine Luecke, fuer die es keinen Grund gibt. */
.spieler-pille .cd:empty { display: none; }
/* Im Kreis steht das Geschlechtszeichen. Die Farbe traegt der Grund:
   Blau fuer maennlich, Rosa fuer weiblich - dieselbe Aufteilung, die
   auch der Zeichner fuer die Hose benutzt (06c-athlete.js: #1e3a8a
   gegen #be185d). Das Zeichen selbst bleibt dunkel, damit es auf beiden
   Gruenden liest. */
.spieler-pille .initial {
    flex: 0 0 auto;
    width: 22px; height: 22px; border-radius: 50%;
    display: grid; place-items: center;
    background: var(--n-line); color: var(--n-dim2);
    /* 13 px: die beiden Zeichen sind schmaler gebaut als ein Buchstabe
       und wirkten bei 11 verloren. */
    font: 900 13px system-ui, sans-serif; font-style: normal;
    line-height: 1;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 14px 14px;
}

/* MARS UND VENUS ALS ZEICHNUNG, NICHT ALS SCHRIFTZEICHEN.

   Hier standen ♂ und ♀ (U+2642/U+2640) als Text. iOS setzt beide in
   Apple Color Emoji: farbig, in eigener Metrik und ohne die dunkle
   Schriftfarbe anzunehmen - im 22-px-Kreis blieb davon ein Fleck.
   Gemeldet als "auf dem iPhone nicht zu erkennen".

   Ein Variantenwaehler (U+FE0E) koennte Textdarstellung erzwingen, tut
   das aber nicht auf jedem Geraet zuverlaessig. Als SVG sieht es
   ueberall gleich aus - dieselbe Loesung wie bei den Bestandschips.

   font-size:0 raeumt einen etwaigen Textknoten weg. Das Fragezeichen
   (noch kein Name) traegt keine dieser Klassen und bleibt sichtbar. */
.spieler-pille .initial.m,
.spieler-pille .initial.w { font-size: 0; }
.spieler-pille .initial.m {
    background-color: #38bdf8;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2304171c' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9.5' cy='14.5' r='5.5'/%3E%3Cpath d='M14 10L20.5 3.5'/%3E%3Cpath d='M15 3.5h5.5V9'/%3E%3C/svg%3E");
}
.spieler-pille .initial.w {
    background-color: #f472b6;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232a0713' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8.5' r='5.5'/%3E%3Cpath d='M12 14v7'/%3E%3Cpath d='M8.5 17.5h7'/%3E%3C/svg%3E");
}
.spieler-pille .txt {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Waehrend der Anmeldung und ohne Konto: leiser Zustand, denselben
   Klassen folgend, die game.html ohnehin setzt. */
.spieler-pille.leer { color: var(--n-dim2); }
.spieler-pille.leer .initial {
    background: none; box-shadow: inset 0 0 0 1px var(--n-line); color: var(--n-dim2);
}

/* ---------- 5. DIE SCHUBLADE ---------- */
.panels {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 12;
    display: flex; flex-direction: column;
    /* Die Buehne rechnet nicht mehr mit diesem Wert - sie bekommt die
       ganze Hoehe und wird beim Oeffnen nur hochgeschoben. Was dabei
       oben hinausragt, ist nicht sichtbar; das ist so gewollt.

       50% + 30px: die Schublade oeffnet 30 Punkte hoeher. Um den
       Beschnitt oben muss sich niemand kuemmern - buehneHochPx() in
       tools/spiel-neu.js misst die tatsaechliche Hoehe der Schublade
       (offsetHeight) und schiebt die Buehne genau so weit nach oben.
       Eine zweite Zahl, die man mitziehen muesste, gibt es hier
       deshalb nicht. */
    max-height: calc(50% + 30px);
    padding: 0 !important;
    background: linear-gradient(180deg, #171e26, var(--n-bg2));
    border-top: 1px solid var(--n-line);
    border-radius: 22px 22px 0 0;
    box-shadow: 0 -18px 44px -18px #000;
    transform: translateY(101%);
    transition: transform .45s cubic-bezier(.34,1.6,.5,1);
    visibility: hidden;
}
#game-screen.schub-auf .panels { transform: none; visibility: visible; }

.schub-griff {
    flex: 0 0 auto; display: grid; place-items: center;
    padding: 8px 0 4px; cursor: pointer;
    background: none; border: 0; width: 100%;
}
.schub-griff i { width: 40px; height: 4px; border-radius: 999px; background: var(--n-line); display: block; }

.schub-kopf {
    flex: 0 0 auto; display: flex; align-items: baseline; gap: 8px;
    padding: 0 16px 8px; border-bottom: 1px solid var(--n-line);
}
.schub-kopf h2 {
    font: 900 15px system-ui, sans-serif; letter-spacing: -.02em;
    color: var(--ton, var(--n-fg)); margin: 0;
}
/* Hier stand der Knopf "Schliessen" (.schub-kopf .zu). Seit v7.26 weg:
   zu geht es ueber den Griff und den Reiter. */

.schub-inhalt {
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto; overscroll-behavior: contain;
    padding: 10px 12px 16px;
    scrollbar-width: none;
}
.schub-inhalt::-webkit-scrollbar { width: 0; }

/* ---------- 6. RINGE UND STATUSZEILE WEICHEN AUS ----------
   Sie liegen unten - also genau dort, wo die Schublade aufgeht. Blieben
   sie stehen, waeren die vier Werte, die einen umbringen koennen,
   ausgerechnet beim Einkaufen verdeckt. Die Pixelwerte setzt der
   Seitenkopf, sobald er die Schubladenhoehe gemessen hat. */
#game-screen.schub-auf .buehne-fuss { opacity: 0; }

/* DIE RINGE TRETEN ZURUECK, SOLANGE DAS MENUE OFFEN IST.

   Geschlossen stehen sie unter den Fuessen im freien Streifen und sind
   das Hauptinstrument. Offen wandern sie um die Schubladenhoehe nach
   oben - und liegen dann mitten auf der Figur, auf Huefthoehe, in
   voller Deckkraft. Nachgesehen im Testspiel, nicht gerechnet: vier
   kraeftige Kreise ueber Bauch und Pokalen, waehrend der Blick
   eigentlich im Regal darunter sucht.

   Weglassen waere falsch. Genau beim Einkaufen will man sehen, was
   Energie und Toxin gerade machen - dafuer wandern sie ueberhaupt mit.
   Sie sind dort nur nicht mehr das Hauptinstrument, sondern eine
   Nebenanzeige, und sehen jetzt auch so aus.

   DIE VERSCHIEBUNG MUSS MIT IN DIE ANGABE. transform kennt keine
   Teilwerte: ein blosses "scale(.86)" wuerde das translateY der
   Wander-Regel loeschen, und die Reihe bliebe hinter der Schublade
   stehen. Beides gehoert deshalb in eine Zeile, in dieser Reihenfolge
   (erst schieben, dann schrumpfen).

   scale statt kleinerer Schriftgrade: die Ringe sind gezeichnet, nicht
   gesetzt. font-size traefe nur Zahl und Etikett, und die Reihe fiele
   auseinander - kleine Zahlen in unveraendert grossen Kreisen.

   SEIT v7.25 OHNE VERKLEINERUNG. Die Schublade belegt seit der Gruppen-
   Leiste (v7.24) nur noch rund 45 % statt 57-61 %, ueber ihr ist Platz.
   Stephan: "die ringe und die zustandicons auf der buehne muessen bei
   geoeffneten menue auch nicht mehr so klein werden (haben ja jetzt mehr
   platz)". Sie wandern nur noch mit; die leisere Deckkraft bleibt -
   sie liegen weiter ueber den Beinen der Figur. */
#game-screen.schub-auf .kopfwerte .ringreihe {
    transform: translateY(calc(var(--schub-hoch, 0px) * -1));
    opacity: .72;
}

/* DER NAME GEHT, SOLANGE DAS MENUE OFFEN IST - ABER NUR IM BROWSER-TAB.

   Die Buehne wandert dann nach oben, und die Pille lag auf dem Kopf der
   Figur oder knapp darueber. Wer im Menue sucht, braucht seinen Namen
   nicht - und die Sperre, die die Pille sonst mitzeigt, laeuft in den
   Knoepfen selbst (.action-btn.is-cooling). Dieselbe Zeit wie die
   Statuszeile, damit beides zusammen geht.

   Seit v6.90 nur noch im Browser-Tab (html.im-browser, gesetzt von
   browserTabMerken in 06c-athlete.js): dort nehmen Adress- und
   Werkzeugleiste Hoehe weg. In der App und vom Startbildschirm ist Platz,
   der Name bleibt. Gewuenscht: "dass der spielername nur beim benutzen
   des browsers (nicht als app) bei geoeffnetem menue ausgeblendet wird". */
/* SEIT v7.25 BLEIBT ER. Stephan: "Auch muss der spielername nicht mehr
   verschwinden, wenn menue offen und im browser gespielt" - mit der
   Gruppen-Leiste ist ueber der Figur wieder Platz, und der Zoom haelt
   ihren Kopf unter den Chips (ZOOM_KOPF_PX, 06c). Mit der Pille bleibt
   auch der Aufnahmepunkt der Doku darunter stehen. tools/buehne-offen.test.js */

/* ---------- 7. HIER STAND EIN ZWEITER SATZ FLUGZAHLEN ----------

   Ein DOM-Behaelter mit eigener Aufstiegs-Animation. Ueberfluessig: die
   Zahlen zeichnet punkteFliegen() in 06f-fx.js auf die Leinwand, und
   zwar seit jeher. Beides zusammen blendete jeden Kaufbetrag zweimal
   ein. Das Markup dazu ist ebenfalls entfallen. */


/* =========================================================
   DIE FENSTER IM NEUEN GEWAND

   Flaechen und Raender waren schon angepasst (siehe weiter oben) - was
   fehlte, war die Anmutung: Die Kaesten erschienen hart, alle Knoepfe
   sahen gleich aus, und die Erklaerzeilen trugen fuenf verschiedene
   Grautoene aus Inline-Stilen der alten Seite.

   Drei Regeln, dieselben wie auf der Buehne:
     1. Was man druecken SOLL, traegt den Hauptzug-Akzent. Genau einer
        je Fenster - der erste Knopf ist immer der, um den es geht
        (Antreten, Wertungsduell, Match erstellen).
     2. Alles Erklaerende ist leise und gleich leise.
     3. Bewegung sagt, woher etwas kommt: die Kaesten steigen auf,
        wie die Schublade einfaehrt.
   ========================================================= */

.modal-box {
    padding: 22px 18px !important;
    border-radius: 20px !important;
    max-width: 420px !important;
    animation: fenster-auf .26s cubic-bezier(.34, 1.6, .5, 1);
}
@keyframes fenster-auf {
    from { opacity: 0; transform: translateY(14px) scale(.97); }
}
@media (prefers-reduced-motion: reduce) {
    .modal-box { animation: none; }
}

/* ---------- DAS EREIGNIS IM TAFEL-LAYOUT (v6.96) ----------
   Wie Dein Pumpling, Hall of Fame und das Duell: die Kopfzeile traegt
   Zeichen und Titel und ist mit einer Linie abgesetzt; bei Ereignissen
   und Entscheidungen steht darunter die Buehne mit der eigenen Figur
   (showModal mit modalBild). Vorher stand das Zeichen gross in einem
   Kreis ueber dem Titel. Die Buehne ist niedriger als in Dein Pumpling:
   Text und drei Knoepfe sollen auf dem Telefon ohne Rollen darunter
   passen. */
#modal-container .modal-box { padding-top: 0 !important; overflow: hidden; }
#modal-container .modal-box > h3 {
    /* Das Zeichen bleibt neben dem Titel; ein langer Titel bricht in sich
       um ("SHOWDOWN: Der Proteinshake-Papst" schob das Zeichen allein in
       die erste Zeile). */
    flex-wrap: nowrap;
    margin: 0 -18px 14px !important;
    padding: 15px 18px 14px;
    border-bottom: 1px solid var(--n-line);
}
#modal-buehne {
    position: relative;
    height: clamp(150px, calc(26 * var(--sh, 1dvh)), 210px);
    margin: -14px -18px 14px;
    overflow: hidden;
    background: var(--n-bg2);
    border-bottom: 1px solid var(--n-line);
}
#modal-buehne[hidden] { display: none; }
#modal-buehne canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
#modal-buehne:not(.zwei) .sb-kegel-ich,
#modal-buehne:not(.zwei) .sb-kegel-er,
#modal-buehne.zwei .sb-kegel-mitte { display: none; }

.modal-box h3 {
    font: 900 17px/1.25 system-ui, sans-serif !important;
    letter-spacing: -.02em;
    margin: 0 0 10px !important;
    /* Zeichen und Text als eine Zeile, mittig - und der Umbruch bleibt
       moeglich: Ueberschriften wie "RIEGEL AUS DER TIEFE DER
       SPORTTASCHE" brauchen zwei Zeilen, und das Zeichen soll dann oben
       neben der ersten stehen statt sie zu sprengen. */
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px;
}
/* Etwas groesser als auf den Knoepfen (19): die Ueberschrift setzt 17 px
   in 900, ein 19-px-Zeichen daneben wirkte zierlich. Die Goldfarbe erbt
   es von der Ueberschrift - genau wozu der Vorrat da ist. */
/* Waehrend der Finger zieht, folgt die Schublade ohne Uebergang - sonst
   liefe sie der Hand um die Dauer der Kurve hinterher und faende sich
   beim Loslassen an einer anderen Stelle als der Finger. Beim Loslassen
   nimmt der Erzeuger die Marke weg, und die normale Kurve traegt die
   Bewegung zu Ende. */
.panels.zieht { transition: none !important; }

/* ZEICHEN MITTEN IM TEXT.

   Aufgabenkoepfe und Gruppenkoepfe sind gewoehnliche Textzeilen - hier
   steht das Zeichen IM Fluss, nicht in einem Gitter. Die Groesse haengt
   deshalb an der Schrift (em) statt an einer festen Zahl: dieselbe
   Regel traegt den 13-px-Aufgabenkopf und den 10-px-Gruppenkopf, ohne
   dass eine zweite Groesse gepflegt werden muesste.

   KEIN eigener Abstand: die Quelltexte haben ihr Leerzeichen hinter dem
   Zeichen ("📋 Tagesplan"), und das bleibt als Textknoten stehen. Ein
   margin obendrauf ergaebe den doppelten Abstand.

   Die -.16em heben das Zeichen auf die Mittellinie der Schrift. Auf der
   Grundlinie sitzend haengt es sichtbar zu tief. */
.txt-ic {
    width: 1.15em; height: 1.15em;
    vertical-align: -.16em;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.1;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.modal-ic {
    width: 22px; height: 22px;
    flex: 0 0 auto;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.1;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Erklaerzeilen: EIN Grauton statt fuenf. Die Inline-Stile der alten
   Seite (#cbd5e1, #94a3b8, #64748b ...) werden hier eingeebnet - sie
   unterschieden Wichtigkeit, wo keine ist. */
.modal-box p {
    /* 12 px auf 1,5 war Kleingedrucktes - in einem Ereignis steht dort
       aber die Entscheidungsgrundlage. 13 px auf 1,55 und die hellere
       Grundfarbe: lesbar, ohne der Ueberschrift Konkurrenz zu machen. */
    font: 400 13px/1.55 system-ui, sans-serif !important;
    color: var(--n-dim) !important;
    max-width: 34ch; margin-left: auto; margin-right: auto;
}

/* ---------- KNOEPFE IM FENSTER ----------
   Eine neutrale Flaeche fuer alle - wie im Knopfgitter der Schublade. */
.modal-box .action-btn,
.modal-box .modal-btn {
    background: var(--n-panel2) !important;
    color: var(--n-fg) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 12px !important;
    font: 800 13.5px system-ui, sans-serif !important;
    padding: 13px 12px !important;
    text-align: center !important;
    transition: transform .13s cubic-bezier(.34,1.6,.5,1), border-color .2s, background .2s;
}
.modal-box .action-btn:hover:not([disabled]),
.modal-box .modal-btn:hover:not([disabled]) {
    background: var(--n-panel) !important;
    border-color: var(--n-stahl) !important;
    transform: translateY(-1px);
}
.modal-box .action-btn:active:not([disabled]),
.modal-box .modal-btn:active:not([disabled]) { transform: scale(.985); }

/* ZWEIZEILIGE KNOEPFE: TITEL OBEN, BEDINGUNG DARUNTER.

   In der Gegnersuche stand die Erklaerung als eigener Absatz UNTER dem
   Knopf. Der Abstand nach unten war dabei groesser als der nach oben,
   und die Zeile las sich als Vorspann des NAECHSTEN Knopfes. Jetzt
   traegt jeder Knopf seine Bezeichnung selbst - dieselbe Bauform wie im
   Knopfgitter der Schublade, wo .t und .s dasselbe tun.

   flex-direction, nicht display: der Knopf IST schon ein Flex-Kasten
   (aus game.html), er stellt hier nur seine Achse um. Ohne diese Regel -
   also im ungebauten Quellstand, der spiel-neu.css nicht laedt - stehen
   Titel und Zeile nebeneinander in einer Zeile. Lesbar, nur schmuckloser;
   die gebaute Seite ist die, die Spieler sehen. */
#match-choice .action-btn.zweizeilig {
    flex-direction: column;
    gap: 3px;
    padding: 12px 14px !important;
    line-height: 1.3;
}
/* Den Abstand trugen bisher die Absaetze dazwischen; ohne sie standen
   die vier Knoepfe gemessen auf Lücke null und lasen sich als ein
   Block mit Trennstrichen. */
#match-choice .zweizeilig + .zweizeilig { margin-top: 9px; }
#match-choice .zweizeilig .t { font: 800 14px system-ui, sans-serif; }
#match-choice .zweizeilig .s {
    font: 400 11px system-ui, sans-serif;
    /* Die Zeile ist der Nebensatz, nicht der Satz. Deckkraft statt einer
       eigenen Farbe: so bleibt sie auf dem hellen Hauptzug-Knopf ebenso
       lesbar wie auf den dunklen darunter, ohne zweiten Farbwert. */
    opacity: .72;
    white-space: normal;
    text-align: center;
}
/* Leer geraeumt (der Spielcode fuellt erst beim Oeffnen) nimmt die
   Zeile keinen Platz - sonst stuende der Titel beim ersten Aufblitzen
   aus der Mitte gerueckt. */
#match-choice .zweizeilig .s:empty { display: none; }

/* DER HAUPTZUG. Genau einer je Fenster: der erste Knopf. Bei den
   Ereignissen ist das die Antwort, die weiterfuehrt ("Antreten"), im
   Duellfenster das Wertungsduell, beim Freund-Zweig "Match erstellen". */
#match-choice .action-btn:first-of-type,
#match-friend .action-btn:first-of-type,
.modal-btn-grid .modal-btn:first-child,
.modal-box > .action-btn:first-of-type {
    background: var(--n-zug) !important;
    border-color: var(--n-zug) !important;
    color: #04171c !important;
    box-shadow: 0 8px 26px -10px rgba(0, 229, 255, .8);
}
#match-choice .action-btn:first-of-type:hover,
#match-friend .action-btn:first-of-type:hover,
.modal-btn-grid .modal-btn:first-child:hover,
.modal-box > .action-btn:first-of-type:hover {
    background: #4de8ff !important;
    border-color: #4de8ff !important;
    transform: translateY(-2px);
}

/* ---------- DIE ANZEIGETAFEL AUF DER TITELKARTE ----------
   Gewaehlt im Layout-Labor (duellfenster.html, Richtung C) fuer die
   Zwischenmomente: zwischen zwei Saetzen bekommt das Ergebnis die Form
   einer Hallentafel - Namen in Versalien, Digitalziffern, Satzlampen.
   Waehrend des Spiels bleibt es beim ruhigen Arenakopf; die Tafel ist
   genau fuer den Augenblick da, in dem ohnehin niemand spielt. */
/* Die Tafel steht an zwei Stellen: zwischen den Saetzen auf der
   Titelkarte und am Ende im Ergebnis. Deshalb haengen die Regeln an der
   Klasse, nicht mehr am Fenster. */
.mk-tafel {
    width: min(300px, 88%); margin: 0 auto;
    padding: 12px 14px 10px; border-radius: var(--r-klein);
    background: linear-gradient(180deg, #0A0E13, #06080B);
    border: 1px solid var(--n-line);
    box-shadow: inset 0 0 26px rgba(0,0,0,.65);
}
.mk-t-namen {
    display: flex; justify-content: space-between; gap: 10px;
    font: 800 9.5px system-ui, sans-serif; letter-spacing: .12em;
    text-transform: uppercase; color: var(--n-dim2);
}
.mk-t-namen span { max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-t-zahlen {
    display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-top: 2px;
}
.mk-t-zahlen b {
    font: 900 30px ui-monospace, Menlo, monospace; color: var(--n-gold);
    font-variant-numeric: tabular-nums; text-shadow: 0 0 18px rgba(255,216,77,.32);
}
.mk-t-zahlen i { font: 800 15px ui-monospace, Menlo, monospace; font-style: normal; color: var(--n-dim2); }
.mk-t-lampen { display: flex; gap: 6px; justify-content: center; margin-top: 8px; min-height: 5px; }
.mk-t-lampen i { width: 22px; height: 5px; border-radius: 2px; background: var(--n-line); }
.mk-t-lampen i.du { background: var(--n-zug); box-shadow: 0 0 10px rgba(0,229,255,.55); }
.mk-t-lampen i.er { background: var(--n-krit); box-shadow: 0 0 10px rgba(255,77,94,.5); }
.mk-t-disziplin {
    text-align: center; margin-top: 7px;
    font: 700 9px system-ui, sans-serif; letter-spacing: .14em;
    text-transform: uppercase; color: var(--n-dim2);
}

/* ---------- DIE GEGNERSUCHE ----------
   Dieselbe Sprache wie der Arenakopf: ein Kreis mit Zeichen, daneben
   Name und Lage. Darunter Karten, die in einer Zeile lesbar machen, was
   sie unterscheiden - Chip rechts sagt Einsatz oder Besetzung. */
/* (Die Zeile "mit wem du antrittst" ist seit v6.80 die Buehne mit den
   Schildern darunter - siehe DIE SUCHE ALS BUEHNE.) */
#match-choice .mm-gruppe {
    font: 800 9px system-ui, sans-serif; letter-spacing: .14em; text-transform: uppercase;
    color: var(--n-dim2); text-align: left; margin: 12px 2px 6px;
}
#match-choice .mm-karte, #match-modi .mm-karte {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 11px 12px; margin-bottom: 8px; text-align: left;
    background: var(--n-panel2) !important; border: 1px solid var(--n-line) !important;
    border-radius: var(--r-klein) !important; color: var(--n-fg) !important;
    box-shadow: none !important; cursor: pointer;
    transition: border-color .18s ease, background .18s ease;
}
#match-choice .mm-zeichen, #match-modi .mm-zeichen {
    width: 34px; height: 34px; border-radius: 50%; flex: none;
    display: grid; place-items: center; font-size: 16px;
    background: var(--n-bg2); border: 1px solid var(--n-line);
}
#match-choice .mm-text, #match-modi .mm-text { display: flex; flex-direction: column; flex: 1; min-width: 0; }
#match-choice .mm-text b, #match-modi .mm-text b { font: 800 13.5px system-ui, sans-serif; color: var(--n-fg); }
#match-choice .mm-text i, #match-modi .mm-text i {
    font: 400 11px/1.35 system-ui, sans-serif; font-style: normal; color: var(--n-dim);
    white-space: normal;
}
#match-choice .mm-chip, #match-modi .mm-chip {
    flex: none; font: 800 10px ui-monospace, Menlo, monospace; color: var(--n-gold);
    background: rgba(255, 216, 77, .10); border: 1px solid rgba(255, 216, 77, .35);
    border-radius: 999px; padding: 4px 9px; white-space: nowrap;
}
/* Gratis, Code, Besetzung: kein Geld, also kein Gold. */
#match-choice .mm-karte:nth-of-type(n+2) .mm-chip,
#match-choice .mm-chip:not(#mm-chip-wertung),
#match-modi .mm-chip:not(.mm-chip-geld) {
    color: var(--n-dim); background: rgba(143, 178, 206, .10); border-color: var(--n-line);
}
@media (hover: hover) and (pointer: fine) {
    #match-choice .mm-karte:hover {
        background: var(--n-panel) !important; border-color: var(--n-stahl) !important;
    }
}

/* ---------- DER ARENAKOPF (v6.81: als Buehne) ----------
   Gewaehlt im Layout-Labor (duellfenster.html, Richtung A): beide
   Spieler stehen waehrend des ganzen Duells oben, einander gegenueber,
   dazwischen der Rundenfortschritt. Seit v6.81 stehen sie dort wirklich:
   dieselbe Buehne wie auf der Gegnersuche (suchBuehneMalen, 'da'), du
   links im cyanen, der Gegner rechts im roten Licht. Darunter die
   Schilder - Strich in der Farbe der Seite, Name, Stand gross - und in
   der Mitte die Runden. */
#match-arena {
    display: grid; grid-template-columns: minmax(0, 1fr);
    padding: 0 0 10px; margin-bottom: 6px;
    border-bottom: 1px solid var(--n-line);
}
#match-arena .ar-buehne {
    position: relative;
    height: clamp(118px, calc(19 * var(--sh, 1dvh)), 168px);
    margin: 0 -18px;
    overflow: hidden;
    background: var(--n-bg2);
    border-top: 1px solid var(--n-line);
    border-bottom: 1px solid var(--n-line);
}
#match-arena .ar-buehne canvas {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    display: block;
}
/* Das rote Licht des Gegners, fest auf seinem Podest. */
.sb-kegel-er {
    left: 51%;
    --sb-licht: linear-gradient(180deg, rgba(255, 77, 94, .30), rgba(255, 77, 94, .06) 85%, transparent);
    --sb-pfuetze: rgba(255, 77, 94, .26);
}
#match-arena .ar-tafel {
    /* minmax(0, 1fr) statt 1fr: sonst waechst die Mitte ueber ihren Anteil
       hinaus und schiebt die Namen in die Ellipse. */
    display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: end; gap: 8px;
    padding: 10px 2px 0;
}
#match-arena .ar-seite { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
#match-arena .ar-seite.rechts { align-items: flex-end; text-align: right; }
#match-arena .ar-seite::before {
    content: '';
    width: 24px; height: 3px; border-radius: 2px;
    margin-bottom: 6px;
    background: var(--n-zug);
    box-shadow: 0 0 10px rgba(0, 229, 255, .45);
}
#match-arena .ar-seite.rechts::before { background: var(--n-krit); box-shadow: 0 0 10px rgba(255, 77, 94, .45); }
#match-arena .ar-text { display: flex; flex-direction: column; min-width: 0; max-width: 100%; }
#match-arena .ar-seite.rechts .ar-text { align-items: flex-end; }
#match-arena .ar-text b {
    font: 800 13px/1.2 system-ui, sans-serif; color: var(--n-fg);
    /* Lange Namen duerfen den Kopf nicht sprengen - er traegt in jeder
       Disziplin dieselbe Hoehe. */
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#match-arena .ar-text i {
    margin-top: 2px;
    font: 800 24px/1.1 ui-monospace, Menlo, monospace; font-style: normal;
    font-variant-numeric: tabular-nums;
    color: var(--n-zug);
}
#match-arena .ar-seite.rechts .ar-text i { color: #ff8a96; }
#match-arena .ar-mitte { min-width: 0; text-align: center; padding-bottom: 5px; }
#match-arena .ar-perlen { display: flex; gap: 5px; justify-content: center; margin-bottom: 4px; min-height: 9px; }
#match-arena .ar-perlen i {
    width: 9px; height: 9px; border-radius: 50%; background: var(--n-line);
    transition: background .25s ease, box-shadow .25s ease;
}
/* Gespielt, laufend, kommend - drei Zustaende, keine Behauptung darueber
   hinaus: wer eine Runde geholt hat, sagt der Punktestand daneben. */
#match-arena .ar-perlen i.durch { background: var(--n-stahl); }
#match-arena .ar-perlen i.jetzt { background: var(--n-zug); box-shadow: 0 0 10px rgba(0,229,255,.55); }
#match-arena .ar-disziplin {
    font: 800 9px system-ui, sans-serif; letter-spacing: .1em; text-transform: uppercase;
    color: var(--n-dim2); white-space: nowrap;
}

/* DIE DISZIPLINEN AUF DER HOHEN TAFEL (v6.81). Das Spielfeld nimmt den
   freien Platz. */
#match-modal .modal-box.sb-gross #match-lauf,
#match-modal .modal-box.sb-gross #match-quiz,
#match-modal .modal-box.sb-gross #match-react,
#match-modal .modal-box.sb-gross #match-rps,
#match-modal .modal-box.sb-gross #match-reihe,
#match-modal .modal-box.sb-gross #match-result {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* DEINE WAHL, SOLANGE DIE RUNDE LAEUFT.

   Gesetzt von 24-match.js, sobald geantwortet ist, und wieder genommen,
   sobald die Aufloesung gruen und rot verteilt. Das ist KEINE Vorauswahl
   (die gibt es hier nicht mehr), sondern die Quittung fuer einen Zug,
   den der Spieler gerade gemacht hat - ohne sie sahen nach dem Tippen
   alle vier Knoepfe gleich blass aus. */
#match-modal .modal-btn-grid .modal-btn.gewaehlt {
    background: rgba(0, 229, 255, .10) !important;
    border-color: var(--n-zug) !important;
    color: var(--n-fg) !important;
    box-shadow: 0 0 0 1px rgba(0, 229, 255, .35) inset;
}

/* GUT UND SCHLECHT IN DEN RUECKMELDUNGSZEILEN.
   Gesetzt von matchTon() in 24-match.js. Vorher stand die Farbe als Hex
   an fuenf Stellen im Spielcode - dieselbe Aussage, fuenf Kopien. */
#match-modal .fb-gut      { color: var(--n-gut) !important; }
#match-modal .fb-schlecht { color: var(--n-krit) !important; }

/* EIN ALS still MARKIERTER KNOPF IST KEIN HAUPTZUG.

   Gesetzt von showModal() (14-ui.js), wenn die Auswahl gleichwertige
   Wege anbietet statt eines weiterfuehrenden Zuges - Hilfe-Fenster,
   Auskuenfte. Ohne diese Regel leuchtete dort der erste Knopf tuerkis
   und las sich wie bereits gewaehlt. */
.modal-btn-grid .modal-btn.still,
.modal-btn-grid .modal-btn.still:first-child {
    background: var(--n-panel2) !important;
    border: 1px solid var(--n-line) !important;
    color: var(--n-fg) !important;
    box-shadow: none !important;
}
@media (hover: hover) and (pointer: fine) {
    .modal-btn-grid .modal-btn.still:hover,
    .modal-btn-grid .modal-btn.still:first-child:hover {
        background: var(--n-panel) !important;
        border-color: var(--n-stahl) !important;
        transform: translateY(-1px);
    }
}

/* IM DUELLFENSTER GIBT ES KEINEN HAUPTZUG.

   Die Regel darueber faerbt den ersten Knopf eines Fensters tuerkis und
   die darunter macht den letzten zum leisen Ausgang. Fuer ein Ereignis
   ist das richtig: dort FUEHRT eine Antwort weiter. Im Duell nicht -
   dort waehlt man.

   Drei Stellen, an denen es falsch aussah:
     - "Gegner suchen": Wertungsduell leuchtete, "nur um die Ehre" stand
       daneben wie die zweite Wahl und der Freund-Zweig wie ein Ausgang.
       Die Farbe hat die Entscheidung vorweggenommen.
     - Quiz und Schere-Hantel-Handtuch: die erste ANTWORT leuchtete, die
       letzte sah aus wie "Abbrechen". Die Farbe hat mitgewaehlt.
     - Ergebnis und Lobby: ein hervorgehobener Knopf wirkt gedrueckt,
       bevor jemand ihn angesehen hat.

   Deshalb sind hier alle Knoepfe gleich. Was der Spieler GEWAEHLT hat,
   markiert danach der Spielcode (Rahmen und Marke) - nicht die
   Grundfarbe. Zustandsfarben, die der Spielcode selbst setzt (der grosse
   Knopf im Reaktions-Duell), bleiben unberuehrt: sie stehen inline und
   werden von diesen Selektoren nicht getroffen. */
/* GLEICH HEISST AUCH GLEICH GROSS.

   Farblich waren die Wahlknoepfe seit v6.19 gleich, in der Hoehe nicht:
   eine kurze Antwort ergab einen flachen Knopf, eine lange einen hohen.
   Nebeneinander liest sich das als Rangfolge - der grosse wirkt wie die
   Hauptantwort. Jetzt haben alle dasselbe Mass, unabhaengig vom Text. */
#match-quiz-options.modal-btn-grid {
    /* Alle Zeilen so hoch wie die hoechste: eine lange Antwort zieht die
       kurzen mit, statt neben ihnen aufzuragen. */
    grid-auto-rows: 1fr;
}
#match-quiz-options.modal-btn-grid .modal-btn {
    min-height: 52px !important;
    display: flex !important; align-items: center; justify-content: center;
}
#match-rps-options.modal-btn-grid .modal-btn { min-height: 78px !important; }

#match-modal #match-choice .action-btn:first-of-type,
#match-modal #match-friend .action-btn:first-of-type,
#match-modal .modal-box > .action-btn:first-of-type,
#match-modal .modal-btn-grid .modal-btn,
#match-modal .modal-btn-grid .modal-btn:first-child {
    background: var(--n-panel2) !important;
    border: 1px solid var(--n-line) !important;
    color: var(--n-fg) !important;
    box-shadow: none !important;
}

/* DER AUSGANG IST KEINE WAHL.

   "Zurueck ins Gym" stand nach v6.19 mit derselben Flaeche da wie die
   Spielarten darueber - vier gleich aussehende Kaesten, von denen einer
   das Fenster schliesst. Gleich heisst hier: keiner ist VORGEWAEHLT.
   Der Ausgang ist deshalb wieder leise, aber er leuchtet auch nicht:
   keine Flaeche, gedaempfte Schrift. */
/* ABER NICHT IN DEN WAHLRASTERN. Die letzte Antwort einer Frage und das
   dritte Symbol bei Schere-Hantel-Handtuch sind keine Ausgaenge - sie
   standen dadurch ohne Flaeche da, waehrend die beiden davor Kaesten
   waren. Drei Wahlmoeglichkeiten, zwei Erscheinungsbilder. */
#match-modal .modal-btn-grid:not(#match-quiz-options):not(#match-rps-options) .modal-btn:last-child:not(:first-child):not(.gym) {
    background: none !important;
    border-color: transparent !important;
    color: var(--n-dim2) !important;
    box-shadow: none !important;
}
#match-modal .modal-btn-grid:not(#match-quiz-options):not(#match-rps-options) .modal-btn:last-child:not(:first-child):not(.gym):hover {
    background: none !important;
    border-color: transparent !important;
    color: var(--n-fg) !important;
}
/* KEIN HOVER OHNE ZEIGER.

   Gemeldet: "beim Quiz ist immer der zuletzt geklickte Knopf in der
   naechsten Runde vorausgewaehlt". Es war der Hover-Zustand: der
   Finger (oder der Mauszeiger) bleibt liegen, wo eben gedrueckt wurde,
   und der frisch aufgebaute Knopf an derselben Stelle leuchtet sofort
   auf - im Bild nicht von einer Vorauswahl zu unterscheiden.

   Zwei Riegel dagegen. Erstens: auf Geraeten OHNE echten Zeiger gibt es
   den Zustand gar nicht mehr. Auf dem Telefon bleibt :hover nach einem
   Tipp sonst kleben, bis irgendwo anders hingetippt wird. */
@media (hover: hover) and (pointer: fine) {
    #match-modal #match-choice .action-btn:first-of-type:hover,
    #match-modal #match-friend .action-btn:first-of-type:hover,
    #match-modal .modal-box > .action-btn:first-of-type:hover,
    #match-modal .modal-btn-grid .modal-btn:hover:not([disabled]),
    #match-modal .modal-btn-grid .modal-btn:first-child:hover,
    #match-modal .modal-btn-grid .modal-btn:last-child:not(:first-child):hover {
        background: var(--n-panel) !important;
        border-color: var(--n-stahl) !important;
        color: var(--n-fg) !important;
        transform: translateY(-1px);
    }
}

/* Zweitens, fuer die Maus: frisch aufgebaute Wahlknoepfe bleiben still,
   bis der Zeiger sich bewegt. wahlOhneVorwahl() in 24-match.js setzt die
   Klasse beim Neuaufbau und nimmt sie beim ersten pointermove wieder
   weg - danach verhaelt sich alles wie gewohnt. */
#match-modal .modal-btn-grid.zeiger-ruht .modal-btn:hover:not([disabled]),
#match-modal .modal-btn-grid.zeiger-ruht .modal-btn:first-child:hover,
#match-modal .modal-btn-grid.zeiger-ruht .modal-btn:last-child:not(:first-child):hover {
    background: var(--n-panel2) !important;
    border-color: var(--n-line) !important;
    color: var(--n-fg) !important;
    /* filter und transform muessen mit: die allgemeine button:hover-Regel
       in game.html hellt sonst trotzdem auf und hebt den Knopf an. */
    filter: none;
    transform: none;
}

/* DER GROSSE KNOPF IM REAKTIONS-DUELL TRAEGT DAS SIGNAL.

   Seine Farbe ist die Ansage: dunkel heisst warten, hell heisst
   druecken. Ein Aufhellen beim Zeigen sieht aus wie der Beginn des
   Signals - und wer darauf drueckt, hat Fehlstart. Also kein Hover. */
#match-react-btn:hover:not(:disabled) { filter: none; transform: none; }

/* Der letzte Knopf eines Fensters ist meist ein Ausgang ("Abbrechen",
   "Spaeter") - leise und ohne Flaeche. AUSGENOMMEN .gym: "Zurueck ins
   Gym" sah dadurch je nach Fenster anders aus - im Studio steht er
   allein im Raster und ist damit :first-child, also gefuellt; im
   Duell- und im Hilfefenster stand etwas davor, und derselbe Knopf
   wurde blass. Wer seine Rolle als Klasse traegt, behaelt sein
   Aussehen, egal an welcher Stelle er landet. */
.modal-btn-grid .modal-btn:last-child:not(:first-child):not(.gym) {
    background: none !important;
    border-color: transparent !important;
    color: var(--n-dim2) !important;
}
.modal-btn-grid .modal-btn:last-child:not(:first-child):not(.gym):hover {
    color: var(--n-fg) !important;
    background: none !important;
    border-color: transparent !important;
}

/* AUSNAHME: "LINK KOPIEREN" IST KEIN AUSGANG.

   Im Einladen-Fenster steht an zweiter Stelle kein "Spaeter", sondern
   der zweite Weg zum selben Ziel: wer nicht ueber die Teilen-Auswahl
   des Geraets geht, kopiert den Link von Hand. Als Ausgang gezeichnet
   sah er aus wie blosser Text und war auf dem dunklen Fenster kaum zu
   finden. Die Regel darueber ist spezifischer als .still (fuenf
   Klassen gegen drei) und hat .still deshalb ueberstimmt - die
   Kennung des Fensters dreht das um. */
/* DIE KAUF-RUECKFRAGE LIEGT OBEN (v7.03). Sie geht auch aus der Galerie
   auf (vorschauAnziehen -> studioKaufen); beide Fenster haben die Ebene
   100 aus spiel-basis.html, und die Galerie steht im Markup spaeter - sie
   lag ueber der Frage, bestaetigen ging nicht (gemeldet bei "Aura
   Glitzern"). Test: tools/kauf-ueber-galerie.test.js. */
#kauf-modal { z-index: 120; }

/* Dasselbe im Schaufenster: "Vorheriges" und "Nächstes" sind ein
   PAAR und muessen gleich aussehen. Ohne die Ausnahme traegt das eine
   den Rahmen und das andere nicht - der zweite Knopf einer Zeile gilt
   sonst als Ausgang. */
#vorschau-modal .modal-btn-grid .modal-btn.still,
#invite-modal .modal-btn-grid .modal-btn.still {
    background: var(--n-panel2) !important;
    border: 1px solid var(--n-line) !important;
    color: var(--n-fg) !important;
}
@media (hover: hover) and (pointer: fine) {
    #vorschau-modal .modal-btn-grid .modal-btn.still:hover,
    #invite-modal .modal-btn-grid .modal-btn.still:hover {
        background: var(--n-panel) !important;
        border-color: var(--n-stahl) !important;
        color: var(--n-fg) !important;
    }
}

/* EIN NEUER STAND LEUCHTET KURZ AUF.
   Gesetzt von matchStandSetzen() in 24-match.js, nur bei einer echten
   Aenderung. Kurz und einmalig - eine Dauerbewegung waere Zappeln. */
#match-modal .stand-neu { animation: stand-neu .55s ease-out; }
@keyframes stand-neu {
    0%   { color: var(--n-zug); text-shadow: 0 0 14px rgba(0, 229, 255, .55); }
    100% { color: inherit;      text-shadow: none; }
}
@media (prefers-reduced-motion: reduce) {
    #match-modal .stand-neu { animation: none; }
}

/* ---------- DER EINLAUF ----------
   Die Vorstellung der beiden Athleten bleibt, wie sie ist - sie ist das
   Beste, was das Fenster hat. Darunter steht jetzt, was gleich gespielt
   wird, und ein Balken zeigt, wie lange es noch dauert. */
#match-einlauf #einlauf-canvas {
    width: 100%; max-width: 300px; margin: 0 auto; display: block;
    border-radius: var(--r-klein); background: var(--n-bg);
    border: 1px solid var(--n-line);
}
#match-einlauf .ein-fuss { margin-top: 10px; }
#match-einlauf .ein-disziplin {
    font: 800 12px system-ui, sans-serif; letter-spacing: .1em; text-transform: uppercase;
    color: var(--n-gold);
}
#match-einlauf .ein-rohr {
    width: min(240px, 78%); height: 4px; margin: 8px auto 0;
    border-radius: 999px; background: rgba(143, 178, 206, .16); overflow: hidden;
}
#match-einlauf .ein-rohr i {
    display: block; height: 100%; width: 0;
    background: linear-gradient(90deg, var(--n-zug), var(--n-gold));
    transition: width .3s linear;
}
#match-einlauf #einlauf-countdown {
    font: 700 12px ui-monospace, Menlo, monospace; color: var(--n-dim2);
    margin: 7px 0 0; font-variant-numeric: tabular-nums;
}

/* ---------- DIE SUCHE ALS BUEHNE (v6.80) ----------
   "Die Spielersuche groesser, moderner und professioneller." Das Fenster
   wird waehrend Suche und Einlauf zur fast bildschirmhohen Tafel
   (sb-gross, gesetzt in showMatchView). Held ist die Buehne: randlos
   ueber die Innenabstaende des Fensters, sie nimmt allen freien Platz.
   Links du im kalten Licht, rechts ein Podest; ein goldener Scheinwerfer
   sucht, und wenn jemand kommt, bleibt er rot auf dessen Podest stehen.
   Die Figuren malt suchBuehneMalen (33-buehne.js), das Licht steht hier.
   Alles andere bleibt ruhig: Schilder, Status, ein Knopf. */
#match-modal:has(.sb-gross) { padding: 10px !important; }
#match-modal .modal-box.sb-gross {
    max-width: 460px !important;
    min-height: min(760px, calc(100 * var(--sh, 1dvh) - 20px));
    max-height: calc(100 * var(--sh, 1dvh) - 20px);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}
#match-modal .modal-box.sb-gross #match-menu,
#match-modal .modal-box.sb-gross #match-lobby,
#match-modal .modal-box.sb-gross #match-einlauf {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
}
#match-lobby .sb-anlass {
    margin: 0 auto 12px !important;
    max-width: 36ch !important;
    font: 600 13px/1.45 system-ui, sans-serif !important;
    color: var(--n-dim) !important;
    text-align: center;
}
#match-modal .sb-buehne {
    position: relative;
    flex: 1 1 260px;
    min-height: 240px;
    margin: 0 -18px;
    overflow: hidden;
    background: var(--n-bg2);
    border-top: 1px solid var(--n-line);
    border-bottom: 1px solid var(--n-line);
}
#match-modal .sb-buehne canvas {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    display: block;
}
/* Ein Scheinwerferkegel: Trapez aus einem Punkt oben, weich gezeichnet.
   Die Weichheit sitzt am aeusseren Element (filter), das Trapez am
   inneren - sonst schnitte der Clip die Unschaerfe wieder scharf. */
.sb-kegel {
    position: absolute;
    top: -6%;
    width: 44%;
    height: 98%;
    transform-origin: 50% 0;
    pointer-events: none;
    filter: blur(6px);
    mix-blend-mode: screen;
}
.sb-kegel::before {
    content: '';
    position: absolute; inset: 0;
    clip-path: polygon(46% 0, 54% 0, 100% 100%, 0 100%);
    background: var(--sb-licht);
}
/* Die Lichtpfuetze am Fuss des Kegels. */
.sb-kegel::after {
    content: '';
    position: absolute;
    left: 6%; right: 6%; bottom: -4%;
    height: 14%;
    border-radius: 50%;
    background: radial-gradient(closest-side, var(--sb-pfuetze), transparent);
}
.sb-kegel-ich {
    left: 5%;
    --sb-licht: linear-gradient(180deg, rgba(0, 229, 255, .26), rgba(0, 229, 255, .05) 85%, transparent);
    --sb-pfuetze: rgba(0, 229, 255, .22);
}
.sb-kegel-such {
    left: 51%;
    --sb-licht: linear-gradient(180deg, rgba(255, 216, 77, .34), rgba(255, 216, 77, .06) 85%, transparent);
    --sb-pfuetze: rgba(255, 216, 77, .26);
    animation: sb-suchen 2.6s ease-in-out infinite alternate;
}
@keyframes sb-suchen {
    from { transform: rotate(24deg); }
    to   { transform: rotate(-30deg); }
}
/* Gefunden: der Kegel bleibt auf dem Podest stehen und wird rot - die
   Farbe, die der Gegner im Duell traegt (Arenakopf, Lampen der Tafel). */
.sb-buehne.gefunden .sb-kegel-such {
    animation: none;
    transform: rotate(0deg);
    transition: transform .6s var(--n-feder);
    --sb-licht: linear-gradient(180deg, rgba(255, 77, 94, .34), rgba(255, 77, 94, .07) 85%, transparent);
    --sb-pfuetze: rgba(255, 77, 94, .28);
}

/* Die Schilder unter den Podesten: Name gross, darunter Masse und Rang.
   Der Strich darueber traegt die Seite - Cyan du, Gold gesucht, Rot der
   Gegner, dieselbe Zuordnung wie im Duell. */
#match-modal .lb-gegen {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: start;
    gap: 8px;
    margin: 14px 0 0;
}
#match-modal .lb-platz {
    display: flex; flex-direction: column; align-items: center;
    gap: 3px; min-width: 0; padding: 0 2px;
    text-align: center;
}
#match-modal .lb-platz::before {
    content: '';
    width: 26px; height: 3px; border-radius: 2px;
    margin-bottom: 5px;
    background: var(--n-zug);
    box-shadow: 0 0 10px rgba(0, 229, 255, .45);
}
#match-modal .lb-platz.er::before {
    background: var(--n-gold);
    box-shadow: 0 0 10px rgba(255, 216, 77, .35);
}
#match-modal .lb-platz.er.da::before {
    background: var(--n-krit);
    box-shadow: 0 0 10px rgba(255, 77, 94, .45);
}
#match-modal .lb-platz b {
    font: 800 16px/1.2 system-ui, sans-serif;
    letter-spacing: -.01em;
    color: var(--n-fg);
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#match-modal .lb-platz.er:not(.da) b { color: var(--n-dim); }
#match-modal .lb-platz i {
    font: 500 12px/1.3 system-ui, sans-serif; font-style: normal;
    color: var(--n-dim2);
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#match-modal .lb-platz.bereit i { color: var(--n-gut); }
#match-modal .lb-vs {
    align-self: center;
    margin-top: 8px;
    font: 900 12px system-ui, sans-serif;
    letter-spacing: .08em;
    color: var(--n-dim2);
}
#match-lobby #match-ready-btn { width: 100%; margin-top: 12px; }
/* Der Knopf unten am Fenster: dorthin reicht der Daumen, und die Tafel
   darueber bleibt frei. */
#match-lobby .sb-fuss { margin-top: auto; padding-top: 16px; }

/* DAS MENUE AUF DERSELBEN BUEHNE: flacher, ohne Suchlicht. Die Karten
   darunter sind der eigentliche Inhalt; die Buehne sagt nur, wohin es
   geht. Auf niedrigen Bildschirmen (unter 640) faellt sie weg. */
#match-modal .sb-buehne.mm-buehne { flex: 0 0 auto; height: clamp(150px, calc(26 * var(--sh, 1dvh)), 220px); min-height: 0; margin-bottom: 0; }
#match-menu .mm-gegen { margin: 12px 0 10px; }
#match-modal .modal-box.sb-gross #match-menu > .modal-btn-grid { margin-top: auto !important; padding-top: 14px; }
@media (max-height: 640px) {
    #match-modal .sb-buehne.mm-buehne { display: none; }
}
#match-lobby .sb-fuss .modal-btn { width: 100%; }
/* Der Einlauf danach steht in derselben Tafel: randlos, so breit wie die
   Buehne der Suche, direkt unter dem Kopf - der freie Platz bleibt unten. */
#match-modal .modal-box.sb-gross #match-einlauf { justify-content: flex-start; }
#match-modal .modal-box.sb-gross #einlauf-canvas {
    max-width: none;
    width: calc(100% + 36px);
    margin: 0 -18px;
    aspect-ratio: 5 / 4;
    height: auto;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
}
#match-modal .modal-box.sb-gross #match-einlauf .ein-fuss { margin-top: 16px; }

/* Der Code ist zum Vorlesen und Abtippen da - Ziffernschrift, weite
   Sperrung, eigene Flaeche, damit er nicht wie eine Ueberschrift wirkt. */
#match-code-display {
    font: 800 30px ui-monospace, Menlo, monospace; letter-spacing: 7px;
    color: var(--n-gold); margin: 6px auto 4px; padding: 10px 8px 10px 15px;
    background: var(--n-bg2); border: 1px solid var(--n-line); border-radius: var(--r-klein);
    width: min(260px, 90%);
}
#match-code-display:empty { display: none; }

/* ---------- DER STAND DER SUCHE ----------
   Gebaut in matchSucheZeigen() (24-match.js): was gesucht wird (die
   Gewichtsklasse mit Zahlen), wie lange schon (Uhr), und ein Balken bis
   zur Aufzeichnung. Die laufenden Punkte sind weg - bewegen tut sich
   der Scheinwerfer. */
#match-players { margin: 16px 0 0; font: 400 13px/1.45 system-ui, sans-serif; color: var(--n-dim); text-align: center; }
#match-players .suche { display: grid; gap: 8px; text-align: left; }
#match-players .suche-kopf {
    display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
}
#match-players .suche-text { font: 700 14px/1.35 system-ui, sans-serif; color: var(--n-fg); }
#match-players .suche-uhr {
    flex: none;
    font: 800 15px ui-monospace, Menlo, monospace;
    font-variant-numeric: tabular-nums;
    color: var(--n-gold);
}
#match-players .suche-rohr {
    height: 6px; border-radius: 999px;
    background: rgba(143, 178, 206, .14);
    overflow: hidden;
}
#match-players .suche-rohr i {
    display: block; height: 100%; width: 0;
    background: linear-gradient(90deg, rgba(255, 216, 77, .55), var(--n-gold));
    /* Der Balken wird alle 250 ms nachgesetzt - die Ueberblendung macht
       daraus eine Bewegung statt einer Folge von Spruengen. */
    transition: width .3s linear;
}
#match-players .suche-fuss { font: 400 12px/1.45 system-ui, sans-serif; color: var(--n-dim2); }

/* Wer Bewegung abbestellt hat, bekommt den Stand ohne Zappeln: der
   Kegel steht still auf dem Podest. */
@media (prefers-reduced-motion: reduce) {
    .sb-kegel-such { animation: none; transform: rotate(-6deg); }
    .sb-buehne.gefunden .sb-kegel-such { transition: none; }
    #match-players .suche-rohr i { transition: none; }
}

/* Das Code-Feld im Freund-Zweig: dieselbe Sprache wie die Knoepfe. */
#match-code-input {
    background: var(--n-bg2) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 12px !important;
    color: var(--n-fg) !important;
    font: 800 18px ui-monospace, Menlo, monospace !important;
}
#match-code-input:focus {
    border-color: var(--n-zug) !important;
    outline: none;
}


/* ---------------------------------------------------------
   DIE HINWEIS-SHEETS (Installation, Ansage)

   Sie fahren von unten ein - das passt zum neuen Layout, dort kommt die
   Schublade genauso. Ihre Farben kamen aber noch aus dem alten Schema:
   gelber 2-px-Rand um einen blaugrauen Kasten, blauer Knopf (#2563eb),
   und die Schrittnummern in Gold auf Schiefer.

   Gleiche Sprache wie die Fenster: ruhige Flaeche, EIN Akzent auf dem
   Knopf, der weiterfuehrt. Der gelbe Rahmen faellt weg - er rief nach
   Aufmerksamkeit, die ein Hinweis nicht braucht, der ohnehin von unten
   hereinfaehrt.
   --------------------------------------------------------- */
.install-card {
    background: linear-gradient(180deg, #171e26, var(--n-bg2)) !important;
    border: 1px solid var(--n-line) !important;
    border-radius: 20px !important;
    padding: 18px 18px 16px !important;
    box-shadow: 0 -18px 44px -18px #000 !important;
}
.install-title {
    color: var(--n-fg) !important;
    font: 900 14.5px system-ui, sans-serif !important;
    letter-spacing: -.01em;
}
.install-sub,
.install-step { color: var(--n-dim2) !important; }
.install-step b { color: var(--n-fg) !important; }
.install-num {
    background: var(--n-panel2) !important;
    color: var(--n-zug) !important;
    box-shadow: inset 0 0 0 1px var(--n-line);
}
.install-close { color: var(--n-dim2) !important; }
.install-close:hover { color: var(--n-fg) !important; }

/* Der Knopf, der weiterfuehrt - derselbe Hauptzug wie in den Fenstern. */
.install-primary {
    background: var(--n-zug) !important;
    color: #04171c !important;
    border: 0 !important;
    border-radius: 12px !important;
    font: 800 13.5px system-ui, sans-serif !important;
    box-shadow: 0 8px 26px -10px rgba(0, 229, 255, .8) !important;
}
.install-primary:hover { background: #4de8ff !important; }

/* =========================================================
   DIE DREI AKTE DES WETTKAMPFTAGS (42-akte.js)

   Eigenes Overlay, weil hier gewischt und gehalten wird: die Leinwand
   braucht die ganze Aufmerksamkeit, und Zeigerereignisse duerfen nicht
   an einer Knopfliste haengenbleiben. Aufgebaut wie die uebrigen
   Fenster des neuen Layouts - Verlaufslinie oben, gehobener Grund.
   ========================================================= */
#akt-overlay .akt-box {
    /* GROESSER, UND DIE HOEHE ZAEHLT MIT. Mit 360 px stand der Athlet als
       Briefmarke in einem halbleeren Fenster. Seit die Leinwand hochkant
       rechnet (300x380), bekommt die Figur die Hoehe, die ein Telefon
       ohnehin hat; das Fenster darf dafuer bis fast an den Rand. */
    width: min(98vw, 470px);
    max-height: calc(94 * var(--sh, 1vh));
    background: linear-gradient(180deg, var(--n-panel2), var(--n-panel) 55%);
    border: 1px solid var(--n-line);
    border-radius: 18px;
    padding: 12px 10px 12px;
    position: relative; overflow: hidden;
    display: flex; flex-direction: column; align-items: center; gap: 8px;
}
#akt-overlay .akt-box::before {
    content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
    background: linear-gradient(90deg, var(--n-stahl), var(--n-zug), var(--n-gold));
}
#akt-overlay .akt-kopf {
    display: flex; align-items: center; gap: 9px; align-self: flex-start;
}
#akt-overlay .akt-kopf span {
    width: 20px; height: 20px; border-radius: 50%;
    display: grid; place-items: center;
    background: rgba(0,229,255,.14); border: 1px solid rgba(0,229,255,.5);
    color: var(--n-zug); font: 800 11px system-ui, sans-serif;
}
#akt-overlay .akt-kopf b { font: 800 14px system-ui, sans-serif; color: var(--n-fg); }

#akt-canvas {
    /* Die Hoehe ist gedeckelt, damit auf kleinen Geraeten Tafel und
       Knopf nicht aus dem Bild rutschen - die Breite folgt dann. */
    width: 100%; height: auto; max-height: calc(62 * var(--sh, 1vh)); object-fit: contain;
    display: block;
    border-radius: 12px; background: #080B0E;
    touch-action: none;              /* sonst scrollt das Wischen die Seite */
    cursor: pointer;
}
/* LANGES DRUECKEN DARF NICHTS MARKIEREN.

   Gemeldet vom iPhone: beim Halten der Pose sprang die Textauswahl an
   und legte den blauen Auswahlrahmen ueber die Leinwand, teils mit
   Kopieren-Menue. Das ist die eingebaute Geste von iOS Safari - sie
   wird an dieser Stelle abgeschaltet, und zwar am ganzen Fenster: die
   Auswahl faengt sonst am Rand daneben an und zieht sich darueber. */
#akt-overlay, #akt-overlay * {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}
#akt-overlay canvas { -webkit-tap-highlight-color: transparent; }
/* Solange ein Akt laeuft, halten sich die Einblendungen von unten
   zurueck - sie lagen sonst ueber der halben Figur und fingen die
   Griffe ab. */
html.akt-laeuft #install-sheet,
html.akt-laeuft #ansage-sheet { display: none !important; }
/* Die Wetter- und Weltbanner ebenfalls: sie schienen durch den
   78-Prozent-Grund der Szene hindurch, und "Zivilfahnder gesichtet"
   ueber der Jury liest sich wie ein Ereignis, das gerade eintritt. */
html.akt-laeuft .weather-banner,
html.akt-laeuft #world-banner { visibility: hidden !important; }
/* Die beiden Buehnenfenster stehen auf eigenem Grund. Die Buehne ist
   ein anderer Ort als das Studio - was dort gerade an der Wand haengt,
   hat hinter dem Athleten nichts zu suchen. */
#akt-overlay, #urteil-overlay { background: #080B0E !important; backdrop-filter: none !important; }

/* UND NICHTS LAESST SICH MARKIEREN, SOLANGE EIN AKT LAEUFT.

   Beim Wischen zieht der Finger ueber die Leinwand hinaus; die Auswahl
   beginnt dann NEBEN dem Fenster und legt ihren blauen Schleier ueber
   alles, was sie unterwegs erwischt - gemeldet beim Uebergang vom
   Oelen ins Posen ("der Avatar ist selected"). Am Fenster allein war
   das nicht zu verhindern: die Auswahl gehoert dem Dokument. Deshalb
   fuer die Dauer eines Akts ueberall aus, danach wieder wie vorher. */
html.akt-laeuft, html.akt-laeuft * {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}
html.akt-laeuft ::selection { background: transparent; }
/* Im Duellfenster laeuft das Ruhefenster ebenfalls (24-match.js) - der
   Freundes-Code muss dort trotzdem markierbar und einfuegbar bleiben. */
html.akt-laeuft #match-modal input,
html.akt-laeuft #match-modal textarea { user-select: text; -webkit-user-select: text; }
html.akt-laeuft #match-modal input::selection { background: rgba(0,229,255,.35); }
#akt-canvas { -webkit-user-drag: none; user-drag: none; }
#akt-overlay .akt-lage {
    margin: 0; min-height: 34px; text-align: center;
    font: 400 12.5px/1.45 system-ui, sans-serif; color: var(--n-dim);
}
#akt-overlay .akt-lage b { color: var(--n-fg); }
#akt-overlay .akt-lage b.gut { color: var(--n-gut); }
#akt-overlay .akt-lage b.schlecht { color: var(--n-krit); }
#akt-overlay .akt-lage .spruch { display: block; margin-top: 4px; color: var(--n-stahl); font-style: italic; }

#akt-overlay .akt-oel { display: flex; align-items: center; gap: 10px; width: 100%; }
#akt-overlay .akt-oel span {
    font: 700 10.5px system-ui, sans-serif; color: var(--n-dim2);
    letter-spacing: .1em; text-transform: uppercase;
}
#akt-overlay .akt-oel .rohr {
    flex: 1 1 auto; height: 9px; border-radius: 999px;
    background: var(--n-bg2); border: 1px solid var(--n-line); overflow: hidden;
}
#akt-overlay .akt-oel .rohr i {
    display: block; height: 100%; width: 100%;
    background: linear-gradient(90deg, #C98D6E, var(--n-gold));
}

/* DIE PUBLIKUMSGUNST IM SHOWDOWN: ein Tauziehen. Dein Anteil kommt
   tuerkis von links, der Rest ist sein Rot. */
/* =========================================================
   DIE TITELKARTE ZWISCHEN DEN SPIELEN (24-match.js)

   Ein Zwischenbildschirm wie im Actionspiel: das Feld dahinter tritt
   zurueck, die Karte traegt Ergebnis, naechste Disziplin und ihre Regel.
   Der Balken zeigt, wie lange es noch dauert - eine Zahl kommt erst in
   den letzten Sekunden, als Startzaehler.
   ========================================================= */
/* WAS FREIGESCHALTET WURDE, IST DIE NACHRICHT.

   In den Fenstern "Erfolg freigeschaltet", "Neues Stueck erspielt" und
   "Neue Liga offen" stand der Name als erste Zeile im Fliesstext - in
   13 Pixeln, grau, zwischen Ueberschrift und Erklaerung. Der Anlass
   stand also gross da ("ERFOLG FREIGESCHALTET") und der Erfolg selbst
   klein darunter. Jetzt traegt er eine goldene Zeile fuer sich. */
/* EINE PILLE, KEINE ZWEITE UEBERSCHRIFT.

   Erster Anlauf: goldene Schrift, gross, ohne Flaeche. Darueber steht
   aber die Ueberschrift des Fensters - ebenfalls gold und fast gleich
   gross. Zwei goldene Zeilen uebereinander verschwimmen, und der Erfolg
   war schwerer zu finden als vorher. Jetzt traegt er eine eigene
   Flaeche: Rahmen, getoenter Grund, hellere Schrift. Der Anlass steht
   in Gold darueber, das Erspielte liegt als Marke darunter. */
#modal-held {
    display: block; width: fit-content; max-width: 100%;
    margin: 6px auto 12px; padding: 7px 17px;
    font: 800 16.5px system-ui, sans-serif; color: #FFEDB0;
    line-height: 1.2; text-align: center;
    background: rgba(255, 216, 77, .13);
    border: 1px solid rgba(255, 216, 77, .55);
    border-radius: 999px;
    box-shadow: 0 0 34px -10px rgba(255, 216, 77, .75);
    animation: modal-held-an .4s cubic-bezier(.34, 1.6, .5, 1) both;
}
#modal-held[hidden] { display: none !important; }
@keyframes modal-held-an {
    0%   { transform: scale(.86); opacity: 0; }
    100% { transform: none; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    #modal-held { animation: none; }
}

#match-modal .modal-box { position: relative; }
#match-karte {
    /* VOLL DECKEND, nicht fast. Mit einem Rest Transparenz schien die
       Meldung des letzten Spiels durch die Regelzeilen - zwei Texte
       uebereinander, keiner davon lesbar. Ein
       Zwischenbildschirm ist ein Bild, kein Schleier. */
    position: absolute; inset: 0; z-index: 6; border-radius: 16px;
    background: var(--n-bg);
    display: flex; flex-direction: column; align-items: center;
    /* safe center: bei viel Inhalt - die Regel von "Drei gewinnt" braucht
       drei volle Zeilen - wird oben nicht abgeschnitten. Mit blossem
       center ragte die Urteilspille aus dem Kartenrand heraus. */
    justify-content: safe center;
    overflow-y: auto;
    gap: 6px; padding: 15px 16px; text-align: center;
    opacity: 0; pointer-events: none; transition: opacity .28s ease;
}
#match-karte.an { opacity: 1; pointer-events: auto; }
/* Die Buehne der Titelkarte (v6.81): oben randlos, der Rest der Karte
   steht mittig im freien Platz darunter. */
#match-karte .mk-buehne {
    position: relative; flex: none;
    width: calc(100% + 32px); margin: -15px -16px 8px;
    height: clamp(150px, calc(28 * var(--sh, 1dvh)), 240px);
    overflow: hidden;
    background: var(--n-bg2);
    border-bottom: 1px solid var(--n-line);
    border-radius: 16px 16px 0 0;
}
#match-karte .mk-buehne canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* Seit v7.39 steht der Inhalt direkt unter der Buehne - vorher hielten
   margin auto oben und unten ihn in der Mitte des freien Platzes, und
   zwischen Buehne und Ergebnis klaffte eine Luecke ("reingeklatscht"). */
#match-karte:has(.mk-buehne) { justify-content: flex-start; gap: 10px; }
#match-karte[hidden] { display: none !important; }
#match-karte .mk-oben { display: flex; flex-direction: column; align-items: center; gap: 7px; width: 100%; }
#match-karte .mk-oben[hidden] { display: none !important; }
/* DAS URTEIL IST DIE AUSSAGE DER KARTE - also steht es auch so da.

   Als 11-Pixel-Zeile ueber der Zahl las es sich wie eine Bildunterschrift;
   wer den Satz geholt hatte, erfuhr man eher aus der Farbe als aus dem
   Wort. Jetzt eine Pille in der Farbe des Ausgangs, doppelt so gross,
   und sie kommt mit einem kurzen Stoss ins Bild. */
#match-karte .mk-urteil, #match-result .mk-urteil {
    font: 800 17px system-ui, sans-serif; letter-spacing: .04em; text-transform: uppercase;
    color: var(--n-dim); padding: 7px 16px; border-radius: 999px;
    background: rgba(143, 178, 206, .10); border: 1px solid var(--n-line);
    animation: mk-urteil-an .42s cubic-bezier(.34, 1.6, .5, 1) both;
}
#match-karte .mk-urteil:empty, #match-result .mk-urteil:empty { display: none; }
#match-karte .mk-urteil.gut, #match-result .mk-urteil.gut {
    color: var(--n-gut);
    background: rgba(53, 208, 127, .14); border-color: rgba(53, 208, 127, .45);
    box-shadow: 0 0 26px -6px rgba(53, 208, 127, .55);
}
#match-karte .mk-urteil.schlecht, #match-result .mk-urteil.schlecht {
    color: var(--n-krit);
    background: rgba(255, 77, 94, .13); border-color: rgba(255, 77, 94, .45);
    box-shadow: 0 0 26px -6px rgba(255, 77, 94, .5);
}
@keyframes mk-urteil-an {
    0%   { transform: scale(.82); opacity: 0; }
    100% { transform: none; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    #match-karte .mk-urteil { animation: none; }
}
#match-karte .mk-stand {
    font: 800 30px ui-monospace, Menlo, monospace; color: var(--n-fg);
    font-variant-numeric: tabular-nums; line-height: 1;
}
#match-karte .mk-stand small {
    display: block; margin-top: 5px; font: 700 10px system-ui, sans-serif;
    color: var(--n-dim2); letter-spacing: .14em; text-transform: uppercase;
}
/* Der Serienstand steht UNTER dem Spielstand, nicht an seiner Stelle.
   Vorher zeigte die Karte entweder das eine oder das andere - wer den
   Satz geholt hatte, las man, wie hoch aber nicht. */
#match-karte .mk-serie {
    font: 700 11px system-ui, sans-serif; color: var(--n-dim2);
    letter-spacing: .1em; text-transform: uppercase;
}
#match-karte .mk-serie:empty { display: none; }
#match-karte .mk-trenner { width: 54%; height: 1px; background: var(--n-line); margin: 3px 0 1px; }
/* DER KASTEN "ALS NAECHSTES" (v7.39): Kopf mit Symbol und Namen, die
   Regel als Liste mit Punkten, unten Startzeile und Balken. */
#match-karte .mk-naechstes {
    width: 100%; max-width: 360px; box-sizing: border-box; text-align: left;
    display: flex; flex-direction: column; gap: 8px;
    padding: 12px 14px 14px; border-radius: 14px;
    background: var(--n-bg2); border: 1px solid var(--n-line);
}
#match-karte .mk-naechstes[hidden] { display: none !important; }
#match-karte .mk-label {
    font: 700 10px system-ui, sans-serif; color: var(--n-dim2);
    letter-spacing: .16em; text-transform: uppercase;
}
#match-karte .mk-kopf { display: flex; align-items: center; gap: 10px; }
#match-karte .mk-symbol {
    flex: none; width: 40px; height: 40px; border-radius: 12px;
    display: flex; align-items: center; justify-content: center; font-size: 22px;
    background: rgba(255, 216, 77, .10); border: 1px solid rgba(255, 216, 77, .32);
}
#match-karte .mk-disziplin {
    font: 800 21px system-ui, sans-serif; color: var(--n-gold); line-height: 1.15;
    text-shadow: 0 0 26px rgba(255, 216, 77, .3);
}
#match-karte .mk-regel { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
#match-karte .mk-regel li {
    position: relative; padding-left: 18px;
    font: 600 13px system-ui, sans-serif; color: var(--n-fg); line-height: 1.4;
}
#match-karte .mk-regel li::before {
    content: ''; position: absolute; left: 3px; top: .5em; width: 7px; height: 7px; border-radius: 50%;
    background: var(--n-zug); box-shadow: 0 0 8px rgba(0, 229, 255, .5);
}
#match-karte .mk-start { display: flex; align-items: center; gap: 10px; margin-top: 2px; }
#match-karte .mk-start span {
    flex: none; font: 700 11px system-ui, sans-serif; color: var(--n-dim); letter-spacing: .04em;
    font-variant-numeric: tabular-nums;
}
#match-karte .mk-start span:empty { display: none; }
#match-karte .mk-zahl {
    font: 800 40px system-ui, sans-serif; color: var(--n-zug); line-height: 1;
    font-variant-numeric: tabular-nums; min-height: 0; transition: min-height .2s ease;
}
#match-karte .mk-zahl:empty { display: none; }
#match-karte .mk-balken {
    flex: 1 1 auto; height: 5px; border-radius: 999px; overflow: hidden;
    background: var(--n-line);
}
#match-karte .mk-balken i {
    display: block; height: 100%; width: 100%;
    background: linear-gradient(90deg, var(--n-gold), var(--n-zug));
    transition: width .25s linear;
}
/* Die Zeilen kommen nacheinander - der Blick geht so von oben nach unten
   durch, statt alles auf einmal zu treffen. */
#match-karte .mk-stand, #match-karte .mk-kopf, #match-karte .mk-regel li {
    transform: translateY(6px); opacity: 0; transition: all .32s var(--n-feder);
}
#match-karte.an .mk-stand,
#match-karte.an .mk-kopf,
#match-karte.an .mk-regel li { transform: none; opacity: 1; }
#match-karte.an .mk-stand { transition-delay: .05s; }
#match-karte.an .mk-kopf { transition-delay: .16s; }
#match-karte.an .mk-regel li:nth-child(1) { transition-delay: .26s; }
#match-karte.an .mk-regel li:nth-child(2) { transition-delay: .32s; }
#match-karte.an .mk-regel li:nth-child(3) { transition-delay: .38s; }

#akt-overlay .akt-gunst { display: flex; align-items: center; gap: 10px; width: 100%; }
#akt-overlay .akt-gunst span {
    font: 700 10.5px system-ui, sans-serif; letter-spacing: .1em; text-transform: uppercase;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 38%; flex: 0 1 auto;
}
#akt-overlay .akt-gunst span.du { color: var(--n-zug); }
#akt-overlay .akt-gunst span.er { color: var(--n-krit); }
#akt-overlay .akt-gunst .rohr {
    flex: 1 1 auto; height: 9px; border-radius: 999px; overflow: hidden;
    background: linear-gradient(90deg, rgba(255,77,94,.16), rgba(255,77,94,.42));
    border: 1px solid var(--n-line);
}
#akt-overlay .akt-gunst .rohr i {
    display: block; height: 100%; width: 50%;
    background: linear-gradient(90deg, #00B8CC, #00E5FF);
    transition: width .35s ease;
}

#akt-overlay .akt-posen { display: flex; gap: 6px; width: 100%; }
#akt-overlay .akt-posen div {
    flex: 1 1 0; text-align: center; padding: 5px 3px; border-radius: 9px;
    background: var(--n-panel); border: 1px solid var(--n-line);
    font: 700 10px system-ui, sans-serif; color: var(--n-dim2);
}
#akt-overlay .akt-posen div.dran { border-color: var(--n-zug); color: var(--n-fg); }
#akt-overlay .akt-posen div b {
    display: block; margin-top: 2px;
    font: 800 13px ui-monospace, Menlo, monospace; color: var(--n-gold);
}
#akt-overlay .akt-posen div.gebrochen b { color: var(--n-krit); }

/* DER HAUPTZUG DES FENSTERS - in den Farben des Hauptzugs.

   Der Knopf trug die Werte aus game.html (btn-action blau), also genau
   die Farb-Kirmes, gegen die das neue Layout gebaut ist. Er bekommt
   dieselbe Form wie der Trainingsknopf im Gitter: Tuerkis, dunkle
   Schrift, ein weicher Schein darunter. Es ist an dieser Stelle die
   eine Sache, die man tun soll. */
#akt-overlay #akt-knopf {
    width: 100%;
    background: var(--n-zug) !important;
    border: 1px solid #7DF2FF !important;
    border-radius: 12px !important;
    color: #04171C !important;
    font: 800 14px system-ui, sans-serif !important;
    padding: 12px 14px !important;
    box-shadow: 0 6px 26px -10px rgba(0,229,255,.95);
    transition: transform .13s var(--n-feder), background .2s;
}
#akt-overlay #akt-knopf:hover { background: #5BEDFF !important; }
#akt-overlay #akt-knopf:active { transform: translateY(1px) scale(.995); }
/* DAS ATTRIBUT MUSS GEWINNEN. Die beiden Leisten stehen auf
   display:flex - damit lief das hidden-Attribut ins Leere, und waehrend
   des Oelens stand die Posentafel des VORIGEN Wettkampfs sichtbar
   darunter. Genau der gemeldete Fehler "Werte bleiben vorhanden". */
#akt-overlay [hidden] { display: none !important; }


/* =========================================================
   KEIN EINZOOMEN BEIM ANTIPPEN EINES FELDES (iOS)

   Safari auf dem iPhone zoomt in jedes Eingabefeld hinein,
   dessen Schrift kleiner als 16 Punkt ist - und zoomt danach
   nicht von selbst zurueck. Der Spieler tippt also auf
   "E-Mail" und findet sich in einer vergroesserten Seite
   wieder, die er von Hand wieder kleinziehen muss.

   Gemessen waren es acht von zehn Feldern: Anmeldung (13),
   Athletenname (13), Liga-Auswahl (12,5), Loeschwort (14),
   beide Fehlermelder (13) und das Testfeld.

   ZWEI WEGE GIBT ES, UND NUR EINER TAUGT.

   maximum-scale=1 im viewport-Tag wuerde den Zoom abschalten -
   auch den, den jemand ABSICHTLICH macht, weil er schlecht
   sieht. Eine Sehhilfe wegzunehmen, um ein Layout zu retten,
   ist der falsche Handel; Apple und die WCAG sehen das ebenso.

   Also die andere Richtung: Felder tragen 16 Punkt, dann hat
   Safari keinen Anlass. Nebenbei sind sie damit auch besser
   zu lesen - die Groesse war ohnehin an der unteren Grenze.

   Kaestchen und Schieber bleiben aussen vor: sie tragen keinen
   Text, und Safari zoomt bei ihnen nicht. */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
textarea,
select {
    font-size: 16px !important;
}

/* Der Athletenname steht im Stilblock der Seite mit 14px und einer
   Spezifitaet, die die Regel oben schlaegt (.name-field input[type=text]).
   Hier, spaeter und mit Kennung, gilt wieder 16. */
#setup-screen #athlete-name-input { font-size: 16px !important; }

/* Die Code-Felder waren schon groesser (18) und gesperrt gesetzt -
   ein Duellcode wird abgetippt, nicht gelesen. Sie behalten ihr Mass;
   die Regel oben wuerde sie verkleinern. */
#match-code-input,
#tour-code-input {
    font-size: 18px !important;
}


/* =========================================================
   DER WEG ZURUECK SIEHT UEBERALL GLEICH AUS

   "Zurueck ins Gym" steht in acht Fenstern, und er sah in
   dreien anders aus als in den anderen fuenf - je nachdem,
   ob er zufaellig der erste Knopf im Raster war.

   Im Studio ist er der einzige und damit :first-child, also
   tuerkis gefuellt. Im Duellfenster steht ein verstecktes
   "Zurueck" davor - strukturell bleibt das der erste Knopf,
   auch wenn es niemand sieht, und der Ausgang wurde grau.
   Dazu kam im Duellfenster eine Regel, die den LETZTEN Knopf
   absichtlich flaechenlos setzt (fuer die dritte Wahl bei
   Schere-Hantel-Handtuch). Im Hilfefenster war er der vierte
   von vier und blieb ebenfalls blass.

   Statt an drei Stellen an Positionen zu drehen, traegt der
   Knopf jetzt seine Rolle selbst: class="modal-btn gym".
   Wer einen neuen Ausgang baut, schreibt sie dazu und muss
   nicht wissen, an welcher Stelle im Raster er landet. */
.modal-btn-grid .modal-btn.gym,
.modal-btn-grid .modal-btn.gym:first-child,
.modal-btn-grid .modal-btn.gym.still,
#match-modal .modal-btn-grid .modal-btn.gym {
    background: var(--n-zug) !important;
    border-color: var(--n-zug) !important;
    color: #04171c !important;
    box-shadow: 0 8px 26px -10px rgba(0, 229, 255, .8) !important;
}
@media (hover: hover) and (pointer: fine) {
    .modal-btn-grid .modal-btn.gym:hover,
    #match-modal .modal-btn-grid .modal-btn.gym:hover {
        background: #4de8ff !important;
        border-color: #4de8ff !important;
        color: #04171c !important;
    }
}

/* ---------- DEIN PUMPLING UND DIE GALERIE IM STIL DER SUCHE (v6.81) ----------
   "Das Dein-Pumpling-Fenster mit den Anpassungsmoeglichkeiten und der
   Galerie auf das frische Design der Spielersuche bringen." Dieselbe hohe
   Tafel wie die Gegnersuche: oben die Buehne mit dem Pumpling im Licht
   (suchBuehneMalen, 'solo'), darunter sein Schild, dann die Wahl. Die
   Buehne bleibt stehen, nur der Inhalt darunter rollt - so sieht man die
   Figur, waehrend man waehlt. */
#pumpling-modal:has(.pb-tafel),
#vorschau-modal:has(.pb-tafel) { padding: 10px !important; }
.modal-box.pb-tafel {
    max-width: 460px !important;
    width: 100%;
    height: min(760px, calc(100 * var(--sh, 1dvh) - 20px));
    max-height: calc(100 * var(--sh, 1dvh) - 20px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.modal-box.vs-tafel { height: auto; min-height: min(640px, calc(100 * var(--sh, 1dvh) - 20px)); text-align: center; }
.pb-tafel .sb-buehne {
    position: relative;
    flex: 0 0 auto;
    height: clamp(180px, calc(34 * var(--sh, 1dvh)), 280px);
    margin: 0 -18px;
    overflow: hidden;
    background: var(--n-bg2);
    border-top: 1px solid var(--n-line);
    border-bottom: 1px solid var(--n-line);
}
.vs-tafel .sb-buehne { flex: 1 1 280px; height: auto; min-height: 240px; }
.pb-tafel .sb-buehne canvas {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    display: block;
}
/* Ein Kegel mittig ueber dem einen Podest, im Cyan des Spielers. */
.sb-kegel-mitte {
    left: 28%;
    --sb-licht: linear-gradient(180deg, rgba(0, 229, 255, .28), rgba(0, 229, 255, .05) 85%, transparent);
    --sb-pfuetze: rgba(0, 229, 255, .24);
}
/* Gesperrt: das Licht wird golden - so sieht, was man sich erst holen
   muss, in der Galerie aus (dieselbe Farbe wie das Suchlicht). Sonst
   bleibt alles hell: man soll sehen, was man sich holen kann. Die
   Klasse heisst nicht 'gesperrt' - die dimmt im Spiel ganze Knoepfe
   ab (opacity .42, spiel-basis.html) und lag so als Schleier ueber der
   ganzen Buehne. */
.vs-buehne.vs-gesperrt .sb-kegel-mitte {
    --sb-licht: linear-gradient(180deg, rgba(255, 216, 77, .32), rgba(255, 216, 77, .06) 85%, transparent);
    --sb-pfuetze: rgba(255, 216, 77, .26);
}

/* Das Schild unter der Buehne: Name gross, darunter Masse und Rang, der
   Strich darueber im Cyan des Spielers - wie auf der Suche. */
.pb-schild {
    display: flex; flex-direction: column; align-items: center;
    gap: 3px; margin: 12px 0 2px; text-align: center; min-width: 0;
}
.pb-schild::before {
    content: '';
    width: 26px; height: 3px; border-radius: 2px;
    margin-bottom: 5px;
    background: var(--n-zug);
    box-shadow: 0 0 10px rgba(0, 229, 255, .45);
}
.pb-schild b {
    font: 800 16px/1.2 system-ui, sans-serif; letter-spacing: -.01em;
    color: var(--n-fg);
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pb-schild i {
    font: 500 12px/1.3 system-ui, sans-serif; font-style: normal;
    color: var(--n-dim2);
}
/* display: flex schlaegt das hidden-Attribut - die Galerie zeigt ihr
   Schild nur bei Namensrahmen (vorschauSchild, 39-vorschau.js). */
.pb-schild[hidden] { display: none; }

/* Die Reiter: ein Schalter aus drei Teilen, der gewaehlte leuchtet cyan. */
.pb-reiter {
    flex: none;
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px;
    margin: 12px 0 10px; padding: 4px;
    border-radius: 999px;
    background: var(--n-bg2);
    border: 1px solid var(--n-line);
}
.pb-reiter button {
    appearance: none; border: 0; cursor: pointer;
    background: transparent;
    color: var(--n-dim);
    font: 700 13px/1 system-ui, sans-serif;
    padding: 10px 6px;
    border-radius: 999px;
    transition: background .2s ease, color .2s ease, box-shadow .2s ease;
}
.pb-reiter button:hover { color: var(--n-fg); }
.pb-reiter button[aria-selected="true"] {
    background: rgba(0, 229, 255, .13);
    color: var(--n-zug);
    box-shadow: inset 0 0 0 1px rgba(0, 229, 255, .45);
}
.pb-reiter button:focus-visible { outline: 2px solid var(--n-zug); outline-offset: 2px; }

/* "Dein Pumpling" hat seit v6.91 vier Reiter, solange der Laden Extras
   fuehrt (34-aussehen.js, pumplingReiterZeigen) - die Spalten richten sich
   nach den sichtbaren Knoepfen statt nach einer festen Drei. */
.pb-reiter-figur { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 1fr; }
.pb-reiter-figur button[hidden] { display: none; }

/* Die Stufe am Preis im Schaufenster (39-vorschau.js, data-stufe). */
.vs-stand[data-stufe="selten"]    { color: #60a5fa; }
.vs-stand[data-stufe="legendaer"] { color: #f1c40f; }
.vs-stand[data-stufe="erspielt"]  { color: #fb923c; }
.vs-stand[data-stufe="monatsplan"] { color: #a78bfa; }

/* NAMENSRAHMEN (v6.92, Laden): am eigenen Namen oben, in "Dein Pumpling",
   in der Hall of Fame und im Arenakopf (namensRahmen, 32-studio.js). */
.rahmen-gold, .rahmen-neon, .rahmen-flammen { border-radius: 999px; padding-left: .45em; padding-right: .45em; }
.rahmen-gold    { box-shadow: 0 0 0 2px #f1c40f, 0 0 10px rgba(241, 196, 15, .45); }
.rahmen-neon    { box-shadow: 0 0 0 2px #22d3ee, 0 0 12px rgba(34, 211, 238, .75), 0 0 22px rgba(236, 72, 153, .45); }
.rahmen-flammen { box-shadow: 0 0 0 2px #f97316, 0 -2px 14px rgba(249, 115, 22, .75), 0 0 20px rgba(239, 68, 68, .5);
                  animation: rahmen-flackern 1.1s ease-in-out infinite alternate; }
@keyframes rahmen-flackern {
    from { box-shadow: 0 0 0 2px #f97316, 0 -2px 10px rgba(249, 115, 22, .6), 0 0 16px rgba(239, 68, 68, .4); }
    to   { box-shadow: 0 0 0 2px #fb923c, 0 -4px 18px rgba(253, 186, 116, .85), 0 0 26px rgba(239, 68, 68, .6); }
}
@media (prefers-reduced-motion: reduce) { .rahmen-flammen { animation: none; } }
/* Saisonrahmen (v6.94): Halloween orange mit violettem Schein, Winter eisblau mit Raureif. */
.rahmen-grusel, .rahmen-frost { border-radius: 999px; padding-left: .45em; padding-right: .45em; }
.rahmen-grusel { box-shadow: 0 0 0 2px #f97316, 0 0 12px rgba(168, 85, 247, .7), 0 0 20px rgba(249, 115, 22, .35); }
.rahmen-frost  { box-shadow: 0 0 0 2px #bae6fd, inset 0 0 6px rgba(224, 242, 254, .55), 0 0 12px rgba(56, 189, 248, .6); }
/* Monatsplan (v7.02): der Rahmen in der Monatsfarbe (Farben als
   Eigenschaften, namensRahmen) und der Regenbogen, der um den Namen laeuft. */
.rahmen-mp, .rahmen-regenbogen { border-radius: 999px; padding-left: .45em; padding-right: .45em; }
.rahmen-mp { box-shadow: 0 0 0 2px var(--rahmen-a), 0 0 12px var(--rahmen-b); }
.rahmen-regenbogen { box-shadow: 0 0 0 2px #ef4444, 0 0 12px rgba(250, 204, 21, .6); animation: rahmen-regenbogen 4s linear infinite; }
@keyframes rahmen-regenbogen {
    0%   { box-shadow: 0 0 0 2px #ef4444, 0 0 12px rgba(250, 204, 21, .6); }
    25%  { box-shadow: 0 0 0 2px #facc15, 0 0 12px rgba(34, 197, 94, .6); }
    50%  { box-shadow: 0 0 0 2px #22c55e, 0 0 12px rgba(59, 130, 246, .6); }
    75%  { box-shadow: 0 0 0 2px #3b82f6, 0 0 12px rgba(139, 92, 246, .6); }
    100% { box-shadow: 0 0 0 2px #ef4444, 0 0 12px rgba(250, 204, 21, .6); }
}
/* Prisma (v7.03): der Regenbogen mit Goldkante - die Prunkfassung. */
.rahmen-prisma { border-radius: 999px; padding-left: .45em; padding-right: .45em;
                 box-shadow: 0 0 0 2px #ef4444, 0 0 0 4px #f1c40f, 0 0 14px rgba(250, 204, 21, .65);
                 animation: rahmen-prisma 4s linear infinite; }
@keyframes rahmen-prisma {
    0%   { box-shadow: 0 0 0 2px #ef4444, 0 0 0 4px #f1c40f, 0 0 14px rgba(250, 204, 21, .65); }
    25%  { box-shadow: 0 0 0 2px #facc15, 0 0 0 4px #f1c40f, 0 0 14px rgba(34, 197, 94, .6); }
    50%  { box-shadow: 0 0 0 2px #22c55e, 0 0 0 4px #f1c40f, 0 0 14px rgba(59, 130, 246, .6); }
    75%  { box-shadow: 0 0 0 2px #3b82f6, 0 0 0 4px #f1c40f, 0 0 14px rgba(139, 92, 246, .6); }
    100% { box-shadow: 0 0 0 2px #ef4444, 0 0 0 4px #f1c40f, 0 0 14px rgba(250, 204, 21, .65); }
}
@media (prefers-reduced-motion: reduce) { .rahmen-regenbogen, .rahmen-prisma { animation: none; } }

/* Nur der Inhalt rollt; Buehne, Schild und Reiter bleiben stehen. */
.pb-inhalt {
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto; overscroll-behavior: contain;
    margin: 0 -8px !important; padding: 0 8px 4px !important;
}
.pb-inhalt .studio-gruppe:first-child { margin-top: 2px; }
.pb-fuss { flex: none; margin-top: 12px !important; }

/* GALERIE: Pfeile auf der Buehne, der Zaehler als Marke oben rechts. */
.vs-pfeil {
    /* Ohne transform: die allgemeine button:hover-Regel (game.html)
       setzt translateY(-1px) und riss den Pfeil beim Ueberfahren aus
       seiner Mitte. */
    position: absolute; top: calc(50% - 22px);
    width: 44px; height: 44px; border-radius: 50%;
    display: grid; place-items: center;
    font: 700 26px/1 system-ui, sans-serif; color: var(--n-fg);
    background: rgba(8, 10, 13, .55);
    border: 1px solid var(--n-line);
    backdrop-filter: blur(4px);
    cursor: pointer;
    transition: border-color .2s ease, color .2s ease;
}
.vs-pfeil:hover, .vs-pfeil:focus-visible { border-color: var(--n-zug); color: var(--n-zug); outline: none; }
.vs-buehne .vs-pfeil:hover:not(:disabled), .vs-buehne .vs-pfeil:active:not(:disabled),
.pb-reiter button:hover:not(:disabled), .pb-reiter button:active:not(:disabled) { transform: none; filter: none; }
.vs-links { left: 12px; }
.vs-rechts { right: 12px; }
.vs-zaehler {
    position: absolute; top: 10px; right: 12px;
    padding: 3px 9px; border-radius: 999px;
    font: 700 11px ui-monospace, Menlo, monospace; letter-spacing: .04em;
    color: var(--n-dim);
    background: rgba(8, 10, 13, .6);
    border: 1px solid var(--n-line);
}
.vs-zaehler:empty { display: none; }
/* Die Kulisse fuer Stuecke der Studiowand fuellt dieselbe Buehne. */
.vs-buehne #vorschau-canvas { object-fit: cover; display: none; }
.vs-buehne.wand #vorschau-canvas { display: block; }
.vs-buehne.wand .sb-kegel { display: none; }
.vs-stand {
    display: inline-block;
    margin: 14px auto 4px;
    padding: 5px 12px; border-radius: 999px;
    font: 700 13px/1.3 system-ui, sans-serif;
    color: var(--n-gold);
    background: rgba(255, 216, 77, .10);
    border: 1px solid rgba(255, 216, 77, .35);
}
.vs-stand:empty { display: none; }
.vs-stand.frei { color: var(--n-gut); background: rgba(74, 222, 128, .10); border-color: rgba(74, 222, 128, .35); }
.vs-text {
    margin: 4px auto 0; max-width: 36ch;
    font: 400 13px/1.45 system-ui, sans-serif; color: var(--n-dim);
}
.vs-fuss { margin-top: auto !important; padding-top: 14px; grid-template-columns: 1fr 1fr !important; }

@media (prefers-reduced-motion: reduce) {
    .pb-reiter button, .vs-pfeil { transition: none; }
}

/* ---------- DEIN STUDIO IM STIL DER SUCHE (v6.81) ----------
   "Dein Studio auch noch im neuen Stil": dieselbe hohe Tafel wie Dein
   Pumpling (.pb-tafel). Die Buehne zeigt hier das Studio selbst - Wand,
   Boden, Licht und Deko mit dem Pumpling davor (32-studio.js,
   studioBuehne) -, deshalb ohne Lichtkegel: das Licht ist selbst ein
   Stueck zum Kaufen. Die Reiter kommen aus dem Katalog, so viele, wie der
   Server Steckplaetze liefert (--st-n). */
#studio-modal:has(.st-tafel) { padding: 10px !important; }
.st-buehne canvas { object-fit: cover; }
.st-probe {
    position: absolute; top: 10px; left: 12px;
    padding: 3px 10px; border-radius: 999px;
    font: 700 11px/1.3 system-ui, sans-serif; letter-spacing: .02em;
    color: var(--n-gold);
    background: rgba(8, 10, 13, .62);
    border: 1px solid rgba(255, 216, 77, .45);
}
.st-probe:empty { display: none; }
.st-reiter { grid-template-columns: repeat(var(--st-n, 4), minmax(0, 1fr)); }
.st-reiter button { font-size: 12.5px; padding: 10px 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Die Karten: ganze Flaeche antippbar (Probe), der Knopf darin kauft. */
.st-inhalt .studio-teil {
    cursor: pointer;
    border-radius: 14px;
    padding: 12px 14px 12px;
    margin-bottom: 8px;
    background: var(--n-panel) !important;
    transition: border-color .2s ease, box-shadow .2s ease;
}
.st-inhalt .studio-teil:hover { border-color: var(--n-stahl) !important; }
.st-inhalt .studio-teil.drin { box-shadow: inset 3px 0 0 var(--n-zug); }
.st-inhalt .studio-teil.probe {
    border-color: var(--n-gold) !important;
    box-shadow: 0 0 0 1px rgba(255, 216, 77, .30), 0 0 18px rgba(255, 216, 77, .10);
}
.st-inhalt .studio-teil.drin.probe { box-shadow: inset 3px 0 0 var(--n-zug), 0 0 0 1px rgba(255, 216, 77, .30); }
.st-inhalt .studio-kopf b { font-size: 14px; }
.st-inhalt .studio-preis { font-weight: 700; }
.st-inhalt .studio-text { font-size: 12px; line-height: 1.45; margin: 4px 0 10px; }
.st-inhalt .studio-knopf { padding: 9px; }
.st-inhalt .studio-teil:focus-within { border-color: var(--n-zug) !important; }

@media (prefers-reduced-motion: reduce) {
    .st-inhalt .studio-teil { transition: none; }
}

/* ---------- HALL OF FAME IM STIL DER SUCHE (v6.81) ----------
   "Die Highscoreliste auch dem neuen Fensterlayout anpassen": dieselbe
   hohe Tafel wie Dein Pumpling und Dein Studio (.pb-tafel). Oben das
   Podest mit den ersten drei (hofBuehneMalen, 33-buehne.js), darunter
   das Schild dessen, der im Licht steht, die vier Wertungen als Reiter
   und die Liste - nur sie rollt. Ein Tipp auf eine Zeile stellt den
   Athleten allein ins Licht, "Podest" auf der Buehne holt die drei
   zurueck.

   Die Buehne ist hier niedriger als in den anderen Tafeln: die Liste
   ist der Inhalt, das Podest ihr Auftakt. Auf einem kleinen Telefon
   bleiben so vier bis fuenf Zeilen sichtbar statt drei. */
#board-modal:has(.hof-tafel) { padding: 10px !important; }
.pb-tafel .sb-buehne.hof-buehne { height: clamp(160px, calc(28 * var(--sh, 1dvh)), 240px); }
.hof-marke {
    position: absolute; top: 10px; right: 12px;
    padding: 3px 10px; border-radius: 999px;
    font: 700 11px/1.3 system-ui, sans-serif; letter-spacing: .02em;
    color: var(--n-dim);
    background: rgba(8, 10, 13, .6);
    border: 1px solid var(--n-line);
}
.hof-marke:empty { display: none; }
.hof-zurueck {
    position: absolute; top: 10px; left: 12px;
    width: auto;                  /* die allgemeine Knopfregel setzt 100 % */
    padding: 5px 12px; border-radius: 999px;
    font: 700 12px/1.2 system-ui, sans-serif;
    color: var(--n-fg);
    background: rgba(8, 10, 13, .62);
    border: 1px solid var(--n-line);
    backdrop-filter: blur(4px);
    cursor: pointer;
    transition: border-color .2s ease, color .2s ease;
}
.hof-zurueck[hidden] { display: none; }
.hof-zurueck:hover, .hof-zurueck:focus-visible { border-color: var(--n-zug); color: var(--n-zug); outline: none; }
/* Wie bei den Pfeilen der Galerie: die allgemeine button:hover-Regel
   (game.html) hebt Knoepfe an und riss den Knopf aus seiner Ecke. */
.hof-buehne .hof-zurueck:hover:not(:disabled), .hof-buehne .hof-zurueck:active:not(:disabled) { transform: none; filter: none; }
.hof-reiter { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.hof-reiter button { font-size: 12.5px; padding: 10px 4px; }
.hof-ticker {
    flex: none;
    margin: -2px 0 8px;
    font: italic 400 12px/1.35 system-ui, sans-serif;
    color: var(--n-dim);
    text-align: center;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Die Liste fuellt, was die Tafel uebrig laesst, und rollt als einzige. */
.hof-tafel .board-list {
    flex: 1 1 auto; min-height: 0; max-height: none;
    overflow-y: auto; overscroll-behavior: contain;
    padding: 4px;
    border-radius: 14px !important;
    font-size: 13px;
}
.hof-tafel .board-row {
    grid-template-columns: 34px 1fr auto;
    padding: 9px 8px;
    border-bottom: 1px solid rgba(143, 178, 206, .08);
    border-radius: 10px;
    transition: background .15s ease, box-shadow .15s ease;
}
.hof-tafel .board-row:last-child { border-bottom: none; }
.hof-tafel .board-row.ist-waehlbar { cursor: pointer; }
.hof-tafel .board-row.ist-waehlbar:hover { background: rgba(255, 255, 255, .035); }
.hof-tafel .board-row:focus-visible { outline: 2px solid var(--n-zug); outline-offset: -2px; }
/* Du: der Strich links im Cyan des Spielers, wie im Studio (.drin). */
.hof-tafel .board-row.is-me { background: rgba(0, 229, 255, .08); box-shadow: inset 3px 0 0 var(--n-zug); }
/* Im Licht: goldener Rahmen, dieselbe Farbe wie das Licht der Galerie. */
.hof-tafel .board-row.ist-fokus {
    background: rgba(255, 216, 77, .10);
    box-shadow: inset 0 0 0 1px rgba(255, 216, 77, .45);
}
.hof-tafel .board-row.is-me.ist-fokus { box-shadow: inset 3px 0 0 var(--n-zug), inset 0 0 0 1px rgba(255, 216, 77, .45); }
.hof-tafel .board-rank:not(.ist-medaille) { color: var(--n-dim); font-variant-numeric: tabular-nums; }
.hof-tafel .board-name { color: var(--n-fg); }
.hof-tafel .board-score { color: var(--n-fg); font-variant-numeric: tabular-nums; }
.hof-tafel .board-gruppe { color: var(--n-dim); border-top-color: var(--n-line); }
.hof-tafel .board-me {
    flex: none;
    margin-top: 10px;
    padding: 8px 12px;
    font: 600 12px/1.35 system-ui, sans-serif;
    text-align: center;
}
.hof-tafel .board-me:empty { display: none; }

/* Kurze Bildschirme (ein iPhone SE hat 667 Punkte): Buehne, Schild und
   Reiter ruecken zusammen, die Nachrichtenzeile faellt weg - sonst
   blieben von der Liste drei Zeilen. Die Zeile setzt 18-board.js als
   Stil (display '' oder 'none'); die Regel greift, wenn sie sichtbar
   waere. */
@media (max-height: 720px) {
    .pb-tafel .sb-buehne.hof-buehne { height: clamp(130px, calc(22 * var(--sh, 1dvh)), 170px); }
    .hof-tafel .pb-schild { margin-top: 8px; }
    .hof-tafel .hof-reiter { margin: 8px 0 8px; }
    .hof-tafel .hof-ticker { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .hof-zurueck, .hof-tafel .board-row { transition: none; }
}

/* MONATSPLAN (v7.02, 51-monatsplan.js): Kasten in der Monatsfarbe unter
   Tagesplan und Wochenzielen, Fenster mit den 30 Stufen. */
.ziel-box[hidden] { display: none; }
.mp-box { border-color: var(--mp-a, var(--n-line)) !important; }
.mp-balken { height: 4px; margin: 0 10px 6px; background: var(--n-panel2); border-radius: 2px; overflow: hidden; }
.mp-balken i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--mp-a, var(--n-gold)), var(--mp-b, var(--n-cyan))); transition: width .4s; }
.mp-rest { font-size: 12px; color: var(--n-dim); margin: 6px 0 4px; }
.mp-alle { width: 100%; margin-top: 4px; }
.mp-fenster { max-width: 420px; }
.mp-buehne { height: 200px; }
.mp-buehne canvas { width: 100%; height: 100%; object-fit: cover; }
.mp-hinweis { font-size: 12px; margin: 6px 0; }
.mp-stufen { max-height: calc(40 * var(--sh, 1vh)); overflow-y: auto; display: grid; gap: 4px; margin-bottom: 10px; }
.mp-stufe { display: grid; grid-template-columns: 2.2em 1fr 1.4em; align-items: center; padding: 6px 8px; border-radius: 8px; background: var(--n-panel2); font-size: 13px; }
.mp-stufe.stueck { cursor: pointer; border: 1px solid var(--n-line); }
/* Das Bild des Stuecks vor seinem Namen (v7.09). */
.mp-stufe.stueck span { display: flex; align-items: center; justify-content: center; gap: 8px; }
.mp-stufe .mp-bild { width: 36px; height: 36px; flex: none; border-radius: 6px; background: var(--n-bg2); }
.mp-stufe span em { font-style: normal; }
.mp-stufe.erreicht { opacity: .6; }
.mp-stufe.naechste { outline: 2px solid var(--n-gold); }
.mp-stufe i { color: var(--n-gut); font-style: normal; text-align: right; }

/* ---------- RUECKMELDUNG (v7.19, 53-rueckmeldung.js) ----------
   Wackeln ueber "translate", nicht "transform": so bleibt eine
   eigene Verschiebung des Fensters (Zentrieren, Einblenden) stehen. */
@keyframes rm-wackeln {
    0%, 100% { translate: 0 0; }
    15% { translate: calc(var(--rm-staerke, 3) * -1px) calc(var(--rm-staerke, 3) * 0.5px); }
    30% { translate: calc(var(--rm-staerke, 3) * 0.9px) calc(var(--rm-staerke, 3) * -0.6px); }
    45% { translate: calc(var(--rm-staerke, 3) * -0.7px) calc(var(--rm-staerke, 3) * 0.4px); }
    60% { translate: calc(var(--rm-staerke, 3) * 0.5px) calc(var(--rm-staerke, 3) * -0.3px); }
    75% { translate: calc(var(--rm-staerke, 3) * -0.3px) 0; }
}
.rm-wackeln { animation: rm-wackeln 0.42s ease-out; }
@keyframes rm-blitz { from { opacity: var(--rm-blitz, 0.35); } to { opacity: 0; } }
.rm-blitz { position: fixed; inset: 0; background: #fff; pointer-events: none; z-index: 2147483000; opacity: 0; animation: rm-blitz 0.32s ease-out; }
@media (prefers-reduced-motion: reduce) {
    .rm-wackeln { animation: none; }
    .rm-blitz { display: none; }
}

/* =========================================================
   GRUPPEN-LEISTE (v7.24)

   Stephan: "dass wir aufklappbaren menues kompakter gestalten, sodass
   das menue auch nur max 40% hoehe im ausgefahrenen zustand belegt und
   mehr platz fuer die buehne bleibt". v7.23 versuchte es mit Kacheln
   (Vorschlag A), danach: "ich wuerde doch vorschlag b 'gruppenleiste'
   bevorzugen. die kacheln jetzt sind zu klein."

   Jede Gruppe eines Reiters ist ein Schalter in der Kopfzeile der
   Schublade (tools/spiel-neu.js, gruppenLeisten); darunter steht nur die
   gewaehlte Gruppe, mit den gewohnten Knoepfen samt Beschreibung. Alle
   Gruppen eines Reiters liegen in DERSELBEN Gitterzelle, die nicht
   gewaehlten unsichtbar: die Schublade ist so hoch wie die hoechste
   Gruppe und springt beim Umschalten nicht - sonst wanderte die Buehne
   bei jedem Schalter mit. tools/menue-gruppen.test.js
   ========================================================= */
/* DER GRIFF STEHT OBEN, DIE LUFT LIEGT ZWISCHEN IHM UND DEN SCHALTERN
   (v7.26). Stephan: "der obere abstand des menues 'mit dem balken zum
   runterziehen' soll mehr abstand zu den pillen haben, nicht der
   untere" - v7.25 hatte den Rand ueber dem Balken vergroessert. Unter
   den Schaltern bleibt es knapp.
   DIE LUFT IST KEINE TIPPFLAECHE (v7.32). Stephan: "der abstand von den
   pillen zur schliesen leiste im menue muss noch etwas mehr. man klickt
   dort oft faelschlicher weise auf schliessen anstatt wie gewollt auf eine
   pille". Bis v7.31 lag die Luft als Innenabstand im Knopf - wer knapp
   ueber einen Schalter tippte, schloss das Menue. Jetzt ein Aussenrand:
   20 statt 16 px zwischen Balken und Schaltern, davon nur 6 zum Schliessen.
   NOCH ETWAS MEHR (v7.44). Stephan: "Der Abstand zwischen den Pillen und
   den schliessen Balken vom Menue noch etwas hoeher" - 28 px, davon
   weiterhin nur 6 zum Schliessen. */
.panels .schub-griff { padding: 8px 0 6px; margin-bottom: 22px; }
.panels .schub-kopf { align-items: center; gap: 8px; padding: 0 10px 6px; }
.panels .schub-inhalt { padding: 8px 12px 10px; }

.gruppen-leiste {
    display: flex; gap: 6px; flex: 1 1 auto; min-width: 0;
    overflow-x: auto; scrollbar-width: none;
}
.gruppen-leiste::-webkit-scrollbar { display: none; }
.gruppen-leiste[hidden] { display: none; }
.gr-chip {
    flex: 0 0 auto; width: auto !important; cursor: pointer;
    padding: 6px 11px !important; border-radius: 999px !important;
    border: 1px solid var(--n-line) !important; background: none !important;
    color: var(--n-dim) !important; font: 800 11.5px system-ui, sans-serif !important;
    white-space: nowrap;
}
.gr-chip[aria-selected="true"] {
    background: var(--ton, var(--n-fg)) !important; color: #04171c !important; border-color: transparent !important;
}

.panel:not([hidden]) { display: grid; }
.panel > .gruppe { grid-area: 1 / 1; visibility: hidden; }
.panel > .gruppe.an { visibility: visible; }
.panel > .gruppe > .lbl { display: none; }
.panel > .gruppe + .gruppe { margin-top: 0; }
/* Die Knoepfe behalten ihre 12 px (v7.24 hatte sie auf 9 gedrueckt, um
   unter 40 % zu bleiben - "das menue ist so ganz gut aber schon etwas zu
   kompakt", v7.25). */

/* Im Wettkampf stehen Peak Week und Wettkampf nebeneinander (die Bühne
   mit der Liga-Auswahl darueber). "Gegner suchen" stand bis v7.29 neben
   dem Armdruecken; seit das keinen eigenen Knopf mehr hat, steht es allein
   in "Gegen andere" und behaelt seine volle Breite (Inline-Stil "span 2"). */
.panel > .gruppe .knopfgitter :is(button[onclick*="enterCompetition"], button[onclick*="peakWeek"]) {
    grid-column: auto !important;   /* gegen den Inline-Stil "span 2" */
}
/* IM REITER "ICH" OHNE BESCHREIBUNGSZEILE (v7.25). "Dein Kram" hat fuenf
   Knoepfe in drei Reihen und bestimmt als hoechste Gruppe die Hoehe der
   Schublade - mit umbrechenden Beschreibungen auf 360 px Breite 235 px,
   das Menue lag dort bei 51 %. "Dein Studio", "Hall of Fame" oder
   "Ton: an" erklaeren sich selbst; in den uebrigen Reitern bleibt die
   Zeile. */
#p-ich .knopfgitter .s { display: none; }
/* Die Versionszeile in den Einstellungen, knapp unter den Knoepfen. */
.panel > .gruppe .ich-stand { margin: 10px 0 0; }

/* NIEDRIGE BILDSCHIRME (unter 740 Punkten, etwa iPhone SE): ohne
   Beschreibungszeile und mit flacheren Schaltern - sonst laege das Menue
   dort ueber der Haelfte. Seit v7.25 wieder erst ab 740 (v7.24: 820) -
   Telefone mit 800 Punkten und Desktop-Fenster zeigen die Beschreibung.
   Der Name und das Zeichen bleiben in voller Groesse. Die Uebungsmarke ("KABELZUG") rueckt in die Zeile der
   fehlenden Beschreibung. */
@media (max-height: 740px) {
    .panel > .gruppe .knopfgitter .s { display: none; }
    .panels .knopfgitter button:not([onclick*="logout"]):not([onclick*="deleteAccount"]) { padding: 9px 10px !important; }
    /* Ohne zweite Zeile steht der Name auf Hoehe der Preismarke: Platz
       fuer sie lassen, lange Namen brechen dann um ("Creatin kaufen"). */
    .panels .knopfgitter button[data-preis]:not(#btn-train) { padding-right: 46px !important; }
    .panel > .gruppe .knopfgitter { gap: 6px; }
    .gr-chip { padding: 4px 10px !important; }
    .panels .schub-griff { padding: 6px 0 5px; margin-bottom: 17px; }
    .panels .schub-kopf { padding-bottom: 4px; }
    .panels .schub-inhalt { padding: 6px 12px 8px; }
    .panel > .gruppe .knopfgitter #btn-train.hat-ic > :not(.knopf-ic):not(.t):not(.s) { grid-area: 2 / 2; justify-self: start; }
    .panel > .gruppe .ich-stand { margin-top: 6px; }
    /* Die Zielkaesten flacher: mit dem Monatsplan sind es drei, und dann
       ist "Aufgaben" hier die hoechste Gruppe (gemessen 154 px, "Ich"
       sonst bei 45 %). */
    .panel > .gruppe .ziel-box { margin: 0 0 6px !important; }
    .panel > .gruppe .ziel-tuer { padding: 7px 10px !important; }
}

/* =========================================================
   LOGIN-SERIE (v7.34, 54-loginserie.js): das eigene Feld bei den
   Aufgaben (v7.43; die Zeile im Tagesplan ist seit v7.44 raus) und der
   7-Tage-Kalender im Fenster.
   ========================================================= */
/* Das eigene Feld bei den Aufgaben (v7.43): in der Farbe der Flamme. */
.ls-box { border-color: rgba(253, 186, 116, .35) !important; }
.ls-box .daily-head { color: #fdba74 !important; }
.ls-box .ziel-stand.fertig { color: #fdba74; }
/* Der Kasten klappt nie auf - ohne "zu" blendete die Regel fuer offene
   Kaesten (.ziel-box:not(.zu) .ziel-stand) den Stand n/7 aus (Foto v7.43). */
.ziel-box.ls-box .ziel-stand { display: inline !important; }
/* GROESSER (v7.38). Stephan: "ein bisschen klein auf dem iPhone 13" - sieben
   Kacheln in einer Reihe waren dort je 40 px breit, die Schrift 9-10 px.
   Jetzt vier je Reihe, Tag 7 ueber zwei Spalten mit Bild und Namen. */
.login-kalender { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; margin: 4px 0 14px; }
.login-kalender[hidden] { display: none; }
.ls-tag { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
          min-width: 0; min-height: 62px; padding: 8px 3px; border-radius: 12px;
          background: rgba(148, 163, 184, .10); border: 1px solid rgba(148, 163, 184, .18); }
.ls-tag .ls-nr { font-size: 12px; color: #94a3b8; white-space: nowrap; }
.ls-tag .ls-wert { font-size: 16px; font-weight: 800; color: #e2e8f0; white-space: nowrap; }
.ls-tag .ls-bild { width: 40px; height: 40px; }
.ls-tag.ls-sieben { grid-column: span 2; }
.ls-tag .ls-name { font-size: 12px; font-weight: 700; color: #fdba74; max-width: 100%;
                   overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ls-tag.erledigt { background: rgba(249, 115, 22, .16); border-color: rgba(249, 115, 22, .45); }
.ls-tag.erledigt .ls-wert { color: #fdba74; }
.ls-tag.heute { background: rgba(249, 115, 22, .32); border-color: #f97316; box-shadow: 0 0 10px rgba(249, 115, 22, .45); }
.ls-tag.heute .ls-nr { color: #fed7aa; }
/* Tag 7 mit einem Rahmen: das Namensschild mit dem neuen Rahmen, ueber den Kacheln. */
.ls-schild { grid-column: 1 / -1; display: flex; justify-content: center; padding: 8px 0 10px; }
.ls-schild b { font-size: 16px; color: #f8fafc; background: rgba(2, 6, 23, .86); padding: .3em .9em; }

/* Der Stammgast-Rahmen (Login-Serie, Woche 1): Bernsteinrand und eine
   Flamme vorn am Namen. Auf der Leinwand: namensRahmenMalen (32-studio.js). */
.rahmen-stammgast { border-radius: 999px; padding-left: 1.5em; padding-right: .45em; position: relative;
                    box-shadow: 0 0 0 2px #f59e0b, 0 0 12px rgba(239, 68, 68, .45); }
.rahmen-stammgast::before { content: '🔥'; position: absolute; left: .3em; top: 50%; transform: translateY(-52%);
                            font-size: .85em; line-height: 1; }

/* =========================================================
   REAKTION: DIE SPIELFLAECHE MIT DEM KREIS (v7.36, 24-match.js)
   Der Kreis erscheint an der Stelle aus reaktOrt (left/top in Prozent, die
   Mitte); getroffen wird nach Geometrie (reaktTreffer) - der Kreis selbst
   nimmt keine Zeiger an.
   ========================================================= */
.react-feld { position: relative; width: 100%; height: 240px; margin-top: 6px; border-radius: 14px;
              background: var(--n-panel2); overflow: hidden; cursor: crosshair;
              touch-action: none; user-select: none; -webkit-user-select: none;
              box-shadow: inset 0 0 0 1px rgba(148, 163, 184, .18); }
.react-ansage { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
                padding: 10px; font-size: 22px; font-weight: bold; line-height: 1.3; text-align: center;
                color: var(--n-fg); pointer-events: none; }
.react-kreis { position: absolute; width: 22%; aspect-ratio: 1; transform: translate(-50%, -50%);
               border-radius: 50%; pointer-events: none;
               background: radial-gradient(circle at 38% 34%, #ffd84d 0 18%, #ff4d5e 46%, #b5172a 100%);
               box-shadow: 0 0 0 3px rgba(255, 255, 255, .85), 0 0 22px rgba(255, 77, 94, .85);
               animation: react-kreis-auf .12s ease-out; }
.react-kreis[hidden] { display: none; }
@keyframes react-kreis-auf { from { transform: translate(-50%, -50%) scale(.6); } to { transform: translate(-50%, -50%) scale(1); } }

/* =========================================================
   STUDIO-LAUF: DIE TEMPOLEISTE (v7.37, 31a-lauf-bild.js)
   Sieben Segmente vom Start- zum Hoechsttempo; laufTempoleisteStellen
   setzt .an. Gruen, dann gelb, orange, rot.
   ========================================================= */
.lauf-tempo { display: flex; align-items: center; justify-content: center; gap: 4px; margin-top: 8px; }
.lauf-tempo b { font-size: 11px; font-weight: 700; color: var(--n-dim); margin-right: 4px; letter-spacing: .04em; }
.lauf-tempo i { width: 24px; height: 6px; border-radius: 3px; background: rgba(148, 163, 184, .18); transition: background-color .2s; }
.lauf-tempo i.an { background: #22c55e; }
.lauf-tempo i.an:nth-of-type(n+4) { background: #eab308; }
.lauf-tempo i.an:nth-of-type(6) { background: #f97316; }
.lauf-tempo i.an:nth-of-type(7) { background: #ef4444; }

/* =========================================================
   ONLINE: GEGNER WEG ALS EIGENE ANSICHT (v7.39, 24-match.js
   renderMatchResult). Buehne oben randlos wie die Pausenkarte, er steht
   blass daneben mit dem Schild "hat das Duell verlassen"; darunter Pille,
   Tafel, die Zeile, was zaehlt, und zwei Knoepfe.
   ========================================================= */
#match-result .erg-buehne {
    position: relative; width: calc(100% + 32px); margin: -6px -16px 12px;
    height: clamp(150px, calc(26 * var(--sh, 1dvh)), 220px); overflow: hidden;
    background: var(--n-bg2); border-bottom: 1px solid var(--n-line); border-radius: 16px 16px 0 0;
}
#match-result .erg-buehne[hidden] { display: none !important; }
#match-result .erg-buehne canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
#match-result .erg-weg-schild {
    position: absolute; right: 8%; bottom: 14px; padding: 4px 10px; border-radius: 999px;
    font: 700 11px system-ui, sans-serif; color: var(--n-dim); letter-spacing: .03em;
    background: rgba(9, 12, 16, .82); border: 1px solid var(--n-line);
}
#match-result .erg-neu { display: none; }
#match-result.erg-weg .erg-neu { display: block; }
#match-result.erg-weg { justify-content: flex-start !important; gap: 10px; }
#match-result.erg-weg .mk-urteil { align-self: center; }
/* Lange Urteile ("Sieg – Gegner hat aufgegeben") einzeilig auf dem iPhone 13 - in Karte und Ergebnis. */
#match-karte .mk-urteil.lang, #match-result .mk-urteil.lang { font-size: 14px; letter-spacing: .02em; padding: 7px 14px; }
#match-result.erg-weg #match-result-text { font-size: 14px !important; color: var(--n-fg) !important; margin: 4px 0 2px !important; }

/* =========================================================
   DISZIPLIN-FILTER (v7.40, 55-duellmodi.js): die Schalterreihe im Fenster
   "Gegner suchen". Angeschaltet in der Farbe des eigenen Lichts (cyan),
   aus nur als Umriss; darunter eine leise Zeile.
   ========================================================= */
.duell-modi { margin: 0 0 4px; }
.duell-modi[hidden] { display: none; }
.dm-reihe { display: flex; flex-wrap: wrap; gap: 6px; }
.dm-schalter {
    flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: center; gap: 5px;
    width: auto; margin: 0;            /* die allgemeine button-Regel setzt width: 100% */
    min-height: 36px; padding: 6px 10px; border-radius: 999px; cursor: pointer;
    font: 700 12px system-ui, sans-serif; color: var(--n-dim);
    background: transparent; border: 1px solid var(--n-line);
    transition: background-color .15s, border-color .15s, color .15s;
}
.dm-schalter span { font-size: 14px; line-height: 1; filter: grayscale(1); opacity: .6; }
.dm-schalter.an { color: var(--n-fg); background: rgba(0, 229, 255, .10); border-color: rgba(0, 229, 255, .55);
                  box-shadow: 0 0 12px -5px rgba(0, 229, 255, .7); }
.dm-schalter.an span { filter: none; opacity: 1; }
/* "Zufaellig" ueber die ganze Breite, die Disziplinen darunter - seit
   v7.41 sechs, also zwei Reihen zu drei. */
.dm-schalter.dm-zufall { flex-basis: 100%; }
.dm-schalter:not(.dm-zufall) { flex: 1 1 calc(33.333% - 6px); padding: 6px 3px; gap: 4px; font-size: 11.5px; white-space: nowrap; }
/* Die gewaehlte Spielart oben - wie ihre Karte, aber nicht mehr antippbar. */
#match-modi .mm-gewaehlt { cursor: default; pointer-events: none; margin-bottom: 14px; }
#match-modi .mm-gewaehlt[hidden] { display: none; }
/* "Los!" - die Hauptsache des Schritts, in der Farbe des eigenen Lichts; aus, solange nichts gewaehlt ist. */
/* Mit ID-Selektor: die allgemeine Knopfregel im Fenster (.modal-box .action-btn) setzt die Flaeche mit !important. */
#match-modi .dm-los { width: 100%; margin-top: 14px; letter-spacing: .04em;
    background: var(--n-zug) !important; border-color: var(--n-zug) !important; color: #04171C !important;
    box-shadow: 0 8px 26px -10px rgba(0, 229, 255, .8); }
#match-modi .dm-los:hover:not([disabled]) { background: #4de8ff !important; border-color: #4de8ff !important; }
#match-modi .dm-los:disabled { background: rgba(148, 163, 184, .14) !important; border-color: var(--n-line) !important;
    color: var(--n-dim2) !important; cursor: default; box-shadow: none; }
.dm-hinweis { min-height: 15px; margin: 6px 2px 2px; font: 600 11px system-ui, sans-serif; color: var(--n-dim); text-align: left; }

/* DER TEXT UEBER DEM ERSTEN KNOPF (v7.40) bei "Freund per Code" und
   "Turnier". Stephan: "komisch ausgerichtet. Bitte ordentlich
   zentrieren" - er erbte die Ausrichtung des Fensters und brach links
   buendig in ungleich lange Zeilen. Jetzt mittig, mit begrenzter
   Zeilenlaenge und ausgeglichenen Umbruechen. */
.mm-intro {
    font-size: 12.5px; line-height: 1.45; color: var(--n-dim);
    text-align: center; text-wrap: balance;
    max-width: 34ch; margin: 2px auto 14px;
}

/* =========================================================
   GEWICHTHEBEN (v7.41, 56-heben.js): die Ansicht im Duell. Das Bild
   nimmt die ganze Breite; die Zeile darunter faerbt sich mit der
   laufenden Quote (data-ton wie die Rueckmeldungen der anderen
   Disziplinen).
   ========================================================= */
.heben-ansicht { text-align: center; }
.heben-countdown { font-size: 48px; font-weight: 800; color: var(--n-gold); min-height: 0; line-height: 1.1; }
.heben-countdown:empty { display: none; }
.heben-meta { font: 700 13px system-ui, sans-serif; color: var(--n-fg); margin: 2px 0 8px; font-variant-numeric: tabular-nums; }
.heben-buehne { border: 1px solid var(--n-line); border-radius: 12px; overflow: hidden; background: var(--n-bg);
                touch-action: none; -webkit-tap-highlight-color: transparent; user-select: none; -webkit-user-select: none; }
.heben-buehne canvas { display: block; width: 100%; touch-action: none; }
.heben-stand { font: 700 13px system-ui, sans-serif; color: var(--n-dim); margin-top: 8px; min-height: 18px; font-variant-numeric: tabular-nums; }
.heben-stand[data-ton="gut"] { color: #50E38C; }
.heben-stand[data-ton="schlecht"] { color: #FF8C5A; }
.heben-gegner { font: 600 12px system-ui, sans-serif; color: var(--n-dim); margin-top: 3px; min-height: 16px; }

/* =========================================================
   BOT-GEGNER (v7.42): dezent gekennzeichnet - ein kleines graues "Bot".
   Vor dem Namen (data-bot, ::before), weil Kopf und Tafel lange Namen
   hinten mit "…" abschneiden; in der Turniertabelle als eigenes Feld.
   ========================================================= */
[data-bot]::before, .bot-marke {
    content: 'Bot';
    display: inline-block; vertical-align: 0.12em;
    margin-right: 5px; padding: 1px 5px 0; border-radius: 6px;
    font: 700 9px/1.4 system-ui, sans-serif; letter-spacing: .04em; text-transform: none;
    color: var(--n-dim); background: rgba(148, 163, 184, .14); border: 1px solid var(--n-line);
}

/* HILFE-FENSTER (v7.50). Stephan: "im hilfe popup ist die unterzeile der
   Ueberschrift seltsam ausgerichtet. bitte auf volle breite in eine zeile
   und zentrieren". .modal-box p begrenzt Absaetze auf 34ch und zentriert
   sie ueber margin auto; die Unterzeile hatte margin:0 im style-Attribut
   und stand deshalb schmal und links. tools/hilfe-fenster.test.js */
.modal-box p.hilfe-unter { max-width: none; margin: 0 0 12px; text-align: center; white-space: nowrap; }

/* =========================================================
   HANDY-RAHMEN AUF DEM PC (v7.46)
   Stephan: "der spielbildschirm soll auf dem pc umrandet sein (soll ein
   smartphone simulieren bzw darstellen)" - Entwurf B (schwarzes
   Gehaeuse, runde Ecken, Kamera-Insel, Seitenknoepfe), "so breit wie
   jetzt": das Bild bleibt 520 px breit.
   Nur im Browser-Tab (html.im-browser, 06c-athlete.js - also nicht in
   der App und nicht in der Fassung fuer itch.io/Game Jolt) mit Maus und
   genug Platz; Handys, Tablets und schmale Fenster bleiben wie bisher.
   Der Body IST das Handy: sein Rand ist das Gehaeuse, transform macht
   ihn zum Bezugsrahmen fuer position:fixed - jedes Fenster
   (.modal-overlay mit inset:0) legt sich so nur ueber das Handy. --sh ist
   ein Hundertstel der Bildhoehe; alle Hoehen im Stil rechnen damit statt
   mit vh/dvh (ohne Rahmen gilt der Rueckfall 1vh bzw. 1dvh), JS misst mit
   schirmUnten() (14-ui.js). Insel und Knoepfe haengen an html::before und
   ::after - im Rand des Body schnitte overflow:hidden sie weg.
   tools/handy-rahmen.test.js
   ========================================================= */
@media (min-width: 700px) and (min-height: 600px) and (hover: hover) and (pointer: fine) {
    html.im-browser {
        --hr-luft: 18px;      /* ueber und unter dem Handy */
        --hr-rand: 13px;      /* Gehaeuse links, rechts und unten */
        --hr-oben: 34px;      /* Gehaeuse oben, darin die Kamera-Insel */
        --hr-breite: 520px;   /* das Bild, so breit wie bisher */
        --sh: calc((100dvh - 2 * var(--hr-luft) - var(--hr-oben) - var(--hr-rand)) / 100);
        height: 100%;
        overflow: hidden;
        background: var(--n-bg);
    }
    html.im-browser body {
        box-sizing: content-box !important;
        width: var(--hr-breite);
        height: calc(100 * var(--sh));
        min-height: 0 !important;
        margin: var(--hr-luft) auto !important;
        border: var(--hr-rand) solid #0A0B0D;
        border-top-width: var(--hr-oben);
        /* oben gleicht die hoehere Kante aus, damit die Ecken des Bildes
           ueberall gleich rund sind */
        border-radius: 50px 50px 50px 50px / 66px 66px 50px 50px;
        overflow: hidden;
        transform: translateZ(0);
        box-shadow: 0 0 0 2px #3A3F47, 0 0 0 3px #16191E, 0 24px 70px rgba(0, 0, 0, 0.65);
    }
    /* Das Spiel fuellt das Handy - ohne die 30 px Abstand, die
       .game-container.in-game sonst gegen die Browserleisten haelt. */
    html.im-browser .game-container { height: 100% !important; max-height: 100% !important; }
    /* Bildlaufleisten schmal und dunkel wie auf dem Handy statt der breiten
       des PCs; das Mausrad scrollt wie bisher. */
    html.im-browser body, html.im-browser body * { scrollbar-width: thin; scrollbar-color: rgba(148, 163, 184, 0.35) transparent; }
    html.im-browser::before {
        content: ''; position: fixed; z-index: 2147483647; pointer-events: none;
        left: 50%; width: 92px; height: 14px; margin-left: -46px;
        top: calc(var(--hr-luft) + (var(--hr-oben) - 14px) / 2);
        border-radius: 99px;
        background: radial-gradient(circle at 74px 7px, #2A3A55 0 2.5px, #121A26 3px, transparent 4px), #000;
        box-shadow: inset 0 0 0 1px #22262D;
    }
    /* links laut und leise, rechts Ein/Aus */
    html.im-browser::after {
        content: ''; position: fixed; pointer-events: none;
        left: calc(50% - var(--hr-breite) / 2 - var(--hr-rand) - 7px);
        top: calc(var(--hr-luft) + 150px);
        width: 4px; height: 56px; border-radius: 2px; background: #2D3239;
        box-shadow: 0 72px 0 #2D3239,
                    calc(var(--hr-breite) + 2 * var(--hr-rand) + 10px) 30px 0 #2D3239;
    }
}
