/* chessplosion — Bildsprache "Turnierfilz & Messing".
 *
 * Ein Clubtisch nachts: Filz als Fläche, Messing als einziger warmer Akzent,
 * alles andere tritt zurück. Die 3D-Szene trägt das Bild; die Oberfläche darf
 * es nicht zukleistern.
 *
 * Kein Text in der 3D-Szene, alles hier als HTML — MSDF-Font-Atlanten decken
 * kein CJK ab, Systemschrift plus Inter schon.
 */

/* Lokal eingebunden, kein CDN: die App muss offline laufen. Inter ist eine
   Variable Font, eine Datei deckt alle Schnitte ab. */
@font-face {
	font-family: 'Inter';
	src: url('./assets/fonts/Inter.ttf') format('truetype');
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: 'Plex Mono';
	src: url('./assets/fonts/IBMPlexMono-Medium.ttf') format('truetype');
	font-weight: 500;
	font-style: normal;
	font-display: swap;
}

:root {
	/* --- Farbe: semantische Tokens, nie rohe Hexwerte in Komponenten --- */
	--felt: #15803D;
	--felt-deep: #0C5028;
	--brass: #D97706;
	--brass-bright: #F0A53A;
	--night: #0F172A;
	--night-deep: #080D18;

	--surface: rgba(14, 20, 33, .86);
	--surface-solid: #131A2A;
	--surface-raised: #1B2436;
	--line: rgba(255, 255, 255, .09);
	--line-strong: rgba(217, 119, 6, .42);

	--text: #F4F7FB;
	--text-muted: #9FB0C3;      /* 7.2:1 auf --night */
	--text-faint: #6B7A8F;      /* nur für Deko, nie für Inhalt */
	--danger: #F0564A;
	--success: #4ADE80;

	/* --- Abstand: 4er-Rhythmus --- */
	--s-1: 4px;
	--s-2: 8px;
	--s-3: 12px;
	--s-4: 16px;
	--s-5: 24px;
	--s-6: 32px;
	--s-7: 48px;
	--s-8: 64px;

	--r-sm: 8px;
	--r-md: 12px;
	--r-lg: 18px;
	--r-xl: 26px;

	/* --- Bewegung: ein Rhythmus für alles --- */
	--t-fast: 140ms;
	--t-base: 220ms;
	--t-slow: 380ms;
	--ease-out: cubic-bezier(.16, 1, .3, 1);
	--ease-in: cubic-bezier(.7, 0, .84, 0);

	/* Von der Shell gesetzt */
	--sa-top: 0px; --sa-bottom: 0px; --sa-left: 0px; --sa-right: 0px;

	--z-hud: 10;
	--z-sheet: 40;
	--z-screen: 100;

	font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, system-ui, sans-serif;
	font-synthesis-weight: none;
}

* { box-sizing: border-box; }

html, body {
	margin: 0; height: 100%; overflow: hidden;
	background: var(--night-deep); color: var(--text);
	-webkit-user-select: none; user-select: none;
	-webkit-tap-highlight-color: transparent;
	overscroll-behavior: none;
	font-size: 16px; line-height: 1.5;
}

#scene { display: block; width: 100%; height: 100%; touch-action: none; }

/* Wer Bewegung reduziert haben will, bekommt sie reduziert. */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
	}
}

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

.icon {
	width: 20px; height: 20px; flex: none;
	stroke: currentColor; fill: none;
	stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
}

.icon-lg { width: 26px; height: 26px; }

button {
	font: inherit; font-size: 14px; font-weight: 550;
	display: inline-flex; align-items: center; justify-content: center;
	gap: var(--s-2);
	color: var(--text);
	background: rgba(255, 255, 255, .06);
	border: 1px solid var(--line);
	border-radius: var(--r-md);
	/* 44px Mindesthöhe: Touch-Ziel, nicht Geschmack */
	padding: 0 var(--s-4); min-height: 44px;
	cursor: pointer;
	white-space: nowrap;
	transition: background var(--t-fast) var(--ease-out),
	            border-color var(--t-fast) var(--ease-out),
	            color var(--t-fast) var(--ease-out),
	            opacity var(--t-fast) var(--ease-out);
}

button:hover:not(:disabled) { background: rgba(255, 255, 255, .11); }
/* Kein Layout-Sprung beim Drücken — nur Fläche, keine Größe */
button:active:not(:disabled) { background: rgba(255, 255, 255, .17); }
button:disabled { opacity: .4; cursor: default; }

