/* ==========================================================================
 * Das hidden-Attribut durchsetzen. Es ist in dieser Lobby das einzige Mittel
 * fuer Sichtbarkeit — jede Autorenregel mit display wuerde es sonst schlagen.
 * ========================================================================== */
[hidden] {
	display: none !important;
}

/* ============================================================================
 * INFERNUS Blackjack — lobby.css
 *
 * Mobil zuerst: entworfen fuer 412x915 CSS-Pixel im Hochformat, danach nach
 * oben skaliert. Alles bis Abschnitt 12 gilt fuer das Telefon.
 *
 * Die Blickfuehrung laeuft von oben nach unten und hat genau drei Stationen:
 *   1. Wer du bist   — Name und Rang, ruhig
 *   2. Wo du stehst  — Stufe und Ziel, der Balken laeuft hoch
 *   3. Was du tust   — EIN glutfarbener Knopf, unten im Daumenbereich angedockt
 * Alles Weitere (Einladungen, Tische) ordnet sich darunter ein.
 *
 * Aufbau: 1 Token · 2 Grundlagen · 3 Kopf · 4 Hero/Dock · 5 Fortschritt
 *         6 Neuigkeiten · 7 Tische · 10 Dialoge/Toasts · 11 Skelette
 *         12 Breite Schirme · 14 Saison
 *
 * Die Luecken in der Nummerierung sind Absicht: 8, 9 und 13 trugen Ranglisten,
 * Freunde und Turniere, die inzwischen eigene Seiten haben. Die Nummern der
 * uebrigen Abschnitte bleiben, damit Verweise aus Kommentaren gueltig bleiben;
 * an Stelle 8 steht, wohin die Regeln gegangen sind.
 *
 * Abschnitt 14 steht hinter den Medienabfragen und bringt seine eigenen mit.
 * ==========================================================================*/

/* ==========================================================================
   1 — TOKEN (Spiegel der Marke; die Lobby laedt game.css nicht)
   ========================================================================== */
:root {
	--bg: #141419;
	--bg-sunk: #0e0e12;
	--bg-raised: #1c1c23;
	--bg-panel: #21212a;
	--line: #34343f;
	--line-soft: #26262f;

	--text: #f7f7f7;
	--text-2: #b9b9c4;
	/* War #85858f. Auf --bg-panel (Dialogflaeche) waren das 4,37:1, auf
	   --bg-raised 4,64:1 — der leise Ton traegt aber .btn--quiet, .tile__label
	   und .tile__hint, also echten Text unter 4,5:1. #94949e liegt bei 5,31:1
	   auf --bg-panel und bleibt klar leiser als --text-2. */
	--text-3: #94949e;
	--text-ink: #17171d;

	--accent: #ff7a00;
	--accent-lit: #ffb45b;
	--accent-deep: #b34e00;
	--accent-glow: rgb(255 122 0 / 0.38);
	--accent-veil: rgb(255 122 0 / 0.12);

	--felt: #123a2c;
	--felt-lit: #1a5040;

	--win: #35c07a;
	--lose: #e2483c;
	/* --lose taugt als Rand und Flaeche, nicht als Schrift: auf --bg-panel
	   (Dialog) 3,97:1 und auf --bg-raised (Kachel) 4,22:1. Dieser Ton traegt
	   6,29:1 beziehungsweise 6,67:1. */
	--lose-lit: #ff7a70;
	--info: #4aa3ff;
	--warn: #ffb020;

	/* Vom Server gelieferte Rangfarbe; bis dahin die Glut. */
	--tier: var(--accent);

	--sp-1: 4px;
	--sp-2: 8px;
	--sp-3: 12px;
	--sp-4: 16px;
	--sp-5: 24px;
	--sp-6: 32px;
	--sp-7: 48px;

	--r-1: 6px;
	--r-2: 10px;
	--r-3: 16px;
	--r-4: 22px;

	/* Sichere Zonen des Geraets. Ohne Fallback waere der Wert leer. */
	--safe-b: env(safe-area-inset-bottom, 0px);
	--safe-t: env(safe-area-inset-top, 0px);
	--safe-l: env(safe-area-inset-left, 0px);
	--safe-r: env(safe-area-inset-right, 0px);

	/* Hoehe des angedockten Hauptknopfs — der Fuss haelt so viel Platz frei.
	   Nur der Startwert bis syncDockHeight() gemessen hat. War 132px, als ueber
	   dem Knopf noch ein Hinweis stand; der steht jetzt oben in der Antwortzeile,
	   der Dock ist eine Zeile niedriger. Ein zu hoher Startwert riss beim ersten
	   Bildaufbau ein Loch unter den Fuss. */
	--dock-h: 100px;

	--font: 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
	--ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ==========================================================================
   2 — GRUNDLAGEN
   ========================================================================== */
*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
}

body.lobby {
	margin: 0;
	background: var(--bg);
	color: var(--text);
	font-family: var(--font);
	font-size: 16px;
	line-height: 1.5;
	/* Der angedockte Knopf verdeckt sonst den Fuss. */
	padding-bottom: calc(var(--dock-h) + var(--safe-b));
	overflow-x: hidden;
}

/*
 * Unten liegen jetzt ZWEI Dinge uebereinander: die Leiste und darueber der
 * Dock. Beide Reserven muessen sich addieren, sonst verschwindet das Seitenende
 * darunter.
 *
 * Die hoehere Spezifitaet ist Absicht und kein Zufall. nav.js setzt seinerseits
 * `body.has-ifb-nav { padding-bottom: … }` — gleiche Spezifitaet wie `body.lobby`,
 * also haette die Reihenfolge im Dokument entschieden, und die entsteht erst zur
 * Laufzeit, weil nav.js seinen Stil beim Einhaengen einspritzt. Genau daran ist
 * die Reserve bisher zerbrochen: die Leiste gewann mit ihren 72 px, obwohl der
 * Dock 132 px hoch ist. Mit `body.lobby.has-ifb-nav` entscheidet die Regel, nicht
 * die Ladereihenfolge.
 *
 * Kein --safe-b im Term: den bringt --ifb-nav-h bereits mit.
 *
 * Die Formel deckt alle drei Groessenbereiche ohne Sonderfall ab, weil beide
 * Variablen sich selbst zuruecknehmen — ab 700 px wird --dock-h zu 0 (der Knopf
 * geht zurueck in den Lesefluss), ab 900 px --ifb-nav-h (die Leiste wandert nach
 * oben). Medienabfragen erhoehen die Spezifitaet nicht, deshalb braucht diese
 * Regel keine Entsprechung weiter unten.
 */
