/* ============================================================================
 * INFERNUS Blackjack — table.css
 *
 * Das Stylesheet des Tisches. Es gehoert zu render.js und wird von dort selbst
 * eingehaengt (ensureStylesheet). Wer Markup erzeugt, gestaltet es auch: JEDE
 * Klasse, die render.js schreibt, hat hier eine Regel. Genau daran ist der Tisch
 * dreimal gescheitert — .is-face-up ohne Regel heisst: keine Karte dreht sich um.
 *
 * Aufbau
 *   0  Grundlage, Marken-Token, [hidden]
 *   1  Tisch und Filz
 *   2  Dealer, Schuh, Tischuhr
 *   3  Sitzanordnung (Telefon zuerst)
 *   4  Sitzteile: Plakette, Knopf, Blase, Emote, Einsatzkreis
 *   5  Hand: Faecher, Plakette, Ergebnis, Einsatz
 *   6  Die Spielkarte
 *   7  Chips
 *   8  Flugschicht, Funken, Guthabenzahl
 *   9  Momente: Zug, Dealer-Moment, Blackjack, Bust, Gewinn
 *  10  Groessere Schirme
 *  11  Ruhige Bewegung
 *
 * Grundsaetze
 *   - Alles ist mit `.ifb-table` praefixiert. Das schlaegt game.css bei gleicher
 *     Klassentiefe und haelt die Wirkung im Tischbereich.
 *   - Bewegt werden nur transform und opacity. Nichts anderes.
 *   - Kartenmasse kommen als --card-w/--card-h aus render.js. Wie stark ein
 *     Platz skaliert, entscheidet hier --seat-cf; JS liest den Faktor ab.
 *   - Zahlen immer tabular-nums.
 * ==========================================================================*/

/* ==========================================================================
   0 — GRUNDLAGE
   ========================================================================== */

/* Bug Nummer drei war ein fehlender [hidden]-Reset: eine Regel mit hoeherer
   Spezifitaet als `[hidden]{display:none}` macht verborgene Knoten sichtbar.
   Hier wird das ein fuer alle Mal festgenagelt. */
.ifb-table [hidden] {
	display: none !important;
}