/* Laeuft gerade.
 *
 * Nur der ausgeloeste Knopf bekommt den Punkt; gesperrt sind waehrenddessen
 * alle. Ohne diese Rueckmeldung stand der Bildschirm bei jedem Aufruf
 * sekundenlang unveraendert da und sah aus wie ein toter Knopf.
 *
 * Der Punkt sitzt in einem eigenen Kasten fester Breite: laeuft die Anzeige
 * ueber ::after ohne reservierten Platz, springt die Beschriftung beim
 * Erscheinen zur Seite. */
button.is-busy { opacity: 1; position: relative; }

button.is-busy::after {
	content: '';
	width: .55em;
	height: .55em;
	margin-inline-start: .5em;
	border-radius: 50%;
	background: currentColor;
	display: inline-block;
	vertical-align: middle;
	animation: busy-pulse 900ms ease-in-out infinite;
}

@keyframes busy-pulse {
	0%, 100% { opacity: .25; transform: scale(.8); }
	50% { opacity: 1; transform: scale(1); }
}

/* Wer Bewegung abbestellt hat, bekommt sie auch hier nicht. Der Punkt bleibt
 * trotzdem stehen — er ist die Auskunft, nicht die Bewegung. */
@media (prefers-reduced-motion: reduce) {

	button.is-busy::after { animation: none; opacity: .8; }

}


button:focus-visible,
[tabindex]:focus-visible {
	outline: 2px solid var(--brass-bright);
	outline-offset: 2px;
}

button.is-active {
	background: rgba(217, 119, 6, .16);
	border-color: var(--line-strong);
	color: var(--brass-bright);
}

button.primary {
	background: var(--felt);
	border-color: rgba(255, 255, 255, .16);
	color: #FFFFFF;
	font-weight: 600;
}

button.primary:hover:not(:disabled) { background: #179145; }
button.primary:active:not(:disabled) { background: #12692F; }

/* Messing statt Filz. Für die eine Aktion, die auffallen soll, ohne dem
   grünen Hauptknopf seinen Rang streitig zu machen — auf einem Bildschirm mit
   zwei gleich grünen Flächen sucht das Auge zweimal. */
button.accent {
	background: rgba(217, 119, 6, .9);
	border-color: rgba(240, 165, 58, .8);
	color: #1B1409;
	font-weight: 650;
}

button.accent .icon { color: #1B1409; }
button.accent:hover:not(:disabled) { background: var(--brass-bright); }
button.accent:active:not(:disabled) { background: #C06A05; }

button.ghost { background: transparent; border-color: transparent; }
button.ghost:hover:not(:disabled) { background: rgba(255, 255, 255, .08); }

button.danger { color: var(--danger); border-color: rgba(240, 86, 74, .35); }
button.danger:hover:not(:disabled) { background: rgba(240, 86, 74, .14); }

.icon-button { padding: 0; width: 44px; }

.panel {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r-lg);
	backdrop-filter: blur(16px) saturate(140%);
	-webkit-backdrop-filter: blur(16px) saturate(140%);
}

/* Messing-Haarlinie oben: das eine Detail, das die Flächen wertig macht */
.panel-brass { position: relative; overflow: hidden; }

.panel-brass::before {
	content: ''; position: absolute; inset: 0 0 auto 0; height: 1px;
	background: linear-gradient(90deg,
		transparent, rgba(240, 165, 58, .55) 20%, rgba(240, 165, 58, .55) 80%, transparent);
}

.num { font-variant-numeric: tabular-nums; }

.mono {
	font-family: 'Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
	font-variant-numeric: tabular-nums;
}

/* Rechts-nach-links (ar, he). Gespiegelt wird die Huelle — das Brett nie, es
   ist ein Bild, und die Notation auch nicht: "Nf3", "1-0", ein Einladungscode
   und jede Zahl lesen sich links nach rechts, auch mitten in einem arabischen
   Satz. Ohne die Isolierung schiebt der Bidi-Algorithmus genau da Ziffern und
   Buchstaben durcheinander. Nur unter [dir='rtl'], damit an den vorhandenen
   Sprachen nichts anders gerechnet wird. */
[dir='rtl'] :is(.mono, .num, .fig, .ltr, .code-value, #moves, #moves li) {
	direction: ltr;
	unicode-bidi: isolate;
}

/* Der Zurueck-Pfeil zeigt dahin, wo "zurueck" liegt — rechts, wenn gelesen
   wird von rechts. Das Zeichen selbst gibt es nur einmal. */
[dir='rtl'] [data-act='back'] svg { transform: scaleX(-1); }

.eyebrow {
	font-size: 11px; font-weight: 600; letter-spacing: .14em;
	text-transform: uppercase; color: var(--brass);
}

.muted { color: var(--text-muted); }

.stack { display: flex; flex-direction: column; }
.row { display: flex; align-items: center; }
.gap-2 { gap: var(--s-2); }
.gap-3 { gap: var(--s-3); }
.gap-4 { gap: var(--s-4); }

/* ---------------------------------------------------------------- Spiel-HUD */

#hud {
	position: fixed; inset: 0; pointer-events: none; z-index: var(--z-hud);
	padding: calc(var(--sa-top) + var(--s-3)) calc(var(--sa-right) + var(--s-3))
	         calc(var(--sa-bottom) + var(--s-3)) calc(var(--sa-left) + var(--s-3));
	display: flex; flex-direction: column; justify-content: space-between;
}

#hud > *, #lower > * { pointer-events: auto; }
#lower { display: flex; flex-direction: column; gap: var(--s-3); pointer-events: none; }

#hud[hidden] { display: none; }

.bar {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-2) var(--s-3);
}

#top { justify-content: space-between; }

#status {
	display: flex; align-items: center; gap: var(--s-2);
	font-size: 15px; font-weight: 600; letter-spacing: .005em;
	padding-inline-start: var(--s-2);
}