body.lobby.has-ifb-nav {
	padding-bottom: calc(var(--dock-h) + var(--ifb-nav-h, 0px));
}

/* Ein ruhiger Glutschimmer am oberen Rand — Stimmung, kein Effekt. */
body.lobby::before {
	content: '';
	position: fixed;
	inset: 0 0 auto 0;
	height: 40dvh;
	background: radial-gradient(120% 100% at 50% 0%, rgb(255 122 0 / 0.13), transparent 70%);
	pointer-events: none;
	z-index: 0;
}

h1,
h2,
h3,
h4,
p,
ul,
ol,
dl,
dd,
figure {
	margin: 0;
	padding: 0;
}

ul,
ol {
	list-style: none;
}

a {
	color: var(--accent-lit);
	text-decoration: none;
}

a:hover {
	text-decoration: underline;
}

button,
input,
select {
	font: inherit;
	color: inherit;
}

/* Zahlen laufen nie: gleiche Ziffernbreite ueberall. */
.tabnum,
.tabnum * {
	font-variant-numeric: tabular-nums;
	font-feature-settings: 'tnum' 1;
}

:focus-visible {
	outline: 2px solid var(--accent-lit);
	outline-offset: 2px;
	border-radius: var(--r-1);
}

.sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.skiplinks a {
	position: absolute;
	left: -9999px;
	top: 0;
	/* 700: UEBER der gemeinsamen Kopfzeile (z-index 500) und ueber ihrem
	   Profilkasten (600), aber unter dem Spielerschutz (9800/9900).

	   DER SCHADEN, den diese Zahl verhindert: Die Kopfzeile klebt seit dem
	   Umbau oben am Fensterrand. Der Sprunglink steht bei top: 0 im selben
	   Bereich — mit einer kleineren Zahl lag er beim Fokussieren HINTER der
	   Leiste. Ein Sprunglink, den man nicht sieht, ist fuer den, der ihn
	   braucht, keiner: Der Vorleser nennt ihn, der Bildschirm zeigt nichts,
	   und der Nutzer weiss nicht, worauf sein Fokus steht. Die Zahl stand hier
	   in sechs Fassungen (10, 90, 100, 300, 500, 900) — dieselbe Krankheit wie
	   bei der Kopfzeile, nur leiser. */
	z-index: 700;
}

.skiplinks a:focus {
	left: var(--sp-3);
	top: var(--sp-3);
	padding: var(--sp-2) var(--sp-3);
	background: var(--accent);
	color: var(--text-ink);
	border-radius: var(--r-1);
}

/* Die sicheren Zonen standen vertauscht: rechts lag der linke Wert und links
   der rechte. Quer am Telefon mit einseitiger Kerbe schob das den Inhalt
   genau auf die falsche Seite — unter die Kerbe statt daneben. */
.wrap {
	position: relative;
	z-index: 1;
	width: 100%;
	max-width: 560px;
	margin: 0 auto;
	padding: 0 calc(var(--sp-4) + var(--safe-r)) 0 calc(var(--sp-4) + var(--safe-l));
}

/* Grosszuegige Abstaende statt Kaesten: die Ruhe kommt aus dem Weissraum. */
.sec {
	margin: 0 0 var(--sp-7) 0;
}

.sec__title {
	margin: 0 0 var(--sp-3) 0;
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--text-3);
}

.sec__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sp-3);
	margin-bottom: var(--sp-3);
}

.sec__head .sec__title {
	margin-bottom: 0;
}

.sec__meta {
	font-size: 0.8rem;
	color: var(--text-3);
}

/*
 * Hier stand .sub — die Zwischenueberschrift von "Offene Anfragen" und
 * "Weitere Termine". Beide sind mit den Freundes- und Turnierabschnitten auf
 * eigene Seiten gezogen; die Regel blieb liegen und ist niemandem aufgefallen,
 * bis tools/lobby-dom.js die Gegenrichtung mitprueft.
 */

.empty {
	padding: var(--sp-4) 0;
	font-size: 0.9rem;
	color: var(--text-3);
}

.warnline {
	margin-top: var(--sp-3);
	padding: var(--sp-3);
	border-left: 3px solid var(--warn);
	background: rgb(255 176 32 / 0.08);
	font-size: 0.88rem;
	color: var(--text-2);
}

/* ==========================================================================
   3 — KOPF
   ----------------------------------------------------------------------------
   HIER STANDEN .topbar, .brand, .brand__mark, .brand__sub, .purse, .purse__val
   und .purse__unit. Sie sind mit ihrem Markup gegangen: Die Kopfzeile erzeugt
   und gestaltet jetzt web/kopf.js, in EINER Datei.

   Der Schaden, den das abstellt: Dieselben sieben Klassen standen in sieben
   Stylesheets, jedes Mal ein wenig anders — die Wortmarke in fuenf Groessen
   und sechs Laufweiten, der Untertitel mit je einem anderen Wort. Der Nutzer
   las das als "auf jeder Seite ein anderes Logo". Wer hier wieder eine
   .topbar-Regel einsetzt, gestaltet ein Markup, das diese Seite nicht mehr
   erzeugt — genau der Riss aus Regel 2.
   ========================================================================== */

/* ==========================================================================
   4 — DIE ANTWORT UND DER ANGEDOCKTE HAUPTKNOPF
   ----------------------------------------------------------------------------
   Hier stand bis eben der Hero mit Begruessung, Anzeigename (28 px) und
   Rangchip. Der Rangchip ist zum Fortschritt gewandert, der Name ganz weg —
   profil.js schreibt ihn seit heute in die Kopfzeile, die groesste Schrift der
   Seite war also eine woertliche Wiederholung. An seiner Stelle steht die
   Antwort auf die einzige Frage dieser Seite.
   ========================================================================== */
.sec--hero {
	padding-top: var(--sp-5);
	margin-bottom: var(--sp-6);
}

/*
 * Der Antwortblock: Tageszeit, Antwort, Zusatz als eine Einheit.
 *
 * Die Breitenbegrenzung ist kein Zierrat. Ab 1000 px ist die Spalte 456 px
 * breit, ab 700 px die ganze Bahn 680 px — eine 1.9rem-Zeile ueber diese Breite
 * zwingt das Auge, am Zeilenende den Anfang der naechsten zu suchen. Auf dem
 * Telefon (Spalte rund 380 px) greift der Wert nicht und aendert nichts.
 */
.lead {
	max-width: 26rem;
}