.ifb-table {
	/* --- Marke. Die Rueckfallwerte gelten auch ohne game.css. ------------- */
	--ifb-ink: var(--text, #f7f7f7);
	--ifb-ink-2: var(--text-2, #b9b9c4);
	--ifb-accent: var(--accent, #ff7a00);
	--ifb-accent-lit: var(--accent-lit, #ffb45b);
	--ifb-accent-deep: var(--accent-deep, #b34e00);
	--ifb-felt: var(--felt, #123a2c);
	--ifb-felt-lit: var(--felt-lit, #1a5040);
	--ifb-felt-deep: var(--felt-deep, #0a2419);
	--ifb-rail: var(--rail, #241a14);
	--ifb-rail-lit: var(--rail-lit, #3a2a1f);
	--ifb-paper: var(--card-paper, #f8f6f1);
	--ifb-paper-2: var(--card-paper-2, #eae6dd);
	--ifb-win: var(--win, #35c07a);
	--ifb-lose: var(--lose, #e2483c);
	--ifb-push: var(--push, #8c8ca0);

	/* Kartenrot zweimal: das grosse Zeichen darf die Markenfarbe tragen, der
	   kleine Eckindex braucht mehr Kontrast auf gebrochenem Weiss (~5:1). */
	--ifb-red: var(--card-red, #c8342b);
	--ifb-red-ink: #ac2118;
	--ifb-black-ink: #16161c;

	/* Notwerte. render.js schreibt die echten Masse inline auf dieses Element. */
	--card-w: 56px;
	--card-h: 78px;
	--seat-cf: 1;
	--tilt: 0deg;
	--chip-d: calc(var(--card-w) * 0.52);

	position: relative;
	display: block;
	box-sizing: border-box;
	width: 100%;
	height: auto;
	/* Der Tisch nimmt genau den Platz, den die Buehne ihm gibt — nicht mehr. */
	align-self: stretch;
	justify-self: stretch;
	/* Mindesthoehe bleibt bewusst bescheiden: .ifb-table liegt in einer
	   minmax(0,1fr)-Zeile unter .app mit overflow:hidden. Eine zu grosse
	   Mindesthoehe laesst den Tisch nicht wachsen, sondern ueberlaufen und
	   abgeschnitten werden. Der zusaetzliche Platz kommt deshalb aus dem
	   Beiwerk drumherum (siehe Hochformat-Block in game.css), nicht von hier. */
	min-height: clamp(300px, 46dvh, 720px);
	margin: 0;
	isolation: isolate;
	/* KEIN perspective auf der Wurzel: das machte sie zum Bezugsrahmen fuer
	   position:fixed und verschoebe die gesamte Flugschicht. Die Perspektive
	   sitzt an der einzelnen Karte. */
	perspective: none;
	color: var(--ifb-ink);
	font-family: var(--font, 'Segoe UI', system-ui, -apple-system, sans-serif);
	-webkit-tap-highlight-color: transparent;
}

.ifb-table *,
.ifb-table *::before,
.ifb-table *::after {
	box-sizing: border-box;
}

.ifb-table .sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

/* ==========================================================================
   1 — TISCH UND FILZ
   ========================================================================== */

/* Lederrand. Liegt hinter dem Filz, deshalb eigener Stapelplatz. */
.ifb-table::before {
	content: '';
	position: absolute;
	inset: -6px;
	border-radius: 22px 22px 46% 46% / 18px 18px 30% 30%;
	background: linear-gradient(180deg, var(--ifb-rail-lit), var(--ifb-rail) 42%, #14100c);
	box-shadow:
		0 16px 40px -14px rgb(0 0 0 / 0.8),
		inset 0 1px 0 rgb(255 255 255 / 0.08);
	z-index: -1;
	pointer-events: none;
}

.ifb-table .felt {
	position: absolute;
	inset: 0;
	border-radius: 18px 18px 44% 44% / 14px 14px 28% 28%;
	background:
		radial-gradient(78% 54% at 50% -4%, rgb(255 255 255 / 0.1) 0%, transparent 60%),
		radial-gradient(72% 88% at 50% 24%, var(--ifb-felt-lit) 0%, var(--ifb-felt) 46%, var(--ifb-felt-deep) 100%);
	box-shadow:
		inset 0 0 0 2px rgb(0 0 0 / 0.32),
		inset 0 2px 0 rgb(255 255 255 / 0.05),
		inset 0 -26px 54px -18px rgb(0 0 0 / 0.72);
	overflow: hidden;
}

/* --------------------------------------------------------------- Turnier --
   Derselbe Filz, aber ein anderer Rand: render.js setzt data-tournament='1',
   sobald der Zustand einen Turnierblock traegt (#reconcile). Der Modus taugt
   dafuer NICHT — der Turniertisch meldet ebenfalls 'ranked'.

   Der Anlass ist kein Geschmack: Ein Spieler kam ueber tisch/?turnier=… an
   einem freien Tisch heraus und setzte dort echte Chips, weil beide Tische
   gleich aussahen. Der violette Saum ist die Farbe des Turnierbandes oben —
   dieselbe Familie, damit beides als EINE Aussage gelesen wird. Er wiederholt
   nur, was Band, Plakette und Text ohnehin sagen; er traegt keine
   Information allein. */
.ifb-table[data-tournament='1'] .felt {
	box-shadow:
		inset 0 0 0 2px rgb(139 106 217 / 0.55),
		inset 0 2px 0 rgb(255 255 255 / 0.05),
		inset 0 -26px 54px -18px rgb(0 0 0 / 0.72);
}

/* Webstruktur und Einsatzbogen — beides nur Farbverlaeufe, kein Bild. */
.ifb-table .felt::before {
	content: '';
	position: absolute;
	inset: 0;
	background-image:
		repeating-linear-gradient(45deg, rgb(255 255 255 / 0.028) 0 1px, transparent 1px 4px),
		repeating-linear-gradient(-45deg, rgb(0 0 0 / 0.05) 0 1px, transparent 1px 4px);
	pointer-events: none;
}

/* Glutsaum. Ruht, bis der Spieler am Zug ist. */
.ifb-table .felt::after {
	content: '';
	position: absolute;
	inset: 0;
	border-radius: inherit;
	box-shadow:
		inset 0 0 0 2px rgb(255 122 0 / 0.5),
		inset 0 -30px 60px -30px rgb(255 122 0 / 0.55);
	opacity: 0;
	transition: opacity 320ms ease;
	pointer-events: none;
}

.ifb-table .table-legend {
	position: absolute;
	left: 50%;
	top: 34%;
	width: 38%;
	margin: 0;
	transform: translateX(-50%);
	text-align: center;
	font-size: clamp(8px, calc(var(--card-w) * 0.17), 13px);
	letter-spacing: 0.14em;
	text-transform: uppercase;
	font-weight: 600;
	line-height: 1.5;
	color: rgb(255 255 255 / 0.16);
	text-shadow: 0 1px 0 rgb(0 0 0 / 0.3);
	pointer-events: none;
	transition: opacity 260ms ease;
}

/* ==========================================================================
   2 — DEALER, SCHUH, TISCHUHR
   ========================================================================== */

.ifb-table .dealer {
	--seat-cf: 0.95;
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	display: flex;
	align-items: flex-start;
	justify-content: center;
	gap: calc(var(--card-w) * 0.18);
	padding: calc(var(--card-w) * 0.6) 2% 0;
	transform-origin: 50% 18%;
	transition: transform 300ms cubic-bezier(0.2, 0.9, 0.3, 1);
	z-index: 3;
}

.ifb-table .dealer-label {
	position: absolute;
	left: 50%;
	top: calc(var(--card-w) * 0.04);
	transform: translateX(-50%);
	font-size: clamp(9px, calc(var(--card-w) * 0.18), 13px);
	letter-spacing: 0.24em;
	text-transform: uppercase;
	font-weight: 700;
	/* 0.44 ergab auf --felt-lit nur 3,16:1 und auf --felt 3,74:1. "Dealer" ist
	   eine Beschriftung, keine Verzierung — 0.72 traegt 7,0:1 auf dem Filz. */
	color: rgb(255 255 255 / 0.72);
	pointer-events: none;
}

/* Der Schuh sitzt aussen rechts — von dort fliegt jede Karte los. */
.ifb-table .shoe {
	position: absolute;
	right: 2.5%;
	top: calc(var(--card-w) * 0.06);
	width: calc(var(--card-w) * 0.66);
	height: calc(var(--card-w) * 0.86);
	border-radius: 3px 3px 7px 7px;
	background: linear-gradient(158deg, #46331f 0%, #2a1e13 62%, #1a120b 100%);
	box-shadow:
		0 6px 14px -4px rgb(0 0 0 / 0.7),
		inset 0 1px 0 rgb(255 255 255 / 0.1),
		inset 0 -4px 8px -4px rgb(0 0 0 / 0.6);
	display: flex;
	align-items: flex-end;
	justify-content: center;
	padding-bottom: 2px;
	transform-origin: 50% 60%;
}

/* Der Kartenblock im Schuh. */
.ifb-table .shoe-body {
	position: absolute;
	left: 14%;
	right: 14%;
	top: 8%;
	height: 52%;
	border-radius: 2px;
	background:
		linear-gradient(180deg, rgb(255 255 255 / 0.22), transparent 40%),
		repeating-linear-gradient(90deg, var(--ifb-paper) 0 2px, #c9c3b6 2px 3px);
	box-shadow: inset 0 -3px 5px -2px rgb(0 0 0 / 0.55);
}

.ifb-table .shoe-count {
	position: relative;
	font-size: clamp(8px, calc(var(--card-w) * 0.16), 12px);
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	letter-spacing: 0.02em;
	color: var(--ifb-accent-lit);
	text-shadow: 0 1px 2px rgb(0 0 0 / 0.7);
}

.ifb-table .shoe[data-low='true'] .shoe-count {
	color: var(--ifb-lose);
}

.ifb-table .shoe[data-low='true'] .shoe-body {
	height: 26%;
}

.ifb-table .shoe.is-shuffling {
	box-shadow:
		0 6px 14px -4px rgb(0 0 0 / 0.7),
		0 0 18px -2px rgb(255 122 0 / 0.55),
		inset 0 1px 0 rgb(255 255 255 / 0.1);
}

/* --- Phasenuhr am Dealer -------------------------------------------------- */

.ifb-table .table-timer {
	position: absolute;
	left: 50%;
	top: calc(var(--card-w) * 0.36);
	width: min(190px, 46%);
	height: 5px;
	transform: translateX(-50%);
	border-radius: 999px;
	background: rgb(0 0 0 / 0.42);
	box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.1);
	overflow: visible;
}

.ifb-table .timer-fill {
	position: absolute;
	inset: 0;
	border-radius: inherit;
	background: linear-gradient(90deg, var(--ifb-accent-deep), var(--ifb-accent) 45%, var(--ifb-accent-lit));
	transform-origin: left center;
	/* --t kommt aus render.js und laeuft von 1 nach 0. Nur transform. */
	transform: scaleX(var(--t, 1));
}

.ifb-table .timer-text {
	position: absolute;
	right: 0;
	bottom: 7px;
	font-size: 11px;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	color: var(--ifb-accent-lit);
	text-shadow: 0 1px 2px rgb(0 0 0 / 0.8);
}

.ifb-table [data-urgent='true'] .timer-fill {
	background: linear-gradient(90deg, #8c1a12, var(--ifb-lose));
}

.ifb-table [data-urgent='true'] .timer-text {
	color: var(--ifb-lose);
	animation: ifb-throb 640ms ease-in-out infinite alternate;
}

@keyframes ifb-throb {
	from {
		transform: scale(1);
		opacity: 0.75;
	}
	to {
		transform: scale(1.16);
		opacity: 1;
	}
}

/* ==========================================================================
   3 — SITZANORDNUNG
   Telefon zuerst. 412 x 915 CSS-Pixel, hochkant, Tischflaeche rund 380 x 430.
   Fuenf Sitze passen dort NICHT auf einen Kreisbogen — der Bogen draengt die
   Aussensitze aus dem Bild, genau das war der Fehlerbericht. Stattdessen zwei
   Saeulen: die beiden fernen Nachbarn oben aussen, die beiden nahen darunter,
   der eigene Sitz ueber die volle Breite unten. Naeher am Spieler heisst weiter
   unten und groesser — die Sitzreihenfolge am Tisch bleibt lesbar, und alles
   Wichtige liegt in der unteren Bildschirmhaelfte.
   ========================================================================== */

.ifb-table .seats {
	position: absolute;
	inset: 0;
	z-index: 2;
}

.ifb-table .seat {
	position: absolute;
	left: 50%;
	top: 50%;
	z-index: 1;
	display: grid;
	justify-items: center;
	align-content: start;
	gap: 3px;
	width: 30%;
	/* left/top bezeichnen die MITTE des Sitzes: spiegeln wird damit trivial. */
	transform: translateX(-50%);
	transition: opacity 240ms ease;
}

.ifb-table .seat:focus-visible {
	outline: 2px solid var(--ifb-accent-lit);
	outline-offset: 4px;
	border-radius: 12px;
}

/* Relativplaetze: 0 = ich, 1/2 rechts herum, 4/3 links herum. */
.ifb-table .seat--rel3,
.ifb-table .seat--rel2 {
	--seat-cf: 0.7;
	top: 23%;
	width: 29%;
}

.ifb-table .seat--rel3 {
	left: 16%;
}

.ifb-table .seat--rel2 {
	left: 84%;
}

.ifb-table .seat--rel4,
.ifb-table .seat--rel1 {
	--seat-cf: 0.78;
	top: 46%;
	width: 31%;
}

.ifb-table .seat--rel4 {
	left: 18%;
}

.ifb-table .seat--rel1 {
	left: 82%;
}

/* Der eigene Sitz: unten mittig, volle Breite, groesste Karten. */
.ifb-table .seat--rel0 {
	--seat-cf: 1;
	left: 50%;
	top: auto;
	bottom: calc(var(--card-w) * 0.12);
	width: min(96%, 420px);
	align-content: end;
	z-index: 4;
}

/* Der eigene Platz. Er ist fast immer rel0 — aber eben nur fast: ein Zuschauer
   hat gar keinen, und nach einem Sitzwechsel gilt die Klasse vor der Position. */
.ifb-table .seat.is-own .seat-plate {
	background: linear-gradient(160deg, rgb(255 122 0 / 0.22), rgb(10 10 14 / 0.72));
	box-shadow:
		inset 0 0 0 1.5px rgb(255 122 0 / 0.45),
		0 2px 8px -2px rgb(0 0 0 / 0.7);
}

.ifb-table .seat.is-own .seat-spot {
	box-shadow: inset 0 0 0 2px rgb(255 255 255 / 0.16);
}

.ifb-table .seat.is-empty {
	opacity: 0.72;
}

.ifb-table .seat.is-offline {
	opacity: 0.42;
	filter: grayscale(0.7);
}

.ifb-table .seat.is-active {
	z-index: 5;
	opacity: 1;
	filter: none;
}

/* Glutkreis unter dem Sitz, der am Zug ist. */
.ifb-table .seat.is-active::before {
	content: '';
	position: absolute;
	left: 50%;
	top: 45%;
	width: 118%;
	aspect-ratio: 1.7;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background: radial-gradient(ellipse at 50% 50%, rgb(255 122 0 / 0.34) 0%, transparent 66%);
	z-index: -1;
	pointer-events: none;
	animation: ifb-halo 1500ms ease-in-out infinite alternate;
}

@keyframes ifb-halo {
	from {
		transform: translate(-50%, -50%) scale(0.9);
		opacity: 0.55;
	}
	to {
		transform: translate(-50%, -50%) scale(1.08);
		opacity: 1;
	}
}

/* ==========================================================================
   4 — SITZTEILE
   ========================================================================== */

/* Der Einsatzkreis auf dem Filz: Anker fuer Chips, Karten und leere Plaetze. */
.ifb-table .seat-spot {
	position: absolute;
	left: 50%;
	top: calc(var(--card-h) * 0.22);
	width: calc(var(--card-w) * 1.75);
	height: calc(var(--card-w) * 0.72);
	transform: translateX(-50%);
	border-radius: 50%;
	background: radial-gradient(ellipse at 50% 42%, rgb(255 255 255 / 0.05), transparent 72%);
	box-shadow: inset 0 0 0 1.5px rgb(255 255 255 / 0.1);
	z-index: -1;
	pointer-events: none;
}

.ifb-table .seat--rel0 .seat-spot {
	top: auto;
	bottom: calc(var(--card-h) * 0.28);
}

.ifb-table .seat.is-empty .seat-spot {
	box-shadow: inset 0 0 0 1.5px rgb(255 255 255 / 0.06);
}

.ifb-table[data-phase='betting'] .seat-spot {
	box-shadow: inset 0 0 0 2px rgb(255 122 0 / 0.4);
}

.ifb-table .seat-hands {
	display: flex;
	align-items: flex-start;
	justify-content: center;
	gap: calc(var(--card-w) * 0.22);
	min-height: var(--card-h);
}

.ifb-table .seat.is-empty .seat-hands {
	min-height: 0;
}

/* Geteilte Haende an fremden Plaetzen brauchen mehr Breite, als die Saeule
   hergibt — dort wird die Gruppe verkleinert statt den Nachbarn zu ueberlappen. */
.ifb-table .seat:not(.is-own) .seat-hands[data-count='2'] {
	transform: scale(0.82);
}

.ifb-table .seat:not(.is-own) .seat-hands[data-count='3'],
.ifb-table .seat:not(.is-own) .seat-hands[data-count='4'] {
	transform: scale(0.66);
}

/* --- Namensplakette ------------------------------------------------------ */

.ifb-table .seat-plate {
	position: relative;
	display: flex;
	align-items: center;
	gap: 6px;
	max-width: 100%;
	padding: 3px 9px;
	border-radius: 999px;
	background: rgb(10 10 14 / 0.66);
	box-shadow:
		inset 0 0 0 1px rgb(255 255 255 / 0.1),
		0 2px 6px -2px rgb(0 0 0 / 0.6);
	font-size: clamp(10px, calc(var(--card-w) * 0.2), 14px);
	line-height: 1.35;
}

.ifb-table .seat.is-active .seat-plate {
	box-shadow:
		inset 0 0 0 1.5px rgb(255 122 0 / 0.65),
		0 0 14px -2px rgb(255 122 0 / 0.5);
}

.ifb-table .seat-name {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	max-width: 10ch;
	font-weight: 700;
	color: var(--ifb-ink);
}

.ifb-table .seat-balance {
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	color: var(--ifb-accent-lit);
}

.ifb-table .seat-balance::before {
	content: '';
	display: inline-block;
	width: 0.62em;
	height: 0.62em;
	margin-right: 0.34em;
	border-radius: 50%;
	background: linear-gradient(145deg, var(--ifb-accent-lit), var(--ifb-accent-deep));
	vertical-align: -0.02em;
}

/* Bereitschaft: ein ruhiger Punkt, kein Text. */
.ifb-table .seat.is-ready .seat-plate::after {
	content: '';
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--ifb-win);
	box-shadow: 0 0 6px -1px var(--ifb-win);
	flex: none;
}

/* --- Uhr am Sitz --------------------------------------------------------- */

.ifb-table .seat-timer {
	position: absolute;
	left: 8%;
	right: 8%;
	bottom: -6px;
	height: 4px;
	border-radius: 999px;
	background: rgb(0 0 0 / 0.5);
	box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.1);
}

.ifb-table .seat-timer .timer-text {
	right: 50%;
	bottom: 6px;
	transform: translateX(50%);
	font-size: clamp(9px, calc(var(--card-w) * 0.18), 12px);
}

/* --- Freier Platz -------------------------------------------------------- */

.ifb-table .seat-join {
	appearance: none;
	border: 0;
	margin: 0;
	min-height: 44px;
	padding: 0 14px;
	border-radius: 999px;
	background: rgb(255 122 0 / 0.14);
	color: var(--ifb-accent-lit);
	box-shadow: inset 0 0 0 1.5px rgb(255 122 0 / 0.42);
	font: inherit;
	font-weight: 700;
	font-size: clamp(11px, calc(var(--card-w) * 0.21), 14px);
	letter-spacing: 0.02em;
	cursor: pointer;
	transition:
		transform 120ms ease,
		background-color 160ms ease;
}

.ifb-table .seat-join:hover {
	background: rgb(255 122 0 / 0.24);
}

.ifb-table .seat-join:active {
	transform: scale(0.95);
}

.ifb-table .seat-join:focus-visible {
	outline: 2px solid var(--ifb-accent-lit);
	outline-offset: 3px;
}

/* --- Sprechblase und Emote ----------------------------------------------- */

.ifb-table .seat-bubble {
	position: absolute;
	left: 50%;
	bottom: calc(100% + 2px);
	transform: translateX(-50%);
	padding: 3px 10px;
	border-radius: 999px;
	white-space: nowrap;
	background: linear-gradient(160deg, #2a2a35, #16161c);
	box-shadow:
		inset 0 0 0 1px rgb(255 255 255 / 0.12),
		0 4px 10px -3px rgb(0 0 0 / 0.7);
	font-size: clamp(10px, calc(var(--card-w) * 0.2), 14px);
	font-weight: 700;
	color: var(--ifb-ink);
	z-index: 20;
	pointer-events: none;
}

.ifb-table .seat-bubble[data-kind='double'],
.ifb-table .seat-bubble[data-kind='split'] {
	color: var(--ifb-accent-lit);
	box-shadow:
		inset 0 0 0 1px rgb(255 122 0 / 0.55),
		0 4px 10px -3px rgb(0 0 0 / 0.7);
}

/* --ifb-push (#8c8ca0) auf der hellen Kante der Blase (#2a2a35) sind nur
   4,30:1. Derselbe helle Ton, den das Ergebnisband fuer "unentschieden"
   benutzt, traegt 9,8:1. */
.ifb-table .seat-bubble[data-kind='surrender'] {
	color: #d6d6e2;
}

.ifb-table .seat-emote {
	position: absolute;
	left: calc(100% - var(--card-w) * 0.3);
	top: 0;
	font-size: clamp(18px, calc(var(--card-w) * 0.46), 34px);
	line-height: 1;
	filter: drop-shadow(0 2px 4px rgb(0 0 0 / 0.6));
	z-index: 21;
	pointer-events: none;
}

/* Die rechte Saeule steht am Bildrand: bei 412 Pixeln endet Sitz 2 auf 405,
   und ein Zeichen, das rechts ueber die Sitzkante hinausragt, wird von der
   Buehne abgeschnitten (bei 360 Pixeln fehlten rund 5). Rechts wird deshalb
   nach innen gespiegelt — dorthin, wo ohnehin der Tisch liegt. */
.ifb-table .seat--rel1 .seat-emote,
.ifb-table .seat--rel2 .seat-emote {
	left: auto;
	right: calc(var(--card-w) * -0.1);
}

/* --- Noch nicht bestaetigter Einsatz ------------------------------------- */

.ifb-table .seat-pending {
	position: absolute;
	left: 50%;
	top: calc(var(--card-h) * 0.2);
	transform: translateX(-50%);
	display: grid;
	justify-items: center;
	gap: 2px;
	z-index: 6;
	pointer-events: none;
}

.ifb-table .seat--rel0 .seat-pending {
	top: auto;
	bottom: calc(var(--card-h) * 0.3);
}

/* ==========================================================================
   5 — DIE HAND
   Der Faecher traegt die Breite; Plakette, Ergebnis und Einsatz haengen
   absolut daran. So waechst die Hand nur zur Seite und nie nach unten — auf
   dem Telefon ist die Hoehe das knappe Gut.
   ========================================================================== */

.ifb-table .hand {
	position: relative;
	display: block;
	transition: opacity 240ms ease;
}

.ifb-table .hand.is-done {
	opacity: 0.88;
}

.ifb-table .hand.is-surrendered {
	opacity: 0.5;
}

.ifb-table .hand-fan {
	position: relative;
	z-index: 0;
	/* Breite aus Kartenzahl (--n von render.js) und Faecherversatz. Der Versatz
	   steht in --fan-dx und wird von render.js aus DIESER Regel gelesen — beide
	   Seiten nutzen also dieselbe Zahl, sie koennen nicht mehr auseinanderlaufen. */
	--fan-dx: 0.3;
	width: calc(var(--card-w) * (1 + var(--fan-dx) * (var(--n, 1) - 1)));
	height: calc(var(--card-h) * 1.14);
	transform: rotate(var(--tilt, 0deg));
	transform-origin: 50% 80%;
}

/* Aktive Hand: ein warmer Schein unter den Karten. */
.ifb-table .hand.is-active .hand-fan::before {
	content: '';
	position: absolute;
	inset: -10% -14%;
	border-radius: 14px;
	background: radial-gradient(ellipse at 50% 60%, rgb(255 122 0 / 0.3), transparent 70%);
	z-index: -1;
	pointer-events: none;
}

/* --- Handsumme ----------------------------------------------------------- */

.ifb-table .hand-badge {
	position: absolute;
	left: 100%;
	top: calc(var(--card-h) * 0.06);
	transform: translate(-45%, 0);
	min-width: 2.1em;
	padding: 2px 6px;
	border-radius: 999px;
	text-align: center;
	font-size: clamp(11px, calc(var(--card-w) * 0.26), 18px);
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	line-height: 1.2;
	letter-spacing: -0.01em;
	background: linear-gradient(160deg, #23232c, #101015);
	color: var(--ifb-ink);
	box-shadow:
		inset 0 0 0 1.5px rgb(255 255 255 / 0.16),
		0 3px 8px -2px rgb(0 0 0 / 0.7);
	z-index: 30;
	pointer-events: none;
}

/* Weiche Summe steht als "17/7" — beide Lesarten auf einen Blick. */
.ifb-table .hand-badge[data-state='soft'] {
	color: #9ed0ff;
	box-shadow:
		inset 0 0 0 1.5px rgb(74 163 255 / 0.5),
		0 3px 8px -2px rgb(0 0 0 / 0.7);
}

.ifb-table .hand-badge[data-state='bust'] {
	background: linear-gradient(160deg, #6d1e18, #3a100c);
	color: #ffd7d3;
	box-shadow:
		inset 0 0 0 1.5px rgb(226 72 60 / 0.7),
		0 3px 8px -2px rgb(0 0 0 / 0.7);
}

.ifb-table .hand-badge[data-state='blackjack'] {
	background: linear-gradient(150deg, var(--ifb-accent-lit), var(--ifb-accent) 55%, var(--ifb-accent-deep));
	color: #23140a;
	box-shadow:
		inset 0 0 0 1.5px rgb(255 214 160 / 0.8),
		0 0 16px -2px rgb(255 122 0 / 0.7);
}

/* Der Dealerfaecher steht immer gerade — der Dealer sitzt nicht auf dem Bogen. */
.ifb-table .dealer-fan {
	--tilt: 0deg;
	margin-top: calc(var(--card-w) * 0.2);
}

/* Die Dealerplakette laeuft in der Reihe mit, nicht an der Ecke. */
.ifb-table .dealer-badge {
	position: static;
	transform: none;
	margin-top: calc(var(--card-h) * 0.3);
}

/* --- Ergebnisband -------------------------------------------------------- */

.ifb-table .hand-flag {
	position: absolute;
	left: 50%;
	/* Mitte der KARTEN, nicht Mitte der Handbox: unter dem Faecher haengen noch
	   Summenplakette und Einsatzchips, ein prozentualer Wert rutschte dadurch
	   optisch nach unten aus der Kartenflaeche heraus. */
	top: calc(var(--card-h) * 0.5);
	transform: translate(-50%, -50%);
	padding: 4px 10px;
	border-radius: 999px;
	white-space: nowrap;
	font-size: clamp(10px, calc(var(--card-w) * 0.23), 16px);
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	letter-spacing: 0.02em;
	background: rgb(8 8 11 / 0.88);
	color: var(--ifb-ink);
	box-shadow:
		inset 0 0 0 1.5px rgb(255 255 255 / 0.16),
		0 4px 12px -3px rgb(0 0 0 / 0.8);
	z-index: 40;
	pointer-events: none;
}

.ifb-table .hand-flag[data-tone='win'] {
	color: #ffd9a8;
	box-shadow:
		inset 0 0 0 1.5px rgb(255 122 0 / 0.75),
		0 0 18px -3px rgb(255 122 0 / 0.6);
}

.ifb-table .hand-flag[data-tone='lose'] {
	color: #ffd0cb;
	box-shadow:
		inset 0 0 0 1.5px rgb(226 72 60 / 0.6),
		0 4px 12px -3px rgb(0 0 0 / 0.8);
}

.ifb-table .hand-flag[data-tone='push'] {
	color: #d6d6e2;
	box-shadow:
		inset 0 0 0 1.5px rgb(140 140 160 / 0.5),
		0 4px 12px -3px rgb(0 0 0 / 0.8);
}

/* --- Einsatz an der Hand ------------------------------------------------- */

.ifb-table .hand-bet {
	position: absolute;
	right: 100%;
	bottom: calc(var(--card-h) * 0.06);
	transform: translateX(38%);
	display: grid;
	justify-items: center;
	gap: 2px;
	z-index: 12;
	pointer-events: none;
}

.ifb-table .hand.is-doubled .hand-bet .chip-amount {
	color: var(--ifb-accent-lit);
	box-shadow: inset 0 0 0 1.5px rgb(255 122 0 / 0.6);
}

/* ==========================================================================
   6 — DIE SPIELKARTE
   Alle Karten liegen deckungsgleich im Faecher; den Versatz macht render.js
   ueber transform. Deshalb absolut positioniert — sonst stapelten sie sich
   untereinander und der Faecher waere sinnlos.
   ========================================================================== */

.ifb-table .card {
	position: absolute;
	left: 0;
	top: calc(var(--card-h) * 0.12);
	width: var(--card-w);
	height: var(--card-h);
	/* Perspektive an der Karte, NICHT am Tisch: sonst wird die Wurzel zum
	   Bezugsrahmen fuer die fest positionierte Flugschicht. */
	perspective: calc(var(--card-w) * 15);
	transform-origin: 50% 100%;
	/* Traegt Eckindex und Zeichen: eine Zahl, alles andere haengt daran. */
	font-size: calc(var(--card-w) * 0.27);
	font-variant-numeric: tabular-nums;
	transition: opacity 240ms ease;
}

.ifb-table .card-inner {
	position: relative;
	width: 100%;
	height: 100%;
	border-radius: 8%;
	transform-style: preserve-3d;
	transform: rotateY(0deg);
	box-shadow:
		0 1px 2px rgb(0 0 0 / 0.45),
		0 6px 14px -4px rgb(0 0 0 / 0.55);
}

/*  D I E   R E G E L .
    Ohne sie dreht sich keine Karte je um — genau das war der Befund. Die
    Wendung selbst laeuft ueber die Web Animations API; diese Zeile haelt den
    Endzustand und deckt jeden Weg ab, der ohne Animation dort ankommt
    (Abgleich nach Wiederverbindung, Flush, sofortiger Zustandssprung). */
.ifb-table .card.is-face-up .card-inner {
	transform: rotateY(180deg);
}

.ifb-table .card-face {
	position: absolute;
	inset: 0;
	display: block;
	border-radius: 8%;
	overflow: hidden;
	backface-visibility: hidden;
	-webkit-backface-visibility: hidden;
}

/* --- Vorderseite --------------------------------------------------------- */

.ifb-table .card-face--front {
	transform: rotateY(180deg);
	background:
		radial-gradient(120% 88% at 22% 2%, #fffefb 0%, transparent 58%),
		linear-gradient(158deg, var(--ifb-paper) 0%, var(--ifb-paper-2) 100%);
	color: var(--ifb-black-ink);
	box-shadow:
		inset 0 0 0 1px rgb(0 0 0 / 0.18),
		inset 0 0 0 2px rgb(255 255 255 / 0.7);
}

.ifb-table .card[data-color='red'] .card-face--front {
	color: var(--ifb-red-ink);
}

/* Feine Innenlinie — macht aus dem Rechteck eine Karte. */
.ifb-table .card-face--front::before {
	content: '';
	position: absolute;
	inset: 5%;
	border-radius: 4%;
	box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.07);
	pointer-events: none;
}

/*  Eckindex. render.js setzt "A\n♠" in einen einzigen Textknoten — ohne
    white-space: pre-line liefen Rang und Zeichen in einer Zeile zusammen und
    die Ecke waere unlesbar. Das ist die zweite Zeile, an der dieser Tisch
    schon einmal gescheitert ist. */
.ifb-table .card-corner {
	position: absolute;
	display: block;
	white-space: pre-line;
	text-align: center;
	line-height: 0.88;
	font-size: 1em;
	font-weight: 800;
	letter-spacing: -0.04em;
	color: inherit;
	text-shadow: 0 1px 0 rgb(255 255 255 / 0.55);
	pointer-events: none;
}

.ifb-table .card-corner--tl {
	top: 5%;
	left: 7%;
}

.ifb-table .card-corner--br {
	bottom: 5%;
	right: 7%;
	transform: rotate(180deg);
}

/* Grosses Farbzeichen in der Mitte. Es traegt die Form — und Form, nicht
   Farbe, unterscheidet die Farben bei Farbfehlsichtigkeit. */
.ifb-table .card-pip {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	font-size: calc(var(--card-w) * 0.52);
	line-height: 1;
	opacity: 0.96;
	pointer-events: none;
}

.ifb-table .card[data-color='red'] .card-pip {
	color: var(--ifb-red);
}

/* Bild- und Assblatt: das Zeichen tritt zurueck, der Rang steht im Vordergrund. */
.ifb-table .card[data-rank='A'] .card-pip {
	font-size: calc(var(--card-w) * 0.62);
}

.ifb-table .card[data-rank='J'] .card-pip,
.ifb-table .card[data-rank='Q'] .card-pip,
.ifb-table .card[data-rank='K'] .card-pip {
	font-size: calc(var(--card-w) * 0.4);
	opacity: 0.8;
}

.ifb-table .card[data-rank='J'] .card-face--front,
.ifb-table .card[data-rank='Q'] .card-face--front,
.ifb-table .card[data-rank='K'] .card-face--front {
	background:
		radial-gradient(120% 88% at 22% 2%, #fffefb 0%, transparent 58%),
		repeating-linear-gradient(45deg, rgb(0 0 0 / 0.022) 0 2px, transparent 2px 5px),
		linear-gradient(158deg, var(--ifb-paper) 0%, var(--ifb-paper-2) 100%);
}

/* --- Rueckseite ---------------------------------------------------------- */

.ifb-table .card-face--back {
	transform: rotateY(0deg);
	background-color: #1d1116;
	background-image:
		radial-gradient(circle at 50% 46%, rgb(255 122 0 / 0.32) 0%, transparent 48%),
		repeating-linear-gradient(45deg, rgb(255 122 0 / 0.16) 0 2px, transparent 2px 7px),
		repeating-linear-gradient(-45deg, rgb(255 180 91 / 0.11) 0 2px, transparent 2px 7px),
		linear-gradient(160deg, #2a1520, #170d12 65%, #0f0a0d);
	box-shadow:
		inset 0 0 0 2px rgb(248 246 241 / 0.9),
		inset 0 0 0 3px rgb(0 0 0 / 0.35),
		inset 0 0 16px rgb(0 0 0 / 0.6);
}

/* Das Glutwappen in der Mitte der Rueckseite. */
.ifb-table .card-back-art {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 44%;
	aspect-ratio: 1;
	transform: translate(-50%, -50%) rotate(45deg);
	border-radius: 18%;
	background:
		radial-gradient(circle at 34% 30%, var(--ifb-accent-lit), transparent 62%),
		linear-gradient(145deg, var(--ifb-accent), var(--ifb-accent-deep));
	box-shadow:
		0 0 12px -3px rgb(255 122 0 / 0.8),
		inset 0 0 0 1px rgb(0 0 0 / 0.3);
	pointer-events: none;
}

/* Waehrend der Wendung liegt die Karte oben. */
.ifb-table .card.is-flipping {
	z-index: 60 !important;
}

/* ==========================================================================
   7 — CHIPS
   ========================================================================== */

.ifb-table .chip-stack {
	position: relative;
	width: var(--chip-d);
	height: var(--chip-d);
}

.ifb-table .chip-stack .chip {
	position: absolute;
	left: 0;
	bottom: 0;
}

.ifb-table .chip {
	--cb: #f0efea;
	--ce: #b9bcc6;
	--ci: #17171d;
	width: var(--chip-d);
	height: var(--chip-d);
	min-width: 22px;
	min-height: 22px;
	border-radius: 50%;
	display: grid;
	place-items: center;
	/* Innere Scheibe und acht Randmarken, alles aus Verlaeufen. */
	background:
		radial-gradient(circle at 50% 50%, var(--cb) 0 57%, transparent 57.5%),
		repeating-conic-gradient(from 11.25deg, var(--ce) 0deg 22.5deg, var(--cb) 22.5deg 45deg);
	color: var(--ci);
	font-size: calc(var(--chip-d) * 0.34);
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	line-height: 1;
	box-shadow:
		inset 0 0 0 1px rgb(0 0 0 / 0.28),
		0 1px 2px rgb(0 0 0 / 0.5);
}

.ifb-table .chip--d1 {
	--cb: #f0efea;
	--ce: #b9bcc6;
	--ci: #17171d;
}

.ifb-table .chip--d5 {
	--cb: #c8342b;
	--ce: #f4f2ee;
	--ci: #fff6f4;
}

.ifb-table .chip--d25 {
	--cb: #1c7a4d;
	--ce: #f4f2ee;
	--ci: #f2fff8;
}

.ifb-table .chip--d100 {
	--cb: #1a1a22;
	--ce: #f4f2ee;
	--ci: #f7f7f7;
}

.ifb-table .chip--d500 {
	--cb: #6d3bbf;
	--ce: #f4f2ee;
	--ci: #f6f1ff;
}

.ifb-table .chip--d1000 {
	--cb: #ff7a00;
	--ce: #ffd9a8;
	--ci: #2a1400;
}

.ifb-table .chip-amount {
	padding: 1px 6px;
	border-radius: 999px;
	background: rgb(8 8 11 / 0.8);
	color: var(--ifb-ink);
	font-size: clamp(9px, calc(var(--card-w) * 0.19), 13px);
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.14);
}

.ifb-table .chip-insurance {
	padding: 1px 6px;
	border-radius: 999px;
	background: rgb(74 163 255 / 0.18);
	color: #9ed0ff;
	font-size: clamp(9px, calc(var(--card-w) * 0.17), 12px);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	box-shadow: inset 0 0 0 1px rgb(74 163 255 / 0.45);
}

/* ==========================================================================
   8 — FLUGSCHICHT, FUNKEN, ZAHLEN
   ========================================================================== */

.ifb-table .fx-layer {
	position: fixed;
	inset: 0;
	z-index: 80;
	overflow: hidden;
	pointer-events: none;
}

.ifb-table .fx-piece {
	position: absolute;
	left: 0;
	top: 0;
	will-change: transform, opacity;
}

/* Der fliegende Doppelgaenger. render.js setzt Breite, Hoehe und --card-w
   inline, damit seine Schrift zur Zielgroesse passt. */
.ifb-table .fx-card {
	position: absolute;
	transform-origin: 50% 50%;
}

.ifb-table .fx-particles {
	position: absolute;
	inset: 0;
	z-index: 70;
	pointer-events: none;
}

/* Guthabenaenderung, die ueber der Plakette aufsteigt. */
.ifb-table .delta-float {
	padding: 3px 10px;
	border-radius: 999px;
	white-space: nowrap;
	font-size: 15px;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	background: rgb(8 8 11 / 0.86);
	box-shadow: 0 4px 12px -3px rgb(0 0 0 / 0.8);
}

.ifb-table .delta-float[data-sign='plus'] {
	color: #ffd9a8;
	box-shadow:
		inset 0 0 0 1.5px rgb(255 122 0 / 0.7),
		0 0 16px -3px rgb(255 122 0 / 0.6);
}

.ifb-table .delta-float[data-sign='minus'] {
	color: #ffd0cb;
	box-shadow: inset 0 0 0 1.5px rgb(226 72 60 / 0.55);
}

/* ==========================================================================
   9 — MOMENTE
   ========================================================================== */

/* --- Ich bin am Zug ------------------------------------------------------ */

.ifb-table.is-own-turn .felt::after {
	opacity: 1;
	animation: ifb-breathe 2200ms ease-in-out infinite alternate;
}

@keyframes ifb-breathe {
	from {
		opacity: 0.55;
	}
	to {
		opacity: 1;
	}
}

/* --- Der Dealer-Moment ---------------------------------------------------
   Wenn die Lochkarte faellt, tritt der ganze Tisch einen Schritt zurueck: die
   Sitze verlieren an Licht, der Aufdruck verschwindet fast, der Dealerplatz
   waechst. Danach kommt alles zurueck. Nur opacity und transform. */

.ifb-table .seats {
	transition: opacity 300ms ease;
}

.ifb-table.is-dealer-moment .seats {
	opacity: 0.36;
}

.ifb-table.is-dealer-moment .table-legend {
	opacity: 0.08;
}

.ifb-table.is-dealer-moment .dealer {
	transform: scale(1.09);
}

.ifb-table.is-dealer-moment .dealer-label {
	color: var(--ifb-accent-lit);
}

/* --- Blackjack ----------------------------------------------------------- */

.ifb-table .hand.is-blackjack .hand-fan::after {
	content: '';
	position: absolute;
	inset: -18% -22%;
	border-radius: 20px;
	background: radial-gradient(ellipse at 50% 50%, rgb(255 122 0 / 0.55) 0%, rgb(255 122 0 / 0.15) 45%, transparent 72%);
	z-index: -1;
	pointer-events: none;
	animation: ifb-ember 1400ms cubic-bezier(0.2, 0.8, 0.3, 1) both;
}

@keyframes ifb-ember {
	0% {
		transform: scale(0.6);
		opacity: 0;
	}
	22% {
		transform: scale(1.14);
		opacity: 1;
	}
	100% {
		transform: scale(1);
		opacity: 0.72;
	}
}

/* --- Ueberkauft ----------------------------------------------------------
   Spuerbar, aber nicht bestrafend: die Karten treten zurueck, mehr nicht. */

.ifb-table .hand.is-bust .card {
	opacity: 0.66;
}

.ifb-table .hand.is-bust .hand-fan::after {
	content: '';
	position: absolute;
	inset: -12%;
	border-radius: 16px;
	background: radial-gradient(ellipse at 50% 50%, rgb(226 72 60 / 0.28), transparent 70%);
	z-index: -1;
	pointer-events: none;
}

/* --- Gewinn und Unentschieden -------------------------------------------- */

.ifb-table .hand.is-win .hand-fan::after {
	content: '';
	position: absolute;
	inset: -14%;
	border-radius: 18px;
	background: radial-gradient(ellipse at 50% 55%, rgb(255 122 0 / 0.34), transparent 70%);
	z-index: -1;
	pointer-events: none;
}

.ifb-table .hand.is-lose .card {
	opacity: 0.78;
}

/* Unentschieden bleibt bewusst still: kein Schein, keine Bewegung. */
.ifb-table .hand.is-push {
	opacity: 0.94;
}

/* ==========================================================================
   9b — FLACHER TISCH
   Unter 360 px Hoehe passen Dealerband, zwei Nachbarreihen und der eigene Sitz
   nicht mehr uebereinander (render.js setzt dann data-compact). Statt Sitze zu
   opfern ruecken die fremden Plaketten NEBEN ihre Karten — das spart je Reihe
   die Hoehe einer Plakette — und das Dealerband wird schmaler. Sichtbar bleibt
   alles; der eigene Sitz liegt oben auf.
   ========================================================================== */

.ifb-table[data-compact='true'] .dealer {
	padding-top: calc(var(--card-w) * 0.42);
}

.ifb-table[data-compact='true'] .dealer-label {
	left: 4%;
	transform: none;
}

.ifb-table[data-compact='true'] .table-legend {
	display: none;
}

.ifb-table[data-compact='true'] .seat:not(.is-own) {
	grid-auto-flow: column;
	align-items: center;
	align-content: center;
	gap: 5px;
	width: 38%;
}

.ifb-table[data-compact='true'] .seat:not(.is-own) .seat-name {
	max-width: 6ch;
}

.ifb-table[data-compact='true'] .seat--rel3,
.ifb-table[data-compact='true'] .seat--rel2 {
	top: 27%;
}

.ifb-table[data-compact='true'] .seat--rel3 {
	left: 20%;
}

.ifb-table[data-compact='true'] .seat--rel2 {
	left: 80%;
}

.ifb-table[data-compact='true'] .seat--rel4,
.ifb-table[data-compact='true'] .seat--rel1 {
	top: 49%;
}

.ifb-table[data-compact='true'] .seat--rel4 {
	left: 21%;
}

.ifb-table[data-compact='true'] .seat--rel1 {
	left: 79%;
}

/* ==========================================================================
   10 — GROESSERE SCHIRME
   Ab hier passt der echte Bogen. Der eigene Sitz bleibt unten mittig, die
   Nachbarn wandern auf die Ellipse, und die Haende duerfen sich neigen.
   ========================================================================== */

@media (min-width: 620px) {
	.ifb-table .seat {
		/* Erst hier traegt die Neigung; hochkant staende sie quer zur Saeule. */
		--tilt: var(--seat-tilt, 0deg);
		width: 22%;
	}

	.ifb-table .seat--rel3,
	.ifb-table .seat--rel2 {
		--seat-cf: 0.84;
		top: 27%;
		width: 21%;
	}

	.ifb-table .seat--rel3 {
		left: 11%;
	}

	.ifb-table .seat--rel2 {
		left: 89%;
	}

	.ifb-table .seat--rel4,
	.ifb-table .seat--rel1 {
		--seat-cf: 0.9;
		top: 50%;
		width: 22%;
	}

	.ifb-table .seat--rel4 {
		left: 27%;
	}

	.ifb-table .seat--rel1 {
		left: 73%;
	}

	.ifb-table .seat--rel0 {
		width: min(42%, 460px);
	}

	.ifb-table .table-legend {
		top: 33%;
		width: 46%;
		font-size: clamp(10px, calc(var(--card-w) * 0.15), 14px);
	}
}

@media (min-width: 1024px) {
	.ifb-table .seat--rel3,
	.ifb-table .seat--rel2 {
		--seat-cf: 0.9;
		top: 30%;
	}

	.ifb-table .seat--rel4,
	.ifb-table .seat--rel1 {
		--seat-cf: 0.95;
		top: 54%;
	}

	.ifb-table .seat--rel0 {
		bottom: calc(var(--card-w) * 0.2);
	}
}

/* Querformat auf dem Telefon: kaum Hoehe, dafuer Breite. Die Saeulen werden
   flacher, alle vier Nachbarn ruecken in eine Reihe neben den Dealer. */
@media (orientation: landscape) and (max-height: 520px) {
	.ifb-table {
		min-height: 240px;
	}

	.ifb-table .seat--rel3,
	.ifb-table .seat--rel2 {
		--seat-cf: 0.72;
		top: 16%;
		width: 20%;
	}

	.ifb-table .seat--rel3 {
		left: 12%;
	}

	.ifb-table .seat--rel2 {
		left: 88%;
	}

	.ifb-table .seat--rel4,
	.ifb-table .seat--rel1 {
		--seat-cf: 0.8;
		top: 48%;
		width: 20%;
	}

	.ifb-table .seat--rel4 {
		left: 26%;
	}

	.ifb-table .seat--rel1 {
		left: 74%;
	}

	.ifb-table .seat--rel0 {
		width: min(44%, 380px);
	}

	.ifb-table .table-legend {
		display: none;
	}

	/* Quer ist der Tisch immer flach genug fuer data-compact (bei 915 x 412
	   bleiben 252 Pixel Tischhoehe, die Schwelle liegt bei 360). Der
	   Kompaktblock oben ist mit dem Attributselektor spezifischer als die
	   Regeln dieser Abfrage und setzt die Reihen sonst auf 27 und 49 Prozent
	   zurueck — bei 252 Pixeln beginnt der eigene Sitz aber schon bei 63
	   Prozent, und die nahe Nachbarreihe ragte 13 Pixel in seinen Kasten.
	   Deshalb hier dieselbe Spezifitaet und zwei flachere Reihen: 14 und 38
	   Prozent lassen zwischen Nachbarreihe und eigenem Sitz 12 Pixel Luft.
	   Die Anordnung selbst — Plakette neben den Karten — bleibt, sie spart
	   genau die Hoehe, die quer fehlt. */
	.ifb-table[data-compact='true'] .seat--rel3,
	.ifb-table[data-compact='true'] .seat--rel2 {
		top: 14%;
	}

	.ifb-table[data-compact='true'] .seat--rel4,
	.ifb-table[data-compact='true'] .seat--rel1 {
		top: 38%;
	}
}

/* ==========================================================================
   11 — RUHIGE BEWEGUNG
   Nicht "alles aus": was Bedeutung traegt, bleibt stehen. Dauerschleifen
   werden zu ruhenden Zustaenden, weite Wege zu kurzen Blenden. Die Wendung
   der Karte bleibt — sie ist die Information, nicht die Verzierung; render.js
   kuerzt sie zusaetzlich.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
	.ifb-table *,
	.ifb-table *::before,
	.ifb-table *::after {
		animation-duration: 1ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 120ms !important;
	}

	/* Der Glutkreis pulst nicht mehr, er steht — sichtbar wie zuvor. */
	.ifb-table .seat.is-active::before {
		animation: none;
		transform: translate(-50%, -50%) scale(1.02);
		opacity: 0.9;
	}

	.ifb-table.is-own-turn .felt::after {
		animation: none;
		opacity: 0.9;
	}

	.ifb-table [data-urgent='true'] .timer-text {
		animation: none;
		transform: scale(1.1);
	}

	.ifb-table .hand.is-blackjack .hand-fan::after {
		animation: none;
		opacity: 0.85;
		transform: none;
	}
}

/* Dieselbe Ruhe, wenn der Spieler sie im Spiel selbst einschaltet. */
.ifb-table.is-calm .seat.is-active::before,
.ifb-table.is-calm.is-own-turn .felt::after,
.ifb-table.is-calm [data-urgent='true'] .timer-text,
.ifb-table.is-calm .hand.is-blackjack .hand-fan::after {
	animation: none;
}

.ifb-table.is-calm .seat.is-active::before {
	transform: translate(-50%, -50%) scale(1.02);
	opacity: 0.9;
}

.ifb-table.is-calm.is-own-turn .felt::after {
	opacity: 0.9;
}

.ifb-table.is-calm .hand.is-blackjack .hand-fan::after {
	opacity: 0.85;
}


/* ==========================================================================
 * Faecherversatz je Blickwinkel.
 *
 * Am eigenen Platz sollen die eigenen Karten NEBENEINANDER liegen, nicht als
 * enger Casino-Faecher mit 70 Prozent Ueberdeckung — dort ist die Breite da,
 * und der Spieler will seine Hand lesen, nicht erraten. Fremde Sitze bleiben
 * kompakt, weil sie am Bildrand nur wenige Pixel haben. Der Dealer liegt
 * dazwischen: zwei Karten, davon eine verdeckt, beide klar als eigenstaendige
 * Karten erkennbar.
 * ========================================================================== */
.ifb-table .seat.is-own .hand-fan {
	--fan-dx: 0.78;
}

.ifb-table .dealer-fan {
	--fan-dx: 0.62;
}

/* Ab der dritten Karte wird es am eigenen Platz sonst zu breit; dann faechert
   es sich wieder zusammen, bleibt aber grosszuegiger als bei fremden Sitzen. */
.ifb-table .seat.is-own .hand-fan[style*="--n: 3"],
.ifb-table .seat.is-own .hand-fan[style*="--n:3"] {
	--fan-dx: 0.58;
}

.ifb-table[data-compact='true'] .seat.is-own .hand-fan {
	--fan-dx: 0.62;
}


/* ==========================================================================
 * Einladungsplaetze.
 *
 * Die beiden Nachbarn des eigenen Sitzes sind keine anonymen freien Stuehle,
 * sondern die Einladung an genau zwei Freunde. Sie werden deshalb deutlicher
 * gezeichnet als ein gewoehnlicher freier Platz — aber ruhiger als der eigene
 * Sitz, der die Aufmerksamkeit behalten muss.
 * ========================================================================== */
.ifb-table .seat-join[data-invite='1'] {
	border-style: solid;
	border-color: color-mix(in srgb, var(--ember, #ff7a00) 45%, transparent);
	color: var(--ember-soft, #ffb45b);
	background: color-mix(in srgb, var(--ember, #ff7a00) 8%, transparent);
}

.ifb-table .seat-join[data-invite='1']:hover,
.ifb-table .seat-join[data-invite='1']:focus-visible {
	border-color: var(--ember, #ff7a00);
	background: color-mix(in srgb, var(--ember, #ff7a00) 16%, transparent);
}

/* Aufklappen der aeusseren Plaetze: kurz und beilaeufig, es ist kein Ereignis. */
.ifb-table .seat {
	transition: opacity 220ms ease, transform 220ms ease;
}

@media (prefers-reduced-motion: reduce) {
	.ifb-table .seat {
		transition: none;
	}
}


/* ==========================================================================
 * DAS RUNDENURTEIL — gross in der Mitte des Filzes.
 *
 * Die kleine Marke an der Hand sagt, WELCHE Hand gewonnen hat; das ist bei
 * geteilten Haenden noetig. Diese Anzeige beantwortet die andere Frage: wie
 * die Runde fuer mich ausgegangen ist. Sie sitzt deshalb nicht an den Karten,
 * sondern mittig auf dem Tisch, wo der Blick ohnehin hinfaellt.
 *
 * Sie liegt UEBER den Sitzen (z-index), aber ohne Zeigerereignisse — sonst
 * schluckte sie Klicks auf die Sitzknoepfe darunter.
 * ========================================================================== */
.ifb-table .table-verdict {
	position: absolute;
	left: 50%;
	top: 46%;
	z-index: 60;
	transform: translate(-50%, -50%) scale(0.86);
	pointer-events: none;
	padding: 10px 26px;
	border-radius: 999px;
	white-space: nowrap;
	font-size: clamp(19px, 5.4vw, 34px);
	font-weight: 800;
	letter-spacing: 0.03em;
	font-variant-numeric: tabular-nums;
	text-transform: uppercase;
	color: var(--ifb-ink);
	background: rgb(8 8 11 / 0.86);
	border: 2px solid transparent;
	box-shadow: 0 18px 44px -18px rgb(0 0 0 / 0.9);
	opacity: 0;
	transition: opacity 260ms var(--ifb-ease-out, ease), transform 260ms var(--ifb-ease-out, ease);
}

.ifb-table .table-verdict.is-in {
	opacity: 1;
	transform: translate(-50%, -50%) scale(1);
}

.ifb-table .table-verdict[data-tone='win'] {
	border-color: var(--ifb-win, #35c07a);
	color: var(--ifb-win, #35c07a);
	box-shadow:
		0 18px 44px -18px rgb(0 0 0 / 0.9),
		0 0 34px -6px color-mix(in srgb, var(--ifb-win, #35c07a) 55%, transparent);
}

.ifb-table .table-verdict[data-tone='lose'] {
	border-color: var(--ifb-lose, #e0554b);
	color: var(--ifb-lose, #e0554b);
}

.ifb-table .table-verdict[data-tone='push'] {
	border-color: var(--ifb-ink-2, #b9b9c4);
	color: var(--ifb-ink-2, #b9b9c4);
}

/* Reduzierte Bewegung: die Anzeige bleibt, nur das Anwachsen entfaellt. */
@media (prefers-reduced-motion: reduce) {
	.ifb-table .table-verdict {
		transition: opacity 120ms linear;
		transform: translate(-50%, -50%) scale(1);
	}

	.ifb-table .table-verdict.is-in {
		transform: translate(-50%, -50%) scale(1);
	}
}