/* Wer am Zug ist, steht als Punkt daneben — Farbe allein reicht nicht,
   deshalb zusätzlich der Text. */
.turn-dot {
	width: 10px; height: 10px; border-radius: 50%; flex: none;
	border: 1px solid rgba(0, 0, 0, .5);
	box-shadow: 0 0 0 1px rgba(255, 255, 255, .18);
}

.turn-dot.w { background: #E8DFCC; }
.turn-dot.b { background: #1C1C22; }

#bottom { align-items: flex-end; }

#moves {
	list-style: none; margin: 0; padding: 0;
	flex: 1; max-height: 96px; overflow-y: auto;
	font-size: 14px; line-height: 1.55;
	display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
	gap: 0 var(--s-4);
	scrollbar-width: thin;
}

#moves li {
	display: grid; grid-template-columns: 2.4em 1fr 1fr; gap: var(--s-2);
	font-variant-numeric: tabular-nums;
}

#moves .no { color: var(--text-faint); }
#moves .boom { color: var(--brass-bright); font-weight: 600; }

/* ---------------------------------------------------------------- Zielhilfe */

/* Anleitung beim ersten Spiel: eine Zeile, kein Dialog. Sie steht im Weg von
   nichts und verschwindet, sobald die Handlung getan ist. */
#coach[hidden] { display: none; }

#coach {
	align-self: center;
	padding: var(--s-2) var(--s-4);
	border-radius: 99px;
	background: rgba(217, 119, 6, .92);
	color: #1b1409;
	font-size: 14px; font-weight: 650;
	box-shadow: 0 6px 20px rgba(0, 0, 0, .4);
	animation: coach-in var(--t-slow) var(--ease-out);
}

@keyframes coach-in {
	from { opacity: 0; transform: translateY(8px); }
}

#aim[hidden] { display: none; }

#aim {
	align-self: center;
	display: flex; flex-direction: column; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-5);
	max-width: min(92vw, 400px); text-align: center;
}

#aim-hint { font-size: 13px; font-weight: 550; line-height: 1.4; }

.meter {
	--fill: 40%;
	position: relative; display: block;
	width: 240px; max-width: 62vw; height: 10px;
	border-radius: 99px; background: rgba(255, 255, 255, .11);
	overflow: hidden;
}

.meter > i {
	display: block; height: 100%; width: var(--fill);
	border-radius: 99px;
	background: linear-gradient(90deg, var(--felt) 0%, var(--brass) 55%, var(--danger) 100%);
	transition: width var(--t-fast) linear;
}

/* Beim Timing-Balken pendelt der Zeiger — dann darf die Breite nicht nachziehen */
.meter.is-swinging > i { transition: none; }

/* Trefferzone des Timing-Balkens: der Bereich, der auf der gegnerischen
   Hälfte landet. Keine erfundene "gute Zone" — darunter trifft man die eigenen
   Figuren, darüber fliegt es vom Brett. */
.meter > .zone {
	position: absolute; top: -2px; bottom: -2px;
	background: rgba(255, 255, 255, .16);
	border-left: 2px solid var(--brass-bright);
	border-right: 2px solid var(--brass-bright);
	z-index: 1; pointer-events: none;
}