/* Die Tageszeit als leise Zeile ueber der Antwort — Waerme, kein Wettbewerb. */
.lead__eyebrow {
	font-size: 0.9rem;
	color: var(--text-3);
}

/*
 * Die groesste Zeile der Seite. Sie traegt Tischnamen aus fremder Hand (bis 32
 * Zeichen ohne Leerzeichen), die bei 24 Pixeln rund 390 Pixel messen — in einer
 * 380 Pixel breiten Spalte liefe das ohne Umbruchregel aus dem Bild.
 *
 * Bewusst 1.5rem und nicht groesser: der Knopf unten ist das lauteste OBJEKT
 * der Seite, diese Zeile der lauteste TEXT. Zwei gleich grosse Anker waren
 * genau das Problem, das hier behoben wird.
 */
.lead__line {
	margin-top: 2px;
	font-size: 1.5rem;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.01em;
	overflow-wrap: anywhere;
}

/* Der Tischname in der Antwort: dorthin faellt der Blick zuerst. */
.lead__line b {
	color: var(--accent-lit);
	font-weight: 800;
}

.lead__sub {
	margin-top: var(--sp-2);
	font-size: 0.92rem;
	color: var(--text-2);
}

/* Zwei der drei Wege in ein Spiel haengen an diesen beiden Knoepfen. Mit
   8 Pixeln Polsterung waren sie 40 Pixel hoch — unter dem Daumenmass. */
.linkbtn {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: var(--sp-2) 0;
	background: none;
	border: 0;
	color: var(--text-2);
	text-decoration: underline;
	text-underline-offset: 3px;
	cursor: pointer;
}

.linkbtn:hover {
	color: var(--accent-lit);
}

/*
 * Der Dock. Auf dem Telefon ist er aus dem Fluss genommen und klebt unten —
 * genau dort, wo der Daumen ohne Umgreifen hinkommt. Der Rumpf haelt mit
 * padding-bottom denselben Platz frei, damit nichts dauerhaft verdeckt wird.
 */
.dock {
	position: fixed;
	left: 0;
	right: 0;
	/*
	 * ÜBER der Navigation, nicht auf ihr. Beide klebten am unteren Rand, und
	 * ein hoeherer z-index waere die falsche Reparatur gewesen: dann verdeckt
	 * der Knopf die Navigation. nav.js misst seine Leiste und veroeffentlicht
	 * die Hoehe als --ifb-nav-h; fehlt die Leiste (am Tisch) oder sitzt sie
	 * oben (ab 900px), ist der Wert 0 und der Knopf faellt an den Rand zurueck.
	 */
	bottom: var(--ifb-nav-h, 0px);
	z-index: 30;
	padding: var(--sp-3) calc(var(--sp-4) + var(--safe-r)) calc(var(--sp-3) + var(--safe-b))
		calc(var(--sp-4) + var(--safe-l));
	background: linear-gradient(to top, var(--bg) 62%, rgb(20 20 25 / 0));
	pointer-events: none;
}

/*
 * Sitzt der Dock ueber der Leiste, beruehrt er die Geraetekante nicht mehr —
 * und die Leiste hat den Sicherheitsabstand schon in ihrer Hoehe. Ohne diese
 * Zeile stuende er ein zweites Mal im Dock und risse auf einem iPhone rund
 * 34 px Luft zwischen Knopf und Leiste.
 */
body.has-ifb-nav .dock {
	--safe-b: 0px;
}

.dock__inner {
	width: 100%;
	max-width: 560px;
	margin: 0 auto;
	pointer-events: auto;
}

/* Das groesste Element der Seite. Genau eines. */
.cta {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: 68px;
	padding: var(--sp-4) var(--sp-5);
	background: linear-gradient(180deg, var(--accent-lit) 0%, var(--accent) 45%, var(--accent-deep) 100%);
	color: #241000;
	border: 0;
	border-radius: var(--r-4);
	font-size: 1.2rem;
	font-weight: 800;
	letter-spacing: 0.01em;
	text-align: center;
	text-decoration: none;
	box-shadow:
		0 8px 24px rgb(0 0 0 / 0.45),
		0 0 0 1px rgb(255 180 91 / 0.3) inset,
		0 0 28px var(--accent-glow);
	transition:
		transform 120ms var(--ease),
		box-shadow 200ms var(--ease);
}

.cta:hover {
	text-decoration: none;
}

.cta:active {
	transform: translateY(2px) scale(0.99);
	box-shadow:
		0 4px 14px rgb(0 0 0 / 0.45),
		0 0 0 1px rgb(255 180 91 / 0.3) inset;
}

.cta[aria-disabled='true'] {
	opacity: 0.6;
	pointer-events: none;
}

/*
 * Ein einmaliger, langsamer Glutpuls, sobald der Knopf zum ersten Mal steht.
 * Er laeuft dreimal und hoert dann auf — Aufmerksamkeit, kein Dauerflackern.
 */
.cta[data-fresh='1'] {
	animation: ctaPulse 2.4s var(--ease) 3;
}

@keyframes ctaPulse {
	0%,
	100% {
		box-shadow:
			0 8px 24px rgb(0 0 0 / 0.45),
			0 0 0 1px rgb(255 180 91 / 0.3) inset,
			0 0 28px var(--accent-glow);
	}
	50% {
		box-shadow:
			0 8px 24px rgb(0 0 0 / 0.45),
			0 0 0 1px rgb(255 180 91 / 0.45) inset,
			0 0 44px rgb(255 122 0 / 0.6);
	}
}

/* ==========================================================================
   5 — FORTSCHRITT
   ----------------------------------------------------------------------------
   Der Hinweis .cta__note stand bis eben zwischen Dock und Knopf. Er ist mit
   seinem Markup gegangen (siehe Abschnitt 4) — eine Regel ohne Markup sieht
   beim naechsten Blick wie ein unterstuetztes Vokabular aus.
   ========================================================================== */
.prog {
	display: flex;
	flex-direction: column;
	gap: var(--sp-5);
}

/*
 * Der Rangchip. Er stand im Kopf der Seite und rang dort mit Anzeigename und
 * Begruessung um denselben Blick; er beantwortet aber "wo stehe ich", nicht
 * "woran spiele ich". Jetzt ist er das erste Kind von .prog.
 *
 * align-self ist hier Pflicht: .prog ist eine Spalte mit align-items: stretch,
 * und eine gestreckte Pille zoege sich ueber die ganze Breite. Der eigene
 * margin-top faellt weg, den Abstand macht die Spalte selbst (gap).
 */
.tierchip {
	display: inline-flex;
	align-self: flex-start;
	align-items: center;
	gap: var(--sp-2);
	padding: 5px var(--sp-3) 5px var(--sp-2);
	background: color-mix(in srgb, var(--tier) 14%, transparent);
	border: 1px solid color-mix(in srgb, var(--tier) 45%, transparent);
	border-radius: 999px;
	font-size: 0.82rem;
}

.tierchip__dot {
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: var(--tier);
	box-shadow: 0 0 10px color-mix(in srgb, var(--tier) 70%, transparent);
}

/* Die Rangfarbe kommt vom Server. Die unterste Stufe "Asche" ist #7c7a8a und
   traegt als Schrift nur 4,38:1 auf dem Grund — und in ihr faengt jeder an.
   18 Prozent Weiss heben alle sechs Stufen ueber 5,5:1, ohne dass die Farbe
   ihren Charakter verliert. Punkt und Rahmen bleiben auf dem reinen Wert. */
.tierchip__name {
	font-weight: 700;
	color: var(--tier);
	color: color-mix(in srgb, var(--tier) 82%, #ffffff);
	letter-spacing: 0.02em;
}

.tierchip__val {
	color: var(--text-3);
}

.track__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sp-3);
	margin-bottom: var(--sp-2);
}

.track__label {
	font-size: 1rem;
	font-weight: 600;
}

.track__label b {
	font-weight: 800;
	color: var(--accent-lit);
}

.track__meta {
	font-size: 0.82rem;
	color: var(--text-3);
}

/* Die Distanz zum Ziel — die wichtigere Zahl, deshalb steht sie ausgeschrieben. */
.track__goal {
	margin-top: var(--sp-2);
	font-size: 0.88rem;
	color: var(--text-2);
}

.bar {
	position: relative;
	height: 12px;
	background: var(--bg-sunk);
	border: 1px solid var(--line-soft);
	border-radius: 999px;
	overflow: hidden;
}

.bar--slim {
	height: 8px;
}

/*
 * Der Fuellstand startet bei 0 und laeuft auf seinen Wert hoch. lobby.js setzt
 * die Breite erst nach dem ersten Bildaufbau, damit der Uebergang wirklich
 * laeuft — ein fertig dastehender Balken erzaehlt keinen Fortschritt.
 */
.bar__fill {
	display: block;
	width: 0;
	height: 100%;
	background: linear-gradient(90deg, var(--accent-deep), var(--accent) 55%, var(--accent-lit));
	border-radius: inherit;
	box-shadow: 0 0 14px var(--accent-glow);
	transition: width 1100ms var(--ease);
}

.rankline {
	font-size: 0.95rem;
	color: var(--text-2);
}

.rankline b {
	color: var(--text);
	font-weight: 700;
}

.tiles {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--sp-2);
}

.tile {
	padding: var(--sp-3) var(--sp-2);
	background: var(--bg-raised);
	border: 1px solid var(--line-soft);
	border-radius: var(--r-2);
	text-align: center;
}

/* Drei Kacheln nebeneinander lassen bei 412 Pixeln 105 Pixel Textbreite.
   "ENTSCHEIDUNGSQUOTE" misst dort rund 129 und ist ein einziges Wort — ohne
   Trennung lief es ueber die Nachbarkachel hinaus. lang="de" steht am
   Dokument, also trennt der Browser sinnvoll; der harte Umbruch ist nur die
   Rueckfallebene. */
.tile__label {
	font-size: 0.68rem;
	line-height: 1.25;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--text-3);
	hyphens: auto;
	overflow-wrap: break-word;
}

.tile__val {
	margin: var(--sp-2) 0 0 0;
	font-size: 1.15rem;
	font-weight: 700;
}

.tile__val[data-tone='good'] {
	color: var(--win);
}

.tile__val[data-tone='bad'] {
	color: var(--lose-lit);
}

/* Der Hinweis ist Beiwerk: auf dem Telefon kostet er nur Platz. */
.tile__hint {
	display: none;
}

/* ==========================================================================
   6 — NEUIGKEITEN UND EINLADUNGEN
   ========================================================================== */
.newslist,
.invlist {
	display: flex;
	flex-direction: column;
	gap: var(--sp-2);
}

.newsitem {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	padding: var(--sp-3);
	background: linear-gradient(90deg, var(--accent-veil), transparent 60%), var(--bg-raised);
	border: 1px solid var(--line-soft);
	border-left: 3px solid var(--accent);
	border-radius: var(--r-2);
	/* Neue Ereignisse gleiten einmal herein. */
	animation: newsIn 420ms var(--ease) both;
}