.meter > .zone[hidden] { display: none; }

.wind {
	display: flex; align-items: center; gap: var(--s-2);
	font-size: 12px; font-weight: 600; color: var(--text-muted);
}

.wind .icon { width: 16px; height: 16px; }
.wind[hidden] { display: none; }

/* ---------------------------------------------------------------- Overlays */

.overlay[hidden] { display: none; }

.overlay {
	position: fixed; inset: 0; z-index: var(--z-sheet);
	display: grid; place-items: center;
	padding: calc(var(--sa-top) + var(--s-4)) var(--s-4) calc(var(--sa-bottom) + var(--s-4));
	/* Scrim kräftig genug, dass der Vordergrund lesbar bleibt */
	background: rgba(6, 9, 16, .72);
	backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
	animation: fade-in var(--t-base) var(--ease-out);
}

.sheet {
	background: var(--surface-solid);
	border: 1px solid var(--line);
	border-radius: var(--r-xl);
	padding: var(--s-6);
	width: min(94vw, 460px);
	max-height: 100%;
	overflow-y: auto;
	box-shadow: 0 24px 60px rgba(0, 0, 0, .55);
	animation: sheet-in var(--t-slow) var(--ease-out);
}

/* Der Dialog bekommt den Fokus fuer Screenreader, ist aber kein Bedienelement —
   ein Fokusring um die ganze Flaeche waere nur Laerm. */
.sheet:focus, .sheet:focus-visible { outline: none; }

.sheet h2 {
	margin: 0 0 var(--s-2); font-size: 22px; font-weight: 650; letter-spacing: -.01em;
}

.sheet p { margin: 0 0 var(--s-5); color: var(--text-muted); font-size: 14px; }

@keyframes fade-in { from { opacity: 0; } }

@keyframes sheet-in {
	from { opacity: 0; transform: translateY(16px) scale(.97); }
}

.choices { display: flex; gap: var(--s-3); flex-wrap: wrap; justify-content: center; }

.choices button {
	flex-direction: column; gap: var(--s-1);
	padding: var(--s-3) var(--s-4); min-width: 84px; min-height: 84px;
}

.choices .glyph { font-size: 34px; line-height: 1; }
.choices .glyph.light { color: #E8DFCC; text-shadow: 0 1px 3px rgba(0, 0, 0, .7); }
.choices .glyph.dark { color: #1C1C22; text-shadow: 0 0 2px rgba(255, 255, 255, .6); }
.choices .label { font-size: 11px; color: var(--text-muted); font-weight: 550; }

/* ------------------------------------------------------------ Wiedergabe */

#replaybar[hidden] { display: none; }

#replaybar {
	position: fixed; z-index: var(--z-hud);
	left: 50%; transform: translateX(-50%);
	bottom: calc(var(--sa-bottom) + var(--s-4));
	display: flex; align-items: center; gap: var(--s-1);
	padding: var(--s-2);
	max-width: calc(100vw - var(--s-6));
}

#rp-play { background: rgba(217, 119, 6, .2); border-color: var(--line-strong); color: var(--brass-bright); }
#rp-speed { min-width: 52px; font-size: 13px; }
#rp-progress { font-size: 13px; padding: 0 var(--s-2); white-space: nowrap; }

/* ------------------------------------------------------------------ Listen */

.cards { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s-2); }

.card {
	display: flex; align-items: stretch; gap: var(--s-1);
	background: rgba(255, 255, 255, .04);
	border: 1px solid var(--line);
	border-radius: var(--r-md);
	padding: var(--s-1);
}

.card-main {
	flex: 1; justify-content: flex-start; gap: var(--s-3);
	background: transparent; border-color: transparent;
	min-height: 56px; text-align: start;
}