@keyframes newsIn {
	from {
		opacity: 0;
		transform: translateY(6px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

.newsitem__icon {
	flex: none;
	width: 32px;
	height: 32px;
	display: grid;
	place-items: center;
	background: var(--bg-sunk);
	border-radius: 50%;
	font-size: 1rem;
}

.newsitem__body {
	flex: 1 1 auto;
	min-width: 0;
}

.newsitem__title {
	display: block;
	font-size: 0.92rem;
	font-weight: 700;
}

.newsitem__text {
	display: block;
	font-size: 0.82rem;
	color: var(--text-2);
}

.newsitem__act {
	flex: none;
}

.invcard {
	padding: var(--sp-3);
	background: var(--bg-raised);
	border: 1px solid var(--line);
	border-radius: var(--r-2);
}

.invcard__title {
	font-weight: 700;
}

.invcard__meta {
	margin-top: 2px;
	font-size: 0.82rem;
	color: var(--text-3);
}

.invcard__actions {
	display: flex;
	gap: var(--sp-2);
	margin-top: var(--sp-3);
}

/* Der Knopf unter der Liste, der die uebrigen Einladungen aufklappt. Leise und
   in voller Breite: er ist eine Auskunft ueber die Anzahl, keine Aufforderung.
   Ohne ihn (und ohne den Deckel in renderInvites) wuchs der Abschnitt nach oben
   unbegrenzt und drueckte die Tischliste aus dem ersten Bildschirm. */
.invmore {
	width: 100%;
	margin-top: var(--sp-2);
}

/* ==========================================================================
   7 — TISCHE
   ========================================================================== */
/*
 * HIER STANDEN .tgroup, .tgroup__title UND .tgroup__note.
 * Sie gestalteten die beiden Zwischenueberschriften "Casual" und "Ranked". Die
 * Gruppen sind entfallen — die Art des Tisches steht als Abzeichen auf der
 * Karte selbst, die Ueberschrift sagte dasselbe ein zweites Mal, und sechs
 * Zeilen Geruest fuer ein bis zwei Karten je Gruppe waren der Grund, warum die
 * Liste unuebersichtlich wirkte.
 *
 * Die Regeln gehen mit ihrem Markup. Regeln ohne Markup sehen beim naechsten
 * Lesen wie ein unterstuetztes Vokabular aus, und genau daraus ist in dieser
 * Datei schon einmal der Bruch entstanden, bei dem 47 von 65 Klassen ohne
 * Regel dastanden.
 */
.tlist {
	display: flex;
	flex-direction: column;
	gap: var(--sp-3);
}

/* 12 statt 16 Pixel Polsterung. Klingt nach Kleinigkeit, sind bei drei Karten
   24 Pixel — und der erste Bildschirm hat nach Kopfzeile, Sitzungsuhr und Dock
   nur rund 484 Pixel fuer die Liste uebrig. */
.tcard {
	padding: var(--sp-3);
	background: var(--bg-raised);
	border: 1px solid var(--line-soft);
	border-radius: var(--r-3);
	transition:
		border-color 160ms var(--ease),
		transform 160ms var(--ease);
}

.tcard:hover {
	border-color: var(--line);
	transform: translateY(-1px);
}

/* Der eigene Tisch hebt sich ab — dorthin will man zurueck. */
.tcard[data-mine='1'] {
	border-color: color-mix(in srgb, var(--accent) 55%, transparent);
	background: linear-gradient(180deg, var(--accent-veil), transparent 40%), var(--bg-raised);
}

.tcard[data-full='1'] {
	opacity: 0.62;
}

.tcard__top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-3);
}

/* Der Weg an einen Tisch. Als reiner Textlink war er 25 Pixel hoch und ohne
   Kuerzung: ein 32 Zeichen langer Tischname drueckte die Modusmarke aus der
   Zeile. Jetzt ein 44 Pixel hohes Ziel, das sich beschneidet statt zu
   draengen. */
.tcard__link {
	display: block;
	min-width: 0;
	min-height: 44px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 1.05rem;
	line-height: 44px;
	font-weight: 700;
	color: var(--text);
}

.tcard__link:hover {
	color: var(--accent-lit);
	text-decoration: none;
}

.badge {
	flex: none;
	padding: 3px var(--sp-2);
	border-radius: 999px;
	font-size: 0.66rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.badge[data-mode='casual'] {
	background: color-mix(in srgb, var(--felt-lit) 60%, transparent);
	color: #9fe6c8;
}

.badge[data-mode='ranked'] {
	background: color-mix(in srgb, var(--accent) 20%, transparent);
	color: var(--accent-lit);
}

/* Fuenf Sitzpunkte — Belegung auf einen Blick, ohne Zahl. */
.seats {
	display: flex;
	gap: 6px;
	margin-top: var(--sp-3);
}

.seat {
	width: 100%;
	max-width: 34px;
	height: 7px;
	background: var(--bg-sunk);
	border: 1px solid var(--line-soft);
	border-radius: 999px;
}

.seat[data-taken='1'] {
	background: var(--accent);
	border-color: var(--accent);
	box-shadow: 0 0 8px var(--accent-glow);
}

/* Der eigene Sitz ist heller als die der anderen. */
.seat[data-taken='me'] {
	background: var(--accent-lit);
	border-color: var(--accent-lit);
	box-shadow: 0 0 10px var(--accent-glow);
}

/*
 * Die Angabenzeile traegt jetzt auch "Dein Platz" und "Zuschauen". Beide
 * standen in einer eigenen vierten Zeile (.tcard__foot), die allein 56 Pixel je
 * Karte kostete — bei drei Karten 168 Pixel, mehr als eine ganze Karte, fuer
 * zwei kurze Angaben. Die Zeile ist mit ihrem Markup gegangen.
 */
.tcard__facts {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-2) var(--sp-3);
	margin-top: var(--sp-2);
	font-size: 0.82rem;
	color: var(--text-2);
}

/*
 * Die gemeinsame Grundform beider Angaben. Sie stand bis eben vollstaendig in
 * .fact--phase, weshalb .fact--bets nichts davon erbte und als nackter
 * Inline-Kasten in der Zeile hing: In .tcard__facts (align-items: center)
 * setzte er auf seiner Textgrundlinie auf und stand dadurch rund zwei Pixel
 * tiefer als der Phasenpunkt daneben. Was beide teilen, gehoert in die Basis.
 */
.fact {
	display: inline-flex;
	align-items: center;
}

.fact--phase {
	gap: 6px;
}

.fact--phase::before {
	content: '';
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--text-3);
}

/* Laeuft eine Runde, pulst der Punkt leise mit. */
.fact--phase[data-live='1']::before {
	background: var(--win);
	animation: livePulse 2s ease-in-out infinite;
}

@keyframes livePulse {
	0%,
	100% {
		opacity: 1;
	}
	50% {
		opacity: 0.35;
	}
}

/*
 * "Einsatz 1.000–10.000". Der Halbgeviertstrich ist fuer den Umbruch eine
 * erlaubte Trennstelle, und .tcard__facts ist eine umbrechende Zeile: auf
 * 412 px riss die Spanne hinter dem Strich um, und in der zweiten Zeile stand
 * eine nackte "10.000" — der Mindesteinsatz war weg, der Hoechsteinsatz sah aus
 * wie der ganze Preis. Die laengste Spanne misst rund 150 px und passt damit
 * ungebrochen in die 356 px, die der Karte auf dem Telefon bleiben.
 */
.fact--bets {
	white-space: nowrap;
}

.tcard__you {
	color: var(--accent-lit);
	font-weight: 700;
}

/* Der zweite Weg an denselben Tisch — ebenfalls ein Daumenziel, vorher
   21 Pixel hoch. margin-left schiebt ihn ans Ende der Angabenzeile, seit die
   eigene Fusszeile weg ist. */
.watch {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	margin-left: auto;
	color: var(--text-3);
	text-decoration: underline;
	text-underline-offset: 3px;
}

/*
 * Die beiden Nebenwege unter der Liste. Sie hiessen .hero__more/.hero__sep und
 * standen im Kopfbereich, wo sie 60 Pixel des ersten Bildschirms kosteten,
 * obwohl sie erst gebraucht werden, wenn in der Liste darueber nichts passt.
 * Mit dem Markup ist auch der Name mitgezogen: eine Klasse namens hero__* unter
 * der Tischliste waere eine falsche Faehrte fuer den Naechsten.
 */
.tables__more {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--sp-2);
	margin-top: var(--sp-4);
	font-size: 0.85rem;
}

.tables__sep {
	color: var(--text-3);
}

/* ==========================================================================
   8 — RANGLISTEN, FREUNDE, TURNIERE, AUSSEHEN, GRENZEN: AUSGEZOGEN
   ----------------------------------------------------------------------------
   Diese fuenf Abschnitte hatten hier einmal Regeln. Sie haben seit der
   Navigation eigene Seiten — rangliste/, freunde/, turnier/, shop/ und die
   Einstellungen des Spielerschutzes — und ihr Markup ist mit ihnen gegangen.
   Die Regeln muessen mitgehen, nicht bloss verwaisen.

   Das ist keine Ordnungsliebe. Genau hier lag schon einmal ein Vokabular fuer
   eine Reiterleiste, die lobby.js nicht mehr erzeugte: Regeln ohne Markup, die
   beim naechsten Blick wie ein unterstuetztes Vokabular aussahen. Aus derselben
   Wurzel stammt der Bruch, bei dem 47 von 65 Klassen ohne Regel dastanden und
   der Spieler keine Karten sah. Was kein Markup mehr hat, hat hier auch keine
   Regel mehr — tools/lobby-dom.js prueft beide Richtungen.
   ========================================================================== */

/* ==========================================================================
   10 — KNOEPFE, FORMULARE, DATENKAESTEN, DIALOGE, TOASTS, FUSS
   ----------------------------------------------------------------------------
   Die Formularteile und die Datenkaesten standen bis eben in den Abschnitten 9
   (Freunde) und 13 (Turniere) — nicht weil sie dorthin gehoerten, sondern weil
   sie dort zuerst gebraucht wurden. Beim Ausraeumen dieser Abschnitte gingen
   sie mit, obwohl Dialoge, Einladungen und die Saison sie weiter benutzen:
   elf Klassen ohne Regel, gefunden von tools/lobby-dom.js.

   Sie stehen jetzt dort, wo ihr Gebrauch sie hintraegt — bei den Knoepfen und
   Dialogen, die sie tragen. Wer Abschnitt 14 spaeter ausbaut, nimmt sie nicht
   versehentlich mit.
   ========================================================================== */
.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: var(--sp-2) var(--sp-4);
	background: var(--accent);
	color: var(--text-ink);
	border: 1px solid var(--accent);
	border-radius: var(--r-2);
	font-size: 0.9rem;
	font-weight: 700;
	text-decoration: none;
	cursor: pointer;
}

.btn:hover {
	text-decoration: none;
	background: var(--accent-lit);
	border-color: var(--accent-lit);
}

.btn:disabled {
	opacity: 0.5;
	cursor: default;
}

/* 44 statt 36. Diese Groesse traegt Annehmen und Ausblenden bei Einladungen,
   die Knoepfe an jeder Freundeszeile, die Suche und die Aktion in einer
   Neuigkeit — alles Daumenziele. */
.btn--small {
	min-height: 44px;
	padding: var(--sp-1) var(--sp-3);
	font-size: 0.82rem;
}

.btn--ghost {
	background: transparent;
	border-color: var(--line);
	color: var(--text-2);
}

.btn--ghost:hover {
	background: var(--bg-panel);
	border-color: var(--text-3);
	color: var(--text);
}

.btn--quiet {
	background: none;
	border-color: transparent;
	color: var(--text-3);
	font-weight: 400;
}

.btn--quiet:hover {
	background: none;
	border-color: transparent;
	color: var(--text);
}

.foot {
	position: relative;
	z-index: 1;
	/* Auch hier standen die sicheren Zonen vertauscht. */
	padding: var(--sp-5) calc(var(--sp-4) + var(--safe-r)) var(--sp-6) calc(var(--sp-4) + var(--safe-l));
	border-top: 1px solid var(--line-soft);
	font-size: 0.78rem;
	line-height: 1.6;
	color: var(--text-3);
	text-align: center;
}

.gate {
	position: fixed;
	inset: 0;
	z-index: 60;
	display: grid;
	place-items: center;
	padding: var(--sp-4);
	background: rgb(14 14 18 / 0.94);
}

.gate__box {
	max-width: 380px;
	padding: var(--sp-5);
	background: var(--bg-panel);
	border: 1px solid var(--line);
	border-radius: var(--r-3);
	text-align: center;
}

.gate__box h2 {
	margin-bottom: var(--sp-3);
	font-size: 1.2rem;
}

.gate__box p {
	margin-bottom: var(--sp-4);
	color: var(--text-2);
	font-size: 0.9rem;
}

.dlg {
	width: min(94vw, 460px);
	max-height: 88dvh;
	padding: 0;
	background: var(--bg-panel);
	color: var(--text);
	border: 1px solid var(--line);
	border-radius: var(--r-3);
	overflow: auto;
}

.dlg::backdrop {
	background: rgb(10 10 14 / 0.72);
	backdrop-filter: blur(3px);
}

.dlg__form {
	display: flex;
	flex-direction: column;
	gap: var(--sp-3);
	padding: var(--sp-5) var(--sp-4) calc(var(--sp-4) + var(--safe-b));
}

.dlg__title {
	font-size: 1.15rem;
	font-weight: 700;
}

.dlg__text {
	font-size: 0.88rem;
	color: var(--text-2);
}

.field {
	margin: 0;
	padding: 0;
	border: 0;
}

.field legend {
	margin-bottom: var(--sp-2);
	padding: 0;
	font-size: 0.78rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-3);
}

.field--pair {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--sp-3);
}

/* Die Beschriftung ist der Schalter: sie umschliesst den Radioknopf. Mit
   8 Pixeln Polsterung war die Trefferflaeche 40 Pixel hoch. */
.choice {
	display: flex;
	align-items: flex-start;
	gap: var(--sp-2);
	min-height: 44px;
	padding: var(--sp-2) 0;
	font-size: 0.9rem;
	cursor: pointer;
}

.choice input {
	margin-top: 3px;
	accent-color: var(--accent);
	width: 18px;
	height: 18px;
}

.code {
	padding: var(--sp-3);
	background: var(--bg-sunk);
	border-radius: var(--r-1);
	font-size: 1.3rem;
	font-weight: 700;
	letter-spacing: 0.24em;
	text-align: center;
	color: var(--accent-lit);
}

.dlg__actions {
	display: flex;
	gap: var(--sp-2);
	justify-content: flex-end;
}

.dlg__actions--end {
	justify-content: center;
}