.card-main .icon { color: var(--brass); }
.card-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.card-title {
	font-size: 15px; font-weight: 600;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.card-meta {
	font-size: 12px; color: var(--text-muted); font-weight: 450;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Auswertung: zwei Spalten nebeneinander, auf schmalen Geräten untereinander */
.review { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); }

@media (max-width: 400px) { .review { grid-template-columns: 1fr; } }

.review-col {
	background: rgba(255, 255, 255, .04);
	border: 1px solid var(--line);
	border-radius: var(--r-md);
	padding: var(--s-3);
}

.review-head { display: flex; align-items: center; gap: var(--s-2); }
.review-col .card-meta { margin: var(--s-1) 0 var(--s-3); }

.review-stats {
	margin: 0; display: grid; grid-template-columns: 1fr auto;
	gap: var(--s-1) var(--s-2); font-size: 13px;
}

.review-stats dt { color: var(--text-muted); }
.review-stats dd { margin: 0; font-weight: 600; }
.review-stats .warn { color: var(--danger); }

/* Regeln: eine Liste zum Lesen, keine Karten zum Antippen. Deshalb kein
   Rahmen und keine Fläche — nur Icon, Satz, Erklärung. */
.rules { list-style: none; margin: 0 0 var(--s-4); padding: 0; display: flex; flex-direction: column; gap: var(--s-4); }
.rules li { display: flex; gap: var(--s-3); align-items: flex-start; }
.rules .icon { color: var(--brass); margin-top: 2px; }
/* Karten kürzen ihren Titel mit Auslassungspunkten ab; ein Regelsatz darf
   umbrechen, sonst steht dort "Wer schlägt, darf …". */
.rules .card-title { white-space: normal; overflow: visible; }
.rule-body { font-size: 13px; line-height: 1.45; color: var(--text-muted); }

/* Wie viele Fernpartien auf einen Zug warten. Messing, weil es die einzige
   Zahl im Menü ist, die etwas von jemand anderem will. */
.badge {
	margin-inline-start: auto;
	min-width: 22px; height: 22px; padding: 0 var(--s-2);
	display: inline-flex; align-items: center; justify-content: center;
	border-radius: 99px;
	background: var(--brass); color: #1B1409;
	font-size: 12px; font-weight: 700;
}

/* Derselbe Hinweis auf Zeilenebene: ein Punkt, kein Text — in einer Liste
   steht schon in der Metazeile, worum es geht. */
.pip {
	width: 8px; height: 8px; border-radius: 50%; flex: none;
	margin-inline-start: auto;
	background: var(--brass-bright);
}

.card.is-waiting { border-color: var(--line-strong); }

/* --- Kontoansicht ------------------------------------------------------- */

/* Wer bin ich. Eine eigene Fläche, damit Name, Kontoart und Freundescode als
   eine Einheit gelesen werden statt als drei gleich aussehende Zeilen. */
.identity {
	background: rgba(255, 255, 255, .04);
	border: 1px solid var(--line);
	border-radius: var(--r-md);
	padding: var(--s-4);
	margin-bottom: var(--s-5);
}

.identity-head {
	display: flex; align-items: center; gap: var(--s-3);
	flex-wrap: wrap;
}

.identity-name {
	font-size: 22px; font-weight: 700; letter-spacing: -.01em;
	overflow: hidden; text-overflow: ellipsis;
}

.identity-sub {
	margin: var(--s-1) 0 0;
	font-size: 13px; color: var(--text-muted);
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Kontoart als Plakette, nicht als weitere Textzeile: sie ist ein Zustand,
   keine Aussage. */
.pill {
	padding: 3px var(--s-3); border-radius: 99px;
	background: rgba(255, 255, 255, .08);
	border: 1px solid var(--line);
	font-size: 11px; font-weight: 650;
	letter-spacing: .08em; text-transform: uppercase;
	color: var(--text-muted);
	white-space: nowrap;
}

/* Ein Gastkonto hat eine Frist — das darf man sehen. */
.pill--warn {
	background: rgba(217, 119, 6, .18);
	border-color: var(--line-strong);
	color: var(--brass-bright);
}

/* Der Freundescode ist das Einzige hier, das man weitergibt. Eigene Zeile,
   Tabellenziffern, Kopierknopf daneben. */
.code-row {
	display: flex; align-items: center; gap: var(--s-3);
	margin-top: var(--s-4);
	padding-top: var(--s-4);
	border-top: 1px solid var(--line);
}

.code-label {
	font-size: 11px; font-weight: 600; letter-spacing: .14em;
	text-transform: uppercase; color: var(--brass);
}

.code-value {
	font-size: 17px; font-weight: 500; letter-spacing: .12em;
	margin-inline-end: auto;
	-webkit-user-select: text; user-select: text;
}

/* Löschen steht abgesetzt und ganz unten: die einzige Handlung auf diesem
   Bildschirm, die sich nicht rückgängig machen lässt. */
.danger-zone {
	margin-top: var(--s-6);
	padding-top: var(--s-5);
	border-top: 1px solid var(--line);
}

.danger-zone .menu-list, .danger-zone > button { width: 100%; }
.danger-zone > button { justify-content: flex-start; min-height: 48px; }
.danger-zone .hint { margin-top: var(--s-2); }

button.ghost.danger { color: var(--danger); border-color: transparent; }
button.ghost.danger:hover:not(:disabled) { background: rgba(240, 86, 74, .12); }

/* Der letzte Abschnitt braucht keinen Abstand nach unten — darunter kommt die
   Trennlinie der Löschzone. */
.field--last { margin-bottom: 0; }

/* Der eigene Name rechts im Menüeintrag: die Antwort auf „bin ich drin?",
   ohne dass man dafür irgendwo hineingehen muss. */
.menu-note {
	margin-inline-start: auto;
	font-size: 13px; font-weight: 500;
	color: var(--text-muted);
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	max-width: 45%;
}

.empty { text-align: center; padding: var(--s-6) var(--s-4); }
.empty-title { margin: 0 0 var(--s-2); font-size: 16px; font-weight: 600; }
.empty .hint { margin: 0; }

/* ---------------------------------------------------------------- Menues */

.hero { text-align: center; margin-bottom: var(--s-6); }

.hero h1 {
	margin: var(--s-2) 0 0;
	font-size: clamp(30px, 8vw, 40px); font-weight: 700;
	letter-spacing: -.03em; line-height: 1.05;
}

.hero .icon-lg { color: var(--brass-bright); }
.hero p { margin: var(--s-2) 0 0; font-size: 14px; }

/* Messing-Strich unter dem Titel: das Markenzeichen der Oberflaeche */
.hero::after {
	content: ''; display: block; width: 56px; height: 2px;
	margin: var(--s-4) auto 0; border-radius: 2px;
	background: linear-gradient(90deg, transparent, var(--brass), transparent);
}

.sheet-head {
	display: flex; align-items: center; gap: var(--s-2);
	margin: calc(var(--s-2) * -1) 0 var(--s-5) calc(var(--s-3) * -1);
}

.sheet-head h2 { margin: 0; font-size: 20px; }

.menu-list { display: flex; flex-direction: column; gap: var(--s-2); }

/* Menue-Eintraege sind linksbuendig und voll breit — eine Liste, keine Wolke
   aus zentrierten Knoepfen. */
.menu-list > button {
	width: 100%; justify-content: flex-start;
	min-height: 52px; padding: 0 var(--s-4);
	font-size: 15px;
}

.menu-list > button .icon { color: var(--brass); }
.menu-list > button.primary .icon { color: rgba(255, 255, 255, .9); }

.field { margin-bottom: var(--s-5); }
.field > .eyebrow { display: block; margin-bottom: var(--s-2); }

.hint {
	margin: var(--s-2) 0 0; font-size: 13px; line-height: 1.45;
	color: var(--text-muted);
}

/* Hinweis auf eine neue Version. Sichtbar, aber nicht laut: eine Zeile unter
   dem Menue, ohne Farbe und ohne Ausrufezeichen. Wer das Spiel oeffnet, will
   spielen — die Aktualisierung ist eine Einladung, keine Aufgabe. */
.notice {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-3); flex-wrap: wrap;
	margin-top: var(--s-5); padding: var(--s-3);
	border: 1px solid var(--line); border-radius: var(--r-md);
	font-size: 13px; color: var(--text-muted);
}
.notice > button { min-height: 36px; padding: 0 var(--s-3); font-size: 13px; }

.segment {
	display: flex; gap: var(--s-1);
	padding: var(--s-1);
	background: rgba(255, 255, 255, .04);
	border: 1px solid var(--line);
	border-radius: var(--r-md);
}

.segment > button {
	flex: 1; min-height: 40px; padding: 0 var(--s-3);
	background: transparent; border-color: transparent;
	font-size: 14px;
}

.segment > button:hover:not(.is-active) { background: rgba(255, 255, 255, .07); }

/* Die Auswahl muss ohne Farbvergleich erkennbar sein: eigene Flaeche und
   Rahmen, nicht nur ein anderer Textton. */
.segment > button.is-active {
	background: rgba(217, 119, 6, .22);
	border-color: rgba(240, 165, 58, .6);
	color: var(--brass-bright);
	box-shadow: 0 1px 0 rgba(0, 0, 0, .3);
}

/* Schachfiguren-Zeichen kommen aus einer Fallback-Schrift und wirken darin
   optisch zu klein. */
.fig { font-size: 1.25em; line-height: 1; vertical-align: -.06em; }

.segment > button .icon { width: 18px; height: 18px; }

/* Die Sprachauswahl hat seit 1.2 fuenfzehn Eintraege — eine Zeile reicht
   nicht mehr. Nur diese eine Segmentleiste bricht um, alle anderen
   (Modus, Schwierigkeit, Notation) bleiben einzeilig. */
.segment--wrap { flex-wrap: wrap; }
.segment--wrap > button { flex: 1 1 28%; }


/* Auf schmalen Geraeten bricht ein Segment mit Icon+Text sonst haesslich um */
@media (max-width: 380px) {
	.segment > button span { font-size: 13px; }
	.segment > button { padding: 0 var(--s-2); }
}

/* --- Balane Play: Konto, Bestenliste, Freunde ---------------------------- */

/* Zeilenaktionen klappen UNTER der Zeile auf, nicht daneben: der Name muss
   sichtbar bleiben, waehrend man entscheidet, ob man ihn meldet. Die Karte
   darf dafuer umbrechen — ohne zusaetzliche Kinder aendert das nichts an den
   Karten von Spielstand und Wiedergabe. */
.card { flex-wrap: wrap; }

.row-actions {
	flex-basis: 100%;
	padding: var(--s-3) var(--s-3) var(--s-2);
	border-top: 1px solid var(--line);
	margin-top: var(--s-1);
}
.row-actions .eyebrow { display: block; margin-bottom: var(--s-2); }
.row-actions .menu-list { margin-top: var(--s-2); }
.row-actions .menu-list > button { min-height: 44px; font-size: 14px; }

/* Der Rang steht vor dem Namen und in gleicher Breite, damit die Namen
   untereinander an derselben Kante beginnen — sonst wandert die Liste beim
   Sprung von Rang 9 auf 10 sichtbar nach rechts. */
.card-rank {
	flex: 0 0 auto; min-width: 2.5ch; text-align: end;
	font-variant-numeric: tabular-nums;
	font-size: 15px; font-weight: 600; color: var(--brass);
}

.text-input {
	width: 100%; box-sizing: border-box;
	min-height: 48px; padding: 0 var(--s-3);
	background: rgba(255, 255, 255, .04);
	border: 1px solid var(--line); border-radius: var(--r-md);
	color: var(--text); font: inherit; font-size: 16px;
}
/* 16px oben ist kein Zufall: alles darunter laesst iOS beim Antippen in das
   Feld hineinzoomen, und danach steht das Menue schief. */
.text-input:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.text-input::placeholder { color: var(--text-faint); }

.notice.is-error { border-color: var(--danger); color: var(--text); }

/* Ein Verweis, der aussieht wie ein Verweis, aber ein Knopf ist. Das Spiel
   läuft in einem WebView ohne Adresszeile und ohne Zurück — eine echte
   Navigation dorthin wäre eine Sackgasse, die Hülle öffnet die Seite deshalb
   im Systembrowser. */
.linky {
	display: inline; padding: 0; min-height: 0; width: auto;
	background: none; border: none; border-radius: 0;
	font: inherit; color: var(--brass-bright);
	text-decoration: underline; text-underline-offset: 2px;
	cursor: pointer;
}

.linky:hover:not(:disabled) { background: none; color: var(--text); }
.linky:active:not(:disabled) { background: none; }

/* Die Zeile über dem Knopf, der ein Konto anlegt. Sie darf nicht schreien,
   aber sie muss dort stehen: AGB gelten nur, wenn man sie vor dem Abschluss
   zur Kenntnis nehmen konnte. */
.legal { margin-top: var(--s-3); }

/* Das Kästchen, mit dem die Nutzungsbedingungen aktiv angenommen werden.
   Steht ÜBER dem Knopf, nicht darunter: erst zustimmen, dann handeln — und
   der Knopf ist bis dahin grau. Nur die Bedingungen bekommen ein Kästchen;
   der Datenschutzhinweis darunter ist Information, keine Einwilligung, und
   deshalb eine schlichte Hinweiszeile. */
.legal-gate { margin-top: var(--s-4); }

.legal-gate .check-row {
	display: flex; align-items: flex-start; gap: var(--s-3);
}

.legal-gate .legal-accept {
	margin: 0; font-size: 14px; line-height: 1.45; color: var(--text);
}

/* 24px plus Innenabstand: ein Kästchen, das man mit dem Daumen trifft. Ein
   kleineres wäre auf einem Telefon eine Zielübung, und dieses hier ist die
   Stelle, an der ein Vertrag zustande kommt. */
.legal-gate .checkbox {
	flex: 0 0 auto; width: 26px; height: 26px; min-height: 0; padding: 0;
	display: flex; align-items: center; justify-content: center;
	background: none; border: 1px solid var(--line); border-radius: var(--r-sm);
	color: var(--bg); cursor: pointer;
}

.legal-gate .checkbox .icon { width: 18px; height: 18px; }

.legal-gate .checkbox.is-checked {
	background: var(--brass-bright); border-color: var(--brass-bright);
}

/* Eine Annahme, die noch aussteht — ein Bestandskonto aus der Zeit vor der
   Pflicht. Abgesetzt, weil daran hängt, ob man gegen andere spielen kann. */
.legal-gate--due {
	padding: var(--s-3);
	border: 1px solid var(--line); border-radius: var(--r-md);
}

/* Der Platz auf dem Ergebnisbildschirm. Messing-Rahmen statt Fläche: er soll
   auffallen, ohne dem Titel der Partie die Aufmerksamkeit zu nehmen — was
   passiert ist, steht darüber. */
.rank-block {
	border: 1px solid var(--line-strong);
	border-radius: var(--r-md);
	padding: var(--s-4);
	background: rgba(217, 119, 6, .07);
}

.rank-block > .eyebrow { display: block; margin-bottom: var(--s-1); }

.rank-line {
	margin: 0 0 var(--s-3);
	font-size: 20px; font-weight: 650; letter-spacing: -.01em;
	font-variant-numeric: tabular-nums;
	color: var(--text);
}

.rank-block .hint { margin-top: var(--s-3); }
.rank-block .menu-list { margin-top: var(--s-3); }

/* --- Zahlen, die sich anhäufen ------------------------------------------ */

/* Bestwert und Serie: zwei Chips unter dem Titel, sonst nichts. Sie stehen im
   Hauptmenü und auf dem Ergebnisbildschirm an derselben Stelle — was sich
   ansammelt, soll man dort wiederfinden, wo man es zuletzt gesehen hat. */
.chips {
	display: flex; flex-wrap: wrap; justify-content: center;
	gap: var(--s-2); margin: var(--s-3) 0 0;
}

.chip {
	display: inline-flex; align-items: center; gap: var(--s-2);
	padding: var(--s-1) var(--s-3);
	border: 1px solid var(--line);
	border-radius: 99px;
	background: rgba(255, 255, 255, .04);
	font-size: 12px; font-weight: 600; color: var(--text-muted);
}

.chip .icon { width: 16px; height: 16px; color: var(--brass); }
.chip .num { color: var(--text); font-variant-numeric: tabular-nums; font-size: 14px; }

/* Ein neuer Bestwert ist die einzige Zahl, die sich selbst hervorheben darf. */
.chip.is-record {
	border-color: var(--line-strong);
	background: rgba(217, 119, 6, .1);
	color: var(--text);
}

.chip.is-record .icon { color: var(--brass-bright); }

/* Zwei Spalten, links die Frage, rechts die Antwort. Wie .review-stats, aber
   ohne Karte drumherum — die Tagesstellung hat nur zwei Zeilen. */
.kv {
	margin: 0; display: grid; grid-template-columns: 1fr auto;
	gap: var(--s-2); font-size: 13px; align-items: baseline;
}

.kv dt { color: var(--text-muted); }
.kv dd { margin: 0; font-weight: 600; text-align: end; }
/* Der Hinweis darunter ist ein eigener Gedanke, keine dritte Zeile der Liste. */
.kv + .hint { margin-top: var(--s-4); }

/* Eine Kartenzeile, die kein Knopf ist. .card-main holt sein Layout sonst vom
   Knopf; als div fiele die Zeile in Blocksatz auseinander und Icon, Text und
   Fortschritt stünden untereinander. */
.card-static {
	display: flex; align-items: center; gap: var(--s-3);
	min-height: 56px; padding: 0 var(--s-3);
}

/* Freischaltungen: die erreichten treten zurück, die offenen sind das Ziel.
   Umgekehrt wäre die Liste eine Vitrine statt einer Aufgabe. */
.card.is-done .card-title,
.card.is-done .card-meta { color: var(--text-muted); }
.card.is-done .card-main > .icon { color: var(--success); }

/* Der Fortschritt daneben trägt keine Messingfläche — die gehört dem, was
   fertig ist. */
.badge.mono {
	background: transparent; color: var(--text-muted);
	border: 1px solid var(--line);
	font-variant-numeric: tabular-nums; font-weight: 600;
}

/* Ein Hinweis, der eine Absage ist: dieselbe Größe, andere Farbe. */
.hint.warn { color: var(--danger); }