.toasts {
	position: fixed;
	left: 50%;
	bottom: calc(var(--dock-h) + var(--ifb-nav-h, var(--safe-b)) + var(--sp-2));
	z-index: 50;
	display: flex;
	flex-direction: column;
	gap: var(--sp-2);
	width: min(92vw, 420px);
	transform: translateX(-50%);
	pointer-events: none;
}

.toast {
	padding: var(--sp-3) var(--sp-4);
	background: var(--bg-panel);
	border: 1px solid var(--line);
	border-left: 3px solid var(--info);
	border-radius: var(--r-2);
	font-size: 0.88rem;
	box-shadow: 0 8px 24px rgb(0 0 0 / 0.5);
	animation: toastIn 260ms var(--ease) both;
}

.toast[data-type='success'] {
	border-left-color: var(--win);
}

.toast[data-type='error'] {
	border-left-color: var(--lose);
}

@keyframes toastIn {
	from {
		opacity: 0;
		transform: translateY(10px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

/* ==========================================================================
   11 — SKELETTE (statt Leere beim Laden)
   ========================================================================== */
.skel-group {
	display: flex;
	flex-direction: column;
	gap: var(--sp-3);
}

.skel {
	display: block;
	background: linear-gradient(90deg, var(--bg-raised) 25%, var(--bg-panel) 50%, var(--bg-raised) 75%);
	background-size: 200% 100%;
	border-radius: var(--r-2);
	animation: shimmer 1.4s linear infinite;
}

@keyframes shimmer {
	from {
		background-position: 200% 0;
	}
	to {
		background-position: -200% 0;
	}
}

.skel--cta {
	height: 68px;
	border-radius: var(--r-4);
}

.skel--line {
	height: 18px;
}

.skel--bar {
	height: 12px;
	border-radius: 999px;
}

.skel--tiles {
	height: 78px;
}

.skel--card {
	height: 132px;
	border-radius: var(--r-3);
}

/* ==========================================================================
   12 — BREITE SCHIRME
   ========================================================================== */
@media (min-width: 700px) {
	:root {
		--dock-h: 0px;
	}

	body.lobby {
		padding-bottom: 0;
	}

	/* Ab hier steht der Hauptknopf wieder im Lesefluss, wo er hingehoert. */
	.dock {
		position: static;
		padding: 0;
		margin-top: var(--sp-5);
		background: none;
		pointer-events: auto;
	}

	.dock__inner {
		max-width: none;
	}

	.cta {
		min-height: 76px;
		font-size: 1.35rem;
	}

	.wrap {
		max-width: 680px;
	}

	.lead__line {
		font-size: 1.9rem;
	}

	/* Auf breiten Schirmen ist Platz fuer die ehrliche Erklaerung der Zahl. */
	.tile__hint {
		display: block;
		margin-top: var(--sp-2);
		font-size: 0.72rem;
		line-height: 1.35;
		color: var(--text-3);
	}

	.toasts {
		bottom: var(--sp-5);
	}
}

/*
 * Zwei Spalten ab 1000 px. Jede Zuweisung steht hier vollstaendig, mit Zeile
 * UND Spalte — und das ist der Punkt:
 *
 * Vorher trugen die Abschnitte nur eine Spalte. Die automatische Platzierung
 * eines Rasters laeuft aber zeilenweise und faehrt den Zeiger nie zurueck.
 * #tables stand als letztes im Markup und war der einzige Eintrag in Spalte 2 —
 * es landete damit in Zeile 5, also UNTER dem gesamten linken Stapel aus Hero,
 * Fortschritt, Saison, Neuem und Einladungen. Die Tischliste war so auch auf
 * dem grossen Schirm die letzte Zeile der Seite, nicht die rechte Spalte.
 *
 * Links steht der Weg ins Spiel (Antwort, Einladungen, Tische), rechts der
 * eigene Stand. Dieselbe Reihenfolge wie auf dem Telefon, nur nebeneinander —
 * wer das Fenster aufzieht, soll nichts neu suchen muessen.
 */
@media (min-width: 1000px) {
	.wrap {
		max-width: 960px;
		display: grid;
		grid-template-columns: 1fr 1fr;
		column-gap: var(--sp-7);
		align-items: start;
	}

	.sec--hero {
		grid-column: 1;
		grid-row: 2;
	}

	#invites {
		grid-column: 1;
		grid-row: 3;
	}

	#tables {
		grid-column: 1;
		grid-row: 4;
	}

	#progress {
		grid-column: 2;
		grid-row: 2;
	}

	#news {
		grid-column: 2;
		grid-row: 3;
	}

	#season {
		grid-column: 2;
		grid-row: 4;
	}

	/*
	 * Zeile 1 gehoert der Sitzungsuhr des Spielerschutzes: protect.js haengt sie
	 * als erstes Kind in #main, damit wird sie zum Rasterelement. Ohne eigene
	 * Zeile schoebe die automatische Platzierung sie in die erste freie Zelle —
	 * bei durchnummerierten Zeilen ganz nach unten links. Ueber beide Spalten,
	 * damit sie nichts verdraengt; justify-self haelt sie schmal, denn sie ist
	 * ein Knopf und kein Balken.
	 *
	 * Die Regel bleibt auch dann richtig, wenn die Uhr in die Kopfzeile zieht:
	 * dann greift sie schlicht nicht mehr.
	 */
	.wrap > .psx-clock {
		grid-column: 1 / -1;
		grid-row: 1;
		justify-self: start;
	}
}

/* ==========================================================================
   14 — SAISON
   ----------------------------------------------------------------------------
   Drei nachgetragene Abschnitte, jeder mit seinen eigenen Medienabfragen am
   Ende — wie Abschnitt 13, damit die Nummern davor sich nicht verschieben.

   Keiner der drei darf die zwei Aufgaben der Lobby verdraengen: in einem Tipp
   an einen Tisch, und ein Grund fuer morgen. Deshalb traegt hier NICHTS die
   Glut als Flaeche; sie bleibt dem Hauptknopf und der eigenen Turnierbahn.
   ========================================================================== */

/* ------------------------------------------------------------------ Saison */
.season {
	display: block;
	padding: var(--sp-4);
	background: var(--bg-raised);
	border: 1px solid var(--line-soft);
	border-radius: var(--r-3);
}

.season__top {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sp-3);
	margin-bottom: var(--sp-4);
}

.season__name {
	font-size: 1.15rem;
	font-weight: 700;
	line-height: 1.25;
	overflow-wrap: anywhere;
}

.season__no {
	flex: none;
	padding: 2px var(--sp-2);
	border: 1px solid var(--line);
	border-radius: 999px;
	font-size: 0.72rem;
	letter-spacing: 0.04em;
	color: var(--text-3);
	white-space: nowrap;
}

/* Die Zahl, wegen der dieser Abschnitt hier steht. */
.season__place {
	margin-top: var(--sp-4);
	font-size: 1rem;
	color: var(--text-2);
}

.season__place b {
	color: var(--accent-lit);
	font-weight: 800;
}

/* Ohne Wertung steht hier ein Satz statt einer Zahl — leiser, weil er nichts
   feiert, sondern nur den Weg dorthin nennt. */
.season__place[data-quiet='1'] {
	font-size: 0.88rem;
	color: var(--text-3);
}

/* Dieselbe Aufhellung wie am Rangchip: die unterste Stufe traegt als reine
   Schriftfarbe nur 4,38:1. */
.season__tier {
	margin-left: var(--sp-2);
	font-size: 0.85rem;
	font-weight: 700;
	color: var(--tier);
	color: color-mix(in srgb, var(--tier) 82%, #ffffff);
}

.season__prev {
	margin-top: var(--sp-3);
	font-size: 0.82rem;
	color: var(--text-3);
}

/* Abzeichen ueberstehen jeden Saisonwechsel — das Bleibende, nicht das Laute. */
.awards {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-2);
	margin-top: var(--sp-4);
}

.award {
	display: inline-flex;
	align-items: center;
	gap: var(--sp-2);
	padding: 6px var(--sp-3) 6px var(--sp-2);
	background: var(--bg-sunk);
	border: 1px solid var(--line-soft);
	border-radius: 999px;
}

.award__mark {
	flex: none;
	color: var(--accent-lit);
	font-size: 0.95rem;
	line-height: 1;
}

.award__body {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

.award__label {
	font-size: 0.82rem;
	font-weight: 600;
}

.award__meta {
	font-size: 0.72rem;
	color: var(--text-3);
}

/* --------------------------------------------------------------- Archiv */
.arclist {
	display: flex;
	flex-direction: column;
	margin-top: var(--sp-2);
}

.arc {
	display: flex;
	align-items: baseline;
	gap: var(--sp-3);
	padding: var(--sp-3) 0;
	border-bottom: 1px solid var(--line-soft);
}

.arc:last-child {
	border-bottom: 0;
}

.arc__no {
	flex: none;
	min-width: 2.6em;
	font-size: 0.85rem;
	font-weight: 700;
	color: var(--text-2);
}

.arc__body {
	flex: 1 1 auto;
	min-width: 0;
}

.arc__name {
	display: block;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 0.92rem;
}

.arc__meta {
	display: block;
	font-size: 0.78rem;
	color: var(--text-3);
}

/* Ein Anzeigename darf 32 Zeichen haben — hier wird er beschnitten statt die
   Zeile zu sprengen. */
.arc__champ {
	flex: none;
	max-width: 9em;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 0.75rem;
	color: var(--text-3);
}

/* ----------------------------------------------------------- Breite Schirme
   Die Saison hatte hier ihre eigene Rasterzuweisung, die Sitzungsuhr auch.
   Zwei Medienabfragen fuer dasselbe Raster sind eine Falle: die spaetere gewann
   bei gleicher Spezifitaet, ohne dass man es an der frueheren sieht. Beide
   Zuweisungen stehen jetzt vollstaendig in Abschnitt 12 — ein Raster, ein Ort.
   ========================================================================== */

/* ==========================================================================
   BEWEGUNG AUF WUNSCH AUS
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
	}
}

/* ==========================================================================
   GEMEINSAMES VOKABULAR: FORMULARE UND DATENKAESTEN
   ----------------------------------------------------------------------------
   Siehe die Notiz an Abschnitt 10. Die frueheren Doppelselektoren
   (.tour__facts, .facts) sind auf die verbliebene Haelfte eingedampft — das
   Turniervokabular ist mit der Turnierseite ausgezogen und hat dort seine
   eigenen Regeln.
   ========================================================================== */

/* --- Aufklappbares (Saisonarchiv) --- */
.fold {
	margin-top: var(--sp-4);
	border-top: 1px solid var(--line-soft);
}

.fold__head {
	padding: var(--sp-3) 0;
	font-size: 0.88rem;
	color: var(--text-2);
	cursor: pointer;
}

.fold__head::marker {
	color: var(--text-3);
}

/* --- Eingaben (Tisch eroeffnen, Einladung einloesen) --- */
.lbl {
	display: block;
	margin-bottom: var(--sp-1);
	font-size: 0.78rem;
	color: var(--text-3);
}

.input {
	width: 100%;
	/* 16px verhindert das Hineinzoomen beim Fokus auf iOS. */
	min-height: 44px;
	padding: var(--sp-2) var(--sp-3);
	background: var(--bg-sunk);
	border: 1px solid var(--line);
	border-radius: var(--r-1);
	font-size: 16px;
}

/* outline:none galt fuer jeden Fokus und schlug damit auch :focus-visible —
   wer per Tastatur durch die Lobby geht, sah nur einen etwas helleren Rahmen
   von einem Pixel. Der Rahmen bleibt als Zusatz, der Ring kommt zurueck. */
.input:focus {
	border-color: var(--accent);
	outline: none;
}

.input:focus-visible {
	outline: 2px solid var(--accent-lit);
	outline-offset: 2px;
}

.code-input {
	letter-spacing: 0.2em;
	text-transform: uppercase;
}

.formnote {
	margin-top: var(--sp-2);
	font-size: 0.82rem;
	color: var(--text-3);
}

.formnote[data-tone='ok'] {
	color: var(--win);
}

.formnote[data-tone='bad'] {
	color: var(--lose-lit);
}

/* --- Datenkasten (dl): Label links, Wert rechts. Erzeugt von factRow(). --- */
.facts {
	margin-top: var(--sp-4);
	border-top: 1px solid var(--line-soft);
}

.fact-row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sp-3);
	padding: var(--sp-2) 0;
	border-bottom: 1px solid var(--line-soft);
}

.fact-row-l {
	font-size: 0.82rem;
	color: var(--text-3);
}

.fact-row-v {
	font-size: 0.92rem;
	font-weight: 600;
}

/* --- Der Pflichthinweis unter der Saison --- */
.season__legal {
	margin-top: var(--sp-4);
	font-size: 0.75rem;
	line-height: 1.45;
	color: var(--text-3);
}
