:root {
	/* --- Design-system primitives (shared across themes) --- */
	--font-ui: ui-sans-serif, system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	--font-display: "Trebuchet MS", "Segoe UI", var(--font-ui);
	--radius-sm: 6px;
	--radius-lg: 12px;
	--border-thin: 1px;
	--border-thick: 2px;

	/* One board cell edge. The board is 11x11 cells, so board height ~= 11*--cell. The whole
	   game (top opponent dock + board + bottom human dock/action bar + gaps) has to fit in the
	   viewport without scrolling, so the cell scales down with viewport HEIGHT: reserve the fixed
	   vertical furniture, split the rest across 11 rows, and clamp so it never gets unusably small or
	   larger than the original 64px. Width is also considered (vw) so an unusually short-but-narrow
	   window still fits horizontally. The 364px reserve = top opponent dock (~118px, see .mono-table
	   margin-top) + bottom human dock + action bar (~160px; the CASH box is one short row and the 2x5
	   property grid tops out at two rows) + board padding/border + gaps, plus ~20px comfort slack. */
	--cell: clamp(26px, min((100vh - 364px) / 11, (100vw - 340px) / 11), 62px);

	/* --- Group colors (tuned for consistent saturation + AA contrast on the tile face) --- */
	--group-brown: #955436;
	--group-lightblue: #7cc4e8;
	--group-pink: #d955a3;
	--group-orange: #e8811f;
	--group-red: #d92d3a;
	--group-yellow: #f2c018;
	--group-green: #1f9d63;
	--group-darkblue: #2555c7;

	/* --- Light theme --- */
	--page-bg: #dfe7ea;
	/* Felt "table" the board sits on - a deep green tablecloth, so the board reads as a physical game surface */
	--felt-bg: radial-gradient(ellipse at 50% 34%, #2c6e49 0%, #245c3d 55%, #1c4a31 100%);
	--board-bg: #f4efe2;
	--board-face: linear-gradient(160deg, #f7f2e6 0%, #efe8d6 100%);
	--board-border: #14251c;
	--cell-bg: #fdfbf4;
	--cell-bg-alt: #f6f1e4;
	--cell-border: #cabfa4;
	--cell-text: #1c1c1c;
	--center-bg: linear-gradient(135deg, #f2ecda, #e5dcc4);
	--center-text: #3a3a2f;
	--sidebar-card-bg: #fff;
	--sidebar-card-border: #d8d0bd;
	--sidebar-card-active-bg: #fff6d8;
	--sidebar-text: #222;
	--sidebar-text-dim: #555;
	--panel-bg: #fffdf8;
	--panel-border: #b9ad92;
	--input-bg: #fff;
	--input-border: #b0a68d;
	--input-text: #1c1c1c;
	--modal-bg: #fffdf8;
	--modal-border: #14251c;
	--modal-text: #222;
	--log-bg: #14181a;
	--log-text: #b9f3c2;
	--btn-bg: #fff;
	--btn-border: #2a2a2a;
	--btn-text: #111;
	--btn-hover-bg: #1c4a31;
	--btn-hover-text: #fff;
	--btn-secondary-bg: #efe9db;
	--btn-primary-bg: #2c6e49;
	--btn-primary-text: #fff;
	--btn-primary-hover-bg: #1c4a31;
	--btn-danger-bg: #c0392b;
	--btn-danger-text: #fff;
	--btn-danger-hover-bg: #97281c;
	--shadow-soft: 0 2px 6px rgba(0, 0, 0, 0.15);
	--shadow-panel: 0 6px 20px rgba(0, 0, 0, 0.22);
	--focus-ring: 0 0 0 3px rgba(44, 110, 73, 0.5);
	--accent-gold: #e0a500;
	--hint-text: #666;
	--body-text: #222;
	--link-color: #0066cc;
	--link-hover: #004499;
	--title-stroke: #14251c;
}

/* Dark theme overrides. The design-system primitives (fonts, radii, group colors) live in the base
   :root above and are inherited here - only the surface/ink tokens are re-pointed for dark mode. The
   two selectors below (explicit toggle + OS-preference-without-explicit-light) share one token set
   via a custom-property indirection so the values only exist in one place. */
:root[data-theme="dark"],
:root:not([data-theme="light"]) {
	--dark-page-bg: #0e1116;
	--dark-felt-bg: radial-gradient(ellipse at 50% 34%, #16332a 0%, #10261f 60%, #0a1a14 100%);
	--dark-board-bg: #18201d;
	--dark-board-face: linear-gradient(160deg, #1e2723 0%, #171e1b 100%);
	--dark-board-border: #05100b;
	--dark-cell-bg: #222a26;
	--dark-cell-bg-alt: #1c231f;
	--dark-cell-border: #3a4149;
	--dark-cell-text: #e8e8e6;
	--dark-center-bg: linear-gradient(135deg, #1b2420, #141b18);
	--dark-center-text: #cfd8d4;
	--dark-sidebar-card-bg: #1a1f24;
	--dark-sidebar-card-border: #333b42;
	--dark-sidebar-card-active-bg: #2b2410;
	--dark-sidebar-text: #eaeaea;
	--dark-sidebar-text-dim: #9aa4ab;
	--dark-panel-bg: #1a1f24;
	--dark-panel-border: #40484f;
	--dark-input-bg: #12161a;
	--dark-input-border: #454d55;
	--dark-input-text: #eaeaea;
	--dark-modal-bg: #1a1f24;
	--dark-modal-border: #454d55;
	--dark-modal-text: #eaeaea;
	--dark-log-bg: #060a08;
	--dark-log-text: #7de892;
	--dark-btn-bg: #232a2f;
	--dark-btn-border: #545c64;
	--dark-btn-text: #eaeaea;
	--dark-btn-hover-bg: #eaeaea;
	--dark-btn-hover-text: #14181a;
	--dark-btn-secondary-bg: #12161a;
	--dark-btn-primary-bg: #2c8a5b;
	--dark-btn-primary-hover-bg: #37a56c;
	--dark-btn-danger-bg: #c0392b;
	--dark-btn-danger-hover-bg: #d5533f;
	--dark-shadow-soft: 0 2px 8px rgba(0, 0, 0, 0.45);
	--dark-shadow-panel: 0 6px 22px rgba(0, 0, 0, 0.55);
	--dark-focus-ring: 0 0 0 3px rgba(55, 165, 108, 0.55);
	--dark-accent-gold: #f2b23c;
	--dark-hint-text: #9aa4ab;
	--dark-body-text: #d6d9db;
	--dark-link-color: #6cb8ff;
	--dark-link-hover: #9fd1ff;
	--dark-title-stroke: #e8e8e6;
}

/* Applies the dark token set. Kept as its own rule (both selectors) so the assignment list exists
   once; the values themselves are defined once in the block above. */
:root[data-theme="dark"] {
	--page-bg: var(--dark-page-bg); --felt-bg: var(--dark-felt-bg);
	--board-bg: var(--dark-board-bg); --board-face: var(--dark-board-face); --board-border: var(--dark-board-border);
	--cell-bg: var(--dark-cell-bg); --cell-bg-alt: var(--dark-cell-bg-alt); --cell-border: var(--dark-cell-border); --cell-text: var(--dark-cell-text);
	--center-bg: var(--dark-center-bg); --center-text: var(--dark-center-text);
	--sidebar-card-bg: var(--dark-sidebar-card-bg); --sidebar-card-border: var(--dark-sidebar-card-border); --sidebar-card-active-bg: var(--dark-sidebar-card-active-bg);
	--sidebar-text: var(--dark-sidebar-text); --sidebar-text-dim: var(--dark-sidebar-text-dim);
	--panel-bg: var(--dark-panel-bg); --panel-border: var(--dark-panel-border);
	--input-bg: var(--dark-input-bg); --input-border: var(--dark-input-border); --input-text: var(--dark-input-text);
	--modal-bg: var(--dark-modal-bg); --modal-border: var(--dark-modal-border); --modal-text: var(--dark-modal-text);
	--log-bg: var(--dark-log-bg); --log-text: var(--dark-log-text);
	--btn-bg: var(--dark-btn-bg); --btn-border: var(--dark-btn-border); --btn-text: var(--dark-btn-text);
	--btn-hover-bg: var(--dark-btn-hover-bg); --btn-hover-text: var(--dark-btn-hover-text); --btn-secondary-bg: var(--dark-btn-secondary-bg);
	--btn-primary-bg: var(--dark-btn-primary-bg); --btn-primary-hover-bg: var(--dark-btn-primary-hover-bg);
	--btn-danger-bg: var(--dark-btn-danger-bg); --btn-danger-hover-bg: var(--dark-btn-danger-hover-bg);
	--shadow-soft: var(--dark-shadow-soft); --shadow-panel: var(--dark-shadow-panel); --focus-ring: var(--dark-focus-ring);
	--accent-gold: var(--dark-accent-gold); --hint-text: var(--dark-hint-text); --body-text: var(--dark-body-text);
	--link-color: var(--dark-link-color); --link-hover: var(--dark-link-hover); --title-stroke: var(--dark-title-stroke);
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		--page-bg: var(--dark-page-bg); --felt-bg: var(--dark-felt-bg);
		--board-bg: var(--dark-board-bg); --board-face: var(--dark-board-face); --board-border: var(--dark-board-border);
		--cell-bg: var(--dark-cell-bg); --cell-bg-alt: var(--dark-cell-bg-alt); --cell-border: var(--dark-cell-border); --cell-text: var(--dark-cell-text);
		--center-bg: var(--dark-center-bg); --center-text: var(--dark-center-text);
		--sidebar-card-bg: var(--dark-sidebar-card-bg); --sidebar-card-border: var(--dark-sidebar-card-border); --sidebar-card-active-bg: var(--dark-sidebar-card-active-bg);
		--sidebar-text: var(--dark-sidebar-text); --sidebar-text-dim: var(--dark-sidebar-text-dim);
		--panel-bg: var(--dark-panel-bg); --panel-border: var(--dark-panel-border);
		--input-bg: var(--dark-input-bg); --input-border: var(--dark-input-border); --input-text: var(--dark-input-text);
		--modal-bg: var(--dark-modal-bg); --modal-border: var(--dark-modal-border); --modal-text: var(--dark-modal-text);
		--log-bg: var(--dark-log-bg); --log-text: var(--dark-log-text);
		--btn-bg: var(--dark-btn-bg); --btn-border: var(--dark-btn-border); --btn-text: var(--dark-btn-text);
		--btn-hover-bg: var(--dark-btn-hover-bg); --btn-hover-text: var(--dark-btn-hover-text); --btn-secondary-bg: var(--dark-btn-secondary-bg);
		--btn-primary-bg: var(--dark-btn-primary-bg); --btn-primary-hover-bg: var(--dark-btn-primary-hover-bg);
		--btn-danger-bg: var(--dark-btn-danger-bg); --btn-danger-hover-bg: var(--dark-btn-danger-hover-bg);
		--shadow-soft: var(--dark-shadow-soft); --shadow-panel: var(--dark-shadow-panel); --focus-ring: var(--dark-focus-ring);
		--accent-gold: var(--dark-accent-gold); --hint-text: var(--dark-hint-text); --body-text: var(--dark-body-text);
		--link-color: var(--dark-link-color); --link-hover: var(--dark-link-hover); --title-stroke: var(--dark-title-stroke);
	}
}

* {
	box-sizing: border-box;
}

body {
	background-color: var(--page-bg);
	margin: 0;
	font-family: var(--font-ui);
	min-height: 100vh;
	transition: background-color 0.2s ease;
}

/* Cash/rent/price figures use tabular figures everywhere so digits keep a fixed width and don't
   jitter sideways as amounts change (e.g. a flying-bill payment ticking a total down). */
.mono-cash-amount,
.mono-cell-price,
.mono-prop-rent,
.mono-bill,
.mono-bill-count {
	font-variant-numeric: tabular-nums;
}

.top-left-buttons {
	position: fixed;
	top: 10px;
	left: 10px;
	display: flex;
	gap: 10px;
	z-index: 100;
}

.top-right-buttons {
	position: fixed;
	top: 10px;
	right: 10px;
	z-index: 100;
	display: flex;
	align-items: center;
	gap: 10px;
}

/* AI-speed control docked in the fixed top-right corner (moved out of the in-flow bottom controls
   so it doesn't count toward the height that must fit on screen - see _renderSpeedControl). Styled
   to sit as a pill next to the theme toggle. Empty (and so invisible) when no game is running. */
.mono-speed-control {
	display: flex;
	align-items: center;
	gap: 6px;
	font-family: var(--font-ui);
	font-size: 13px;
	color: var(--btn-text);
	background: var(--btn-bg);
	border: 1px solid var(--btn-border);
	border-radius: var(--radius-sm);
	padding: 6px 10px;
	box-shadow: var(--shadow-soft);
}

.mono-speed-control:empty {
	display: none;
}

.mono-speed-control label {
	white-space: nowrap;
}

.mono-speed-control select {
	background: var(--input-bg);
	color: var(--input-text);
	border: 1px solid var(--input-border);
	border-radius: 4px;
	font-family: var(--font-ui);
	font-size: 12px;
	padding: 2px 4px;
}

.back-buttons,
.theme-toggle-btn {
	background: var(--btn-bg);
	color: var(--btn-text);
	border: 1px solid var(--btn-border);
	border-radius: var(--radius-sm);
	padding: 8px 12px;
	cursor: pointer;
	font-family: var(--font-ui);
	font-size: 13px;
	box-shadow: var(--shadow-soft);
	transition: background-color 0.15s ease, color 0.15s ease;
}

.back-buttons:hover,
.theme-toggle-btn:hover {
	background: var(--btn-hover-bg);
	color: var(--btn-hover-text);
}

.back-buttons:focus-visible,
.theme-toggle-btn:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
}

.back-buttons:active,
.theme-toggle-btn:active {
	transform: translate(0px, 2px);
}

.mono-wrapper {
	max-width: 1400px;
	margin: 0 auto;
	padding: 6px 10px;
}

/* Tabletop layout: the 3 AI docks are thin strips fused directly onto the board's own frame,
   overlapping a fixed small amount ONTO the board edge (not a percentage of the dock's own size -
   that blew up once the dock grew content, pushing it off past the page's own title/viewport).
   Each dock is capped to a fixed max width/height so it can never grow past the board's own side
   length. The human dock stays in normal flow directly below. */
.mono-table {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	/* Top clearance for the opponent dock that hangs above the board (label + cash row + property
	   cards, which grow upward - see .mono-dock-top's bottom:100% anchor below). The whole game is
	   sized to fit the viewport without scrolling (see --cell), so this is kept as tight as the
	   dock's own content needs; the boxed 2x5 property grid caps how tall it can get. */
	margin: 118px auto 0 auto;
}

.mono-board-wrap {
	position: relative;
	flex: 0 0 auto;
	padding: 14px;
	background: var(--felt-bg);
	border: 1px solid var(--board-border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-panel), inset 0 0 60px rgba(0, 0, 0, 0.25);
}

.mono-dock {
	display: flex;
	justify-content: center;
}

/* Top/left/right docks are positioned against the board frame with a fixed pixel offset (not a
   transform percentage) so their own size never affects how far they sit from the board - they
   hug the edge exactly the same amount regardless of how many properties/denominations a player
   has. */
.mono-dock-top,
.mono-dock-left,
.mono-dock-right {
	position: absolute;
	z-index: 20;
}

/* The dock BOX itself sits entirely outside the board (zero overlap) - only the cash-pile element
   inside it gets pulled back in with its own negative margin (see .mono-dock-*.mono-cash-piles
   below) so just that sliver reaches under the board panel. Pulling the whole dock box in (an
   earlier attempt) dragged the name label along with it, hiding the label behind the board's
   higher z-index background - this keeps the label fully outside no matter what. */
.mono-dock-top {
	bottom: 100%;
	margin-bottom: 8px;
	left: 50%;
	transform: translateX(-50%);
	max-width: min(90vw, 560px);
}

.mono-dock-left {
	right: 100%;
	margin-right: 4px;
	top: 50%;
	transform: translateY(-50%);
	max-height: min(80vh, 560px);
}

.mono-dock-right {
	left: 100%;
	margin-left: 4px;
	top: 50%;
	transform: translateY(-50%);
	max-height: min(80vh, 560px);
}

.mono-dock-bottom {
	flex-direction: column;
	align-items: center;
	gap: 6px;
}

.mono-board {
	display: grid;
	grid-template-columns: repeat(11, var(--cell));
	grid-template-rows: repeat(11, var(--cell));
	border: 3px solid var(--board-border);
	border-radius: var(--radius-sm);
	background: var(--board-face);
	position: relative;
	overflow: hidden;
	box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.06), 0 8px 24px rgba(0, 0, 0, 0.35);
	/* Higher than .mono-dock-top/-left/-right (z-index 20) so the board panel's own box visually
	   covers the top of each side's cash piles where they overlap (see .mono-cash-piles / the
	   .mono-dock-* negative-margin tuck-under rules) - the "tucked under the board" look from
	   point 1. */
	z-index: 25;
}

.mono-cell {
	border: 1px solid var(--cell-border);
	position: relative;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: var(--cell-bg);
	color: var(--cell-text);
	font-size: 8px;
	/* subtle top bevel so each tile reads as a raised physical space rather than a flat grid cell */
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35);
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.15s ease;
}

/* Landing pulse: briefly glows a tile when a token arrives on it, so the eye follows the action
   (added/removed in JS around _animateTokenMove; see MonopolyUI). */
.mono-cell.mono-cell-landed {
	animation: mono-cell-land 0.9s ease-out;
	z-index: 3;
}

@keyframes mono-cell-land {
	0% { box-shadow: inset 0 0 0 2px var(--accent-gold), 0 0 14px 3px rgba(224, 165, 0, 0.75); }
	100% { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35); }
}

@media (prefers-reduced-motion: reduce) {
	.mono-cell.mono-cell-landed { animation: none; }
}

.mono-cell-tradeable {
	cursor: pointer;
	box-shadow: inset 0 0 0 2px var(--accent-gold);
	/* Sits above sibling board layers so the click reliably lands on the cell. The trade tray is a
	   docked side panel (not a full-screen backdrop), so the board stays fully clickable behind it -
	   click-to-add works throughout the human's turn. */
	position: relative;
	z-index: 30;
}

.mono-cell-tradeable:hover {
	background: var(--sidebar-card-active-bg);
}

.mono-cell-color {
	height: clamp(9px, calc(var(--cell) * 0.24), 14px);
	width: 100%;
	flex-shrink: 0;
	border-bottom: 1px solid rgba(0, 0, 0, 0.3);
	box-shadow: inset 0 2px 3px rgba(255, 255, 255, 0.35), inset 0 -2px 3px rgba(0, 0, 0, 0.25);
}

/* Cell text/icons scale with the cell size (--cell) so a board shrunk to fit a short viewport stays
   proportional rather than clipping fixed-size 8.5px text. */
.mono-cell-label {
	padding: 3px 3px 1px 3px;
	line-height: 1.1;
	font-size: clamp(5.5px, calc(var(--cell) * 0.15), 8.5px);
	font-weight: 700;
	flex: 1;
	word-break: break-word;
	letter-spacing: 0.005em;
}

.mono-cell.mono-cell-special .mono-cell-label {
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	font-size: clamp(5.5px, calc(var(--cell) * 0.15), 8.5px);
}

.mono-cell-icon {
	display: block;
	width: clamp(14px, calc(var(--cell) * 0.42), 22px);
	height: clamp(14px, calc(var(--cell) * 0.42), 22px);
	margin: 3px auto 0 auto;
	image-rendering: pixelated;
	image-rendering: crisp-edges;
}

/* The four corner squares - a warm parchment wash + bigger icon so they read as the board's
   anchors (Start / Jail / Free Parking / Go-To-Jail) rather than just another special tile. */
.mono-cell-corner {
	background: radial-gradient(circle at 50% 40%, var(--cell-bg) 0%, var(--cell-bg-alt) 100%);
	justify-content: center;
}

.mono-cell-corner .mono-cell-icon {
	width: 30px;
	height: 30px;
}

.mono-cell-corner .mono-cell-label {
	flex: 0 0 auto;
	font-size: 8px;
}

.mono-cell-info {
	display: flex;
	gap: 2px;
	padding: 1px 2px;
	flex-wrap: wrap;
}

.mono-owner-chip {
	width: 15px;
	height: 15px;
	border-radius: 50%;
	color: #fff;
	font-size: 9px;
	display: flex;
	align-items: center;
	justify-content: center;
	font-weight: bold;
	border: 1px solid rgba(0, 0, 0, 0.45);
	text-shadow: 0 0 2px rgba(0, 0, 0, 0.9);
	flex-shrink: 0;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
	transition: background-color 0.15s ease;
}

/* The bank's asking price, shown on an unowned tile in place of the owner chip (see
   _renderBoardState) - small enough to fit the cell without competing with the name label above
   it, but still legible at a glance so the cost to buy doesn't require landing on the space. */
.mono-cell-price {
	font-size: 8px;
	font-weight: 700;
	color: var(--sidebar-text-dim);
	background: rgba(0, 0, 0, 0.06);
	border-radius: 999px;
	padding: 0 4px;
	line-height: 1.5;
}

:root[data-theme="dark"] .mono-cell-price {
	background: rgba(255, 255, 255, 0.08);
}

/* House/hotel pips shown on an owned tile (see _renderBoardState) - little green squares for
   houses, a red bar for a hotel, echoing the physical game pieces. Sits in the tile's info strip
   next to the owner chip. */
.mono-cell-pips {
	display: flex;
	gap: 1px;
	align-items: center;
}

.mono-pip-house {
	width: 5px;
	height: 5px;
	border-radius: 1px;
	background: #2f9e44;
	box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.5);
}

.mono-pip-hotel {
	width: 11px;
	height: 5px;
	border-radius: 1px;
	background: #d92d3a;
	box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.5);
}

/* Shown instead of a property's real owner color while the trade builder modal has a
   not-yet-sent offer that would move this property (see MonopolyUI._tradePreview /
   _previewOwner) - dashed ring makes clear this is a preview, not a completed trade. */
.mono-owner-chip-preview {
	outline: 2px dashed var(--accent-gold);
	outline-offset: 1px;
}

.mono-token-layer {
	position: absolute;
	inset: 0;
	pointer-events: none;
	z-index: 5;
}

.mono-token {
	position: absolute;
	width: 22px;
	height: 22px;
	margin-left: -11px;
	margin-top: -11px;
	border-radius: 50%;
	/* colored ring (per-player) around a light disc that carries the emoji game piece */
	border: 2px solid var(--token-color, #fff);
	background: rgba(255, 255, 255, 0.92);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 13px;
	line-height: 1;
	box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35), 0 2px 4px rgba(0, 0, 0, 0.5);
	transition: left 0.12s ease-in-out, top 0.12s ease-in-out;
	z-index: 6;
}

:root[data-theme="dark"] .mono-token {
	background: rgba(40, 46, 42, 0.92);
}

@media (prefers-reduced-motion: reduce) {
	.mono-token {
		transition: none;
	}
}

.mono-center {
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--center-bg);
	border: 1px solid var(--cell-border);
	/* Positioning context for .mono-dice-area, which now lives here (on the board itself) rather
	   than pinned inside the human's own dock - see .mono-dice-area-* below. */
	position: relative;
}

.mono-center-title {
	font-family: var(--font-display);
	font-weight: 800;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	font-size: 30px;
	text-align: center;
	color: var(--center-text);
	transform: rotate(-8deg);
	opacity: 0.8;
	text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
}

.mono-center-title span {
	font-size: 12px;
	letter-spacing: 0.05em;
	display: block;
	margin-top: 4px;
	opacity: 0.85;
}

/* Sits on the board itself (centered on the middle logo area, see .mono-center's position:relative)
   and slides toward whichever seat's turn it currently is, so it reads as "the dice are in front of
   the active player" rather than always parked at the human's own seat - see
   MonopolyUI._positionDiceForCurrentPlayer, which swaps the mono-dice-area-* modifier class below
   each time the current player changes. Rotated to face that seat, same convention as the player
   docks' cash/property rows (DOCK_ROTATE). */
.mono-dice-area {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	background: var(--panel-bg);
	border: 1px solid var(--panel-border);
	border-radius: 8px;
	padding: 14px 12px;
	box-shadow: var(--shadow-panel);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
	transition: top 0.25s ease, left 0.25s ease, transform 0.25s ease;
	z-index: 4;
}

.mono-dice-area-bottom {
	top: auto;
	left: 50%;
	bottom: 12%;
	transform: translate(-50%, 0);
}

.mono-dice-area-top {
	top: 12%;
	left: 50%;
	transform: translate(-50%, 0) rotate(180deg);
}

.mono-dice-area-left {
	top: 50%;
	left: 12%;
	transform: translate(0, -50%) rotate(90deg);
}

.mono-dice-area-right {
	top: 50%;
	left: auto;
	right: 12%;
	transform: translate(0, -50%) rotate(-90deg);
}

@media (prefers-reduced-motion: reduce) {
	.mono-dice-area {
		transition: none;
	}
}

.mono-dice-pair {
	display: flex;
	gap: 12px;
	perspective: 300px;
}

.mono-die {
	width: 48px;
	height: 48px;
	image-rendering: pixelated;
	image-rendering: crisp-edges;
	filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.35));
}

.mono-die-rolling {
	animation: mono-die-tumble 0.16s linear infinite;
}

.mono-die-land {
	animation: mono-die-land 0.3s ease-out;
}

@keyframes mono-die-tumble {
	0% { transform: rotate(0deg) scale(1); }
	50% { transform: rotate(15deg) scale(1.05); }
	100% { transform: rotate(-10deg) scale(1); }
}

@keyframes mono-die-land {
	0% { transform: scale(1.3) rotate(8deg); }
	60% { transform: scale(0.94) rotate(-4deg); }
	100% { transform: scale(1) rotate(0deg); }
}

.mono-roll-btn {
	font-size: 15px;
	padding: 10px 18px;
	font-weight: bold;
}

/* ---- Physical dice throw (see MonopolyUI._animateDiceThrow) ----
   Two dice are flung from the active seat, tumble across the open board center along a randomized
   path, and settle showing the true faces, with a "Move N" badge. Lives on the fixed fx layer. */
.mono-thrown-dice {
	position: fixed;
	inset: 0;
	pointer-events: none;
	z-index: 30;
}

.mono-thrown-die {
	position: fixed;
	width: 46px;
	height: 46px;
	image-rendering: pixelated;
	image-rendering: crisp-edges;
	filter: drop-shadow(0 4px 5px rgba(0, 0, 0, 0.45));
	/* the travel + spin; duration is set per-throw in JS (transitionDuration) */
	transition: left 0.5s cubic-bezier(0.2, 0.7, 0.3, 1), top 0.5s cubic-bezier(0.2, 0.7, 0.3, 1), transform 0.5s cubic-bezier(0.2, 0.7, 0.3, 1);
	will-change: left, top, transform;
}

.mono-dice-badge {
	position: fixed;
	transform: translate(-50%, -50%) scale(0.8);
	background: var(--panel-bg);
	color: var(--sidebar-text);
	border: 1px solid var(--panel-border);
	border-radius: 999px;
	padding: 4px 12px;
	font-size: 13px;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
	box-shadow: var(--shadow-panel);
	opacity: 0;
	transition: opacity 0.18s ease, transform 0.18s cubic-bezier(0.2, 0.9, 0.3, 1.4);
}

.mono-dice-badge.show {
	opacity: 1;
	transform: translate(-50%, -50%) scale(1);
}

.mono-dice-badge-dbl {
	color: var(--accent-gold);
	text-transform: uppercase;
	letter-spacing: 0.03em;
}

@media (prefers-reduced-motion: reduce) {
	.mono-thrown-die { transition: opacity 0.12s ease; }
	.mono-dice-badge { transition: opacity 0.12s ease; }
}

@media (prefers-reduced-motion: reduce) {
	.mono-die-rolling,
	.mono-die-land {
		animation: none;
	}
}

/* The bank: a static visual anchor in the board's center (alongside the dice/title, see
   .mono-center) for flying bill/property animations to fly to/from - not a running cash total,
   since this ruleset's bank has unlimited money (game.js never checks a bank balance). Sits below
   the dice area in normal flex flow within .mono-center. */
/* Tucked in a corner rather than dead-center - the dice area (.mono-dice-area-*) can slide to
   any of center/top/left/right/bottom depending on whose turn it is, so a corner is the one spot
   never occupied by the dice regardless of current player. */
.mono-bank {
	position: absolute;
	top: 6%;
	right: 6%;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 5px;
	z-index: 3;
}

.mono-bank-label {
	font-size: 12px;
	font-weight: bold;
	color: var(--center-text);
	background: var(--panel-bg);
	border: 1px solid var(--panel-border);
	border-radius: 6px;
	padding: 2px 8px;
	box-shadow: var(--shadow-soft);
	white-space: nowrap;
}

/* The bank now shows two distinct piles side by side: a cash pile (bills fly to/from here) and a
   property pile (deeds fly to/from here) - see MonopolyUI._bankAnchor. */
.mono-bank-piles {
	display: flex;
	align-items: flex-end;
	gap: 10px;
}

.mono-bank-pile {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
}

/* Cash pile: a small stack of stylized bills with a $ cap, a compact echo of the players' own cash
   stacks so it reads as "the bank's money". */
.mono-bank-cash {
	width: 30px;
	height: 30px;
}

.mono-bank-bill {
	position: absolute;
	width: 28px;
	height: 16px;
	border-radius: 2px;
	border: 1px solid rgba(0, 0, 0, 0.5);
	background: repeating-linear-gradient(135deg, #cdebd6, #cdebd6 3px, #bfe0c9 3px, #bfe0c9 6px);
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.mono-bank-bill:nth-child(1) { top: 12px; left: 0; }
.mono-bank-bill:nth-child(2) { top: 8px; left: 1px; }
.mono-bank-bill:nth-child(3) { top: 4px; left: 2px; }

.mono-bank-pile-cap {
	position: absolute;
	top: -4px;
	left: 3px;
	font-size: 13px;
	font-weight: 800;
	color: #2f9e44;
	text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
}

/* Property pile: fanned stack of face-down generic deeds standing in for "the unowned property
   deck" (see MonopolyUI._flyProperty for the real per-property flying card). */
.mono-bank-props {
	flex-direction: row;
}

/* .mono-mini-prop.mono-deck-card (two-class selector) so this width/height reliably beats
   .mono-mini-prop's own 34px width, regardless of source order between the two rules. */
.mono-mini-prop.mono-deck-card {
	width: 20px;
	height: 28px;
	background: repeating-linear-gradient(135deg, #8a8f96, #8a8f96 3px, #797d84 3px, #797d84 6px);
	border: 1px solid rgba(0, 0, 0, 0.5);
}

.mono-bank-props .mono-deck-card + .mono-deck-card {
	margin-left: -12px;
}

/* ---- Card decks (Wild Fate top-left, Fortune Chest bottom-right of the board center) ----
   Small fanned stacks of face-down cards. A draw animation (see MonopolyUI._animateCardDraw) sends a
   card flying to center, flips it face-up to read, then returns it to the deck. */
.mono-card-deck {
	position: absolute;
	width: 30px;
	height: 40px;
	z-index: 3;
}

.mono-deck-fate {
	top: 6%;
	left: 6%;
}

.mono-deck-chest {
	bottom: 6%;
	right: 6%;
}

.mono-card-back {
	position: absolute;
	width: 26px;
	height: 36px;
	border-radius: 4px;
	border: 1px solid rgba(0, 0, 0, 0.55);
	background: linear-gradient(135deg, #d98324, #b5651d);
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
	display: flex;
	align-items: center;
	justify-content: center;
	color: #fff;
	font-size: 14px;
	font-weight: 800;
	text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

.mono-card-back.chest {
	background: linear-gradient(135deg, #4a7fd0, #2c5aa8);
}

.mono-card-back:nth-child(1) { top: 3px; left: 3px; }
.mono-card-back:nth-child(2) { top: 1.5px; left: 1.5px; }
.mono-card-back-top { top: 0; left: 0; }

.mono-card-deck-label {
	position: absolute;
	top: 42px;
	left: 50%;
	transform: translateX(-50%);
	font-size: 8px;
	font-weight: 700;
	white-space: nowrap;
	color: var(--center-text);
	opacity: 0.85;
}

.mono-deck-chest .mono-card-deck-label {
	top: auto;
	bottom: 42px;
}

/* The flying/flipping card during a draw (see _animateCardDraw). Fixed-positioned on the fx layer,
   flips via a 3D rotateY reveal from a face-down back to a face-up reading side. */
.mono-card-draw {
	position: fixed;
	width: 150px;
	height: 200px;
	transform-style: preserve-3d;
	transition: left 0.5s cubic-bezier(0.25, 0.8, 0.35, 1), top 0.5s cubic-bezier(0.25, 0.8, 0.35, 1), transform 0.5s cubic-bezier(0.25, 0.8, 0.35, 1), opacity 0.3s ease;
	z-index: 60;
	pointer-events: none;
}

.mono-card-draw-inner {
	position: relative;
	width: 100%;
	height: 100%;
	transform-style: preserve-3d;
	transition: transform 0.5s cubic-bezier(0.4, 0.1, 0.2, 1);
}

.mono-card-draw.flipped .mono-card-draw-inner {
	transform: rotateY(180deg);
}

.mono-card-face {
	position: absolute;
	inset: 0;
	backface-visibility: hidden;
	border-radius: 10px;
	border: 2px solid rgba(0, 0, 0, 0.5);
	box-shadow: var(--shadow-panel);
	display: flex;
	align-items: center;
	justify-content: center;
}

.mono-card-face.back {
	background: linear-gradient(135deg, #d98324, #b5651d);
	color: #fff;
	font-size: 60px;
	font-weight: 800;
	text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
}

.mono-card-face.back.chest {
	background: linear-gradient(135deg, #4a7fd0, #2c5aa8);
}

.mono-card-face.front {
	transform: rotateY(180deg);
	flex-direction: column;
	gap: 12px;
	padding: 18px;
	text-align: center;
	background: var(--modal-bg);
	color: var(--modal-text);
}

.mono-card-front-head {
	font-size: 13px;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--sidebar-text-dim);
}

.mono-card-front-text {
	font-size: 16px;
	font-weight: 600;
	line-height: 1.35;
}

@media (prefers-reduced-motion: reduce) {
	.mono-card-draw, .mono-card-draw-inner { transition: opacity 0.15s ease; }
}

/* First-run coach-mark tour (see MonopolyUI._startTour). A full-screen dimmer with a "spotlight"
   cutout over the current target element (achieved via a huge box-shadow spread that darkens
   everything outside the spotlight rect) plus an anchored text card. Above everything except nothing
   in-game needs to be interactive while it's up. */
.mono-tour {
	position: fixed;
	inset: 0;
	z-index: 2000;
}

.mono-tour-spotlight {
	position: fixed;
	border-radius: var(--radius-sm);
	box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.62);
	outline: 2px solid var(--accent-gold);
	transition: left 0.2s ease, top 0.2s ease, width 0.2s ease, height 0.2s ease;
	pointer-events: none;
}

.mono-tour-card {
	position: fixed;
	width: 280px;
	background: var(--modal-bg);
	color: var(--modal-text);
	border: 2px solid var(--accent-gold);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-panel);
	padding: 14px 16px;
}

.mono-tour-text {
	font-size: 13px;
	line-height: 1.45;
}

.mono-tour-foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-top: 12px;
}

.mono-tour-progress {
	font-size: 11px;
	color: var(--hint-text);
	font-variant-numeric: tabular-nums;
}

.mono-tour-btns { display: flex; gap: 6px; }
.mono-tour-btns .mono-btn { margin: 0; }

/* Hover title-deed tooltip (see MonopolyUI._showDeedTip) - a floating card mirroring a physical
   Monopoly deed: group color header, name, price/mortgage, current owner, and the full rent ladder
   with the currently-active tier highlighted. Positioned in JS (fixed, viewport-clamped), so this
   just styles it. Above the board/docks but below the modals. */
.mono-deed-tip {
	position: fixed;
	z-index: 950;
	width: 200px;
	background: var(--modal-bg);
	color: var(--modal-text);
	border: 1px solid var(--panel-border);
	border-radius: var(--radius-sm);
	box-shadow: var(--shadow-panel);
	overflow: hidden;
	pointer-events: none;
	font-size: 11px;
}

/* Same deed layout as the hover tooltip, but embedded in a modal (the buy dialog) as a static card
   rather than a floating fixed tooltip. */
.mono-deed-card {
	border: 1px solid var(--panel-border);
	border-radius: var(--radius-sm);
	overflow: hidden;
	margin: 10px 0;
	background: var(--sidebar-card-bg);
	font-size: 12px;
}

.mono-deed-card .mono-deed-name { font-size: 15px; }

.mono-buy-callout {
	text-align: center;
	font-size: 12px;
	font-weight: 700;
	padding: 7px;
	border-radius: var(--radius-sm);
	background: var(--sidebar-card-active-bg);
	margin-bottom: 10px;
}

.mono-buy-callout.complete {
	background: #2f9e44;
	color: #fff;
}

.mono-buy-cash {
	font-size: 12px;
	font-variant-numeric: tabular-nums;
}

.mono-deed-bar {
	height: 20px;
	border-bottom: 1px solid rgba(0, 0, 0, 0.35);
}

.mono-deed-body {
	padding: 8px 10px 9px 10px;
}

.mono-deed-name {
	font-weight: 800;
	font-size: 13px;
	line-height: 1.15;
	margin-bottom: 2px;
}

.mono-deed-meta {
	color: var(--sidebar-text-dim);
	font-size: 10px;
	margin-bottom: 4px;
	font-variant-numeric: tabular-nums;
}

.mono-deed-owner {
	font-size: 10.5px;
	margin-bottom: 6px;
	padding-bottom: 6px;
	border-bottom: 1px dashed var(--panel-border);
}

.mono-deed-rent-row {
	display: flex;
	justify-content: space-between;
	gap: 10px;
	padding: 1.5px 0;
	font-variant-numeric: tabular-nums;
}

.mono-deed-rent-row.sub {
	margin-top: 3px;
	padding-top: 4px;
	border-top: 1px dashed var(--panel-border);
	color: var(--sidebar-text-dim);
}

/* the rent tier matching the property's current house count is highlighted, so you can see at a
   glance what it costs to land there right now */
.mono-deed-rent-row.current {
	background: var(--sidebar-card-active-bg);
	font-weight: 700;
	border-radius: 3px;
	padding-left: 4px;
	padding-right: 4px;
	margin: 0 -4px;
}

/* Full-viewport overlay for flying bill/property animations (see MonopolyUI._flyBills/
   _flyProperty) - fixed with inset:0 so getBoundingClientRect()'s viewport coordinates can be used
   directly as left/top without any offset math. pointer-events:none so it never blocks clicks on
   the docks/board beneath it. Above the board/docks/tokens but below the decision/event modals
   (1000-1150) - a flying bill briefly crossing in front of a modal reads fine, but must never
   block the modal's own controls. */
.mono-fx-layer {
	position: fixed;
	inset: 0;
	pointer-events: none;
	z-index: 900;
}

/* Flying bill/property elements: absolutely positioned at their start point, then moved to their
   destination on the next frame so the browser animates the transform via a plain CSS transition
   (transitionDuration is set per-flight in JS so multi-bill flurries can share this one rule while
   each bill's own duration/stagger still comes from _flyBills). Centered on their own {left,top}
   point (matching _elCenter's center-point contract) via negative margins, same convention as
   .mono-token. */
.mono-fly-bill {
	position: fixed;
	margin-left: -19px;
	margin-top: -11px;
	transition-property: left, top, opacity;
	transition-timing-function: ease-in-out;
	will-change: left, top, opacity;
}

/* .mono-mini-prop.mono-fly-prop (two-class selector, higher specificity than plain .mono-mini-prop
   alone) so `position: fixed` here reliably beats .mono-mini-prop's own `position: relative`
   regardless of which rule happens to come later in this file. */
.mono-mini-prop.mono-fly-prop {
	position: fixed;
	width: 34px;
	margin-left: -17px;
	margin-top: -14px;
	transition-property: left, top, opacity;
	transition-timing-function: ease-in-out;
	will-change: left, top, opacity;
}

@media (prefers-reduced-motion: reduce) {
	.mono-fly-bill,
	.mono-fly-prop {
		transition-duration: 1ms !important;
	}
}

/* Gutted dock: no boxed card at all anymore - a bare, unboxed strip (name label + cash piles +
   property clusters) hugging the board's edge. Top/bottom docks stack their contents in a row
   (name above, cash+properties below, laid out horizontally); left/right docks run as a narrow
   vertical column instead, since they hug a vertical board edge. */
.mono-player-dock {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 3px;
	padding: 1px;
	cursor: pointer;
	/* Forces the dock to size itself to its widest child (the cash-pile row, now much wider than
	   the name label) rather than shrinking to the label's own width - without this, the outer
	   flex layout was sizing the dock box off the label alone, leaving the wider cash row centered
	   within a too-narrow box and visually offset from the label above it. */
	width: max-content;
}

.mono-dock-left .mono-player-dock,
.mono-dock-right .mono-player-dock {
	/* Wide enough to hold the rotated assets viewport (see .mono-dock-assets-viewport) without
	   clipping it - the viewport's own overflow:hidden already trims the rotated content. */
	max-width: 150px;
}

/* Explicit flex `order`: name label first, stats, then the CASH/PROPERTIES asset container last (the
   child nearest the board on every edge). Independent of DOM order so it holds on all four edges. */
.mono-player-label { order: 0; }
.mono-player-stats { order: 1; }
.mono-dock-assets,
.mono-dock-assets-viewport { order: 2; }

/* ---- Uniform CASH / PROPERTIES boxes on every dock (see _renderPlayerCardHtml) ----
   Both asset groups sit side by side in labeled boxes that size to the player's actual cash and
   property count. The whole container is rotated as a unit to face each seat (see the -180/-left/
   -right variants), so all four players' boxes are identical and just reoriented. */
.mono-dock-assets {
	display: flex;
	align-items: flex-start;
	justify-content: center;
	gap: 8px;
	flex-wrap: nowrap;
	width: max-content;
}

/* Seat-facing rotation of the whole container. 180deg (top) keeps width/height, so it needs no
   wrapper. 90deg (left/right) swaps width/height, so those are wrapped in .mono-dock-assets-viewport
   (a fixed-size clip box sized for the post-rotation footprint) and get flex-shrink:0 so the flex
   parent doesn't squash them before the transform is applied. */
.mono-dock-assets-180 { transform: rotate(180deg); }
/* left/right rotation (with absolute-centering translate) is defined below, alongside the side-dock
   viewport that positions them out of flow. */

/* Side docks STACK their CASH/PROPERTIES/CARDS boxes vertically (rather than side by side like top/
   bottom), so the upright container is only one box wide. The CASH box keeps its single row of bills
   (same as every dock). */
.mono-dock-assets-left,
.mono-dock-assets-right {
	flex-direction: column;
	align-items: center;
	gap: 4px;
	width: auto;
}

/* The rotated assets are taken OUT of flow (position:absolute) and centered on the viewport, so
   their true (variable, content-driven) size never clips and never pushes the board sideways - the
   viewport just reserves a fixed, predictable box for the label/stats to sit beside, while the real
   rotated content overflows it invisibly. This replaces the old fixed-size overflow:hidden clip,
   which cut off box edges whenever the content was bigger than the guessed clip dimensions. */
.mono-dock-left .mono-dock-assets-viewport,
.mono-dock-right .mono-dock-assets-viewport {
	position: relative;
	width: 128px;   /* horizontal footprint reserved beside the board (rotated width of the stack) */
	/* Vertical footprint reserved = the rotated height = the one-row CASH box's own width. A full
	   starting-cash stack (all 7 denominations + the $ total, one row) rotates to ~260px, so reserve
	   that much: the box is centered in this box, and if the reserved height matches the content there
	   is no upward overflow into the name label above it (the label sits cleanly above the whole box). */
	height: 264px;
	overflow: visible;
}

.mono-dock-left .mono-dock-assets-viewport > .mono-dock-assets,
.mono-dock-right .mono-dock-assets-viewport > .mono-dock-assets {
	position: absolute;
	top: 50%;
	left: 50%;
}

.mono-dock-assets-left { transform: translate(-50%, -50%) rotate(90deg); }
.mono-dock-assets-right { transform: translate(-50%, -50%) rotate(-90deg); }

.mono-asset-box {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	padding: 3px 6px 4px 6px;
	border: 1px solid var(--panel-border);
	border-radius: var(--radius-sm);
	background: var(--panel-bg);
	box-shadow: var(--shadow-soft);
	flex-shrink: 0;
}

.mono-asset-head {
	font-size: 8px;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--sidebar-text-dim);
}

/* Cash piles inside a box: one row of bill piles with the $ total inline to the right, so the CASH
   box stays short (its height is just one pile tall). */
.mono-asset-box .mono-cash-piles {
	width: auto;
	max-width: 100%;
	flex-direction: row;
	align-items: center;
	gap: 6px;
}

/* CARDS box: holds Get Out of Jail Free card(s), shown only when a player has one (see
   _renderPlayerCardHtml). */
.mono-jailcard-row {
	display: flex;
	align-items: center;
	gap: 2px;
}

.mono-jailcard {
	font-size: 15px;
	line-height: 1;
}

.mono-jailcard-count {
	font-size: 9px;
	font-weight: 800;
	color: var(--sidebar-text);
}

.mono-dock-tradeable {
	/* Same reasoning as .mono-cell-tradeable: this is only clickable while the "choose an action"
	   decision modal's backdrop (z-index 1000) is up, so it must poke through the dimming overlay. */
	position: relative;
	z-index: 1050;
}

.mono-dock-tradeable:hover .mono-player-label {
	background: var(--sidebar-card-active-bg);
	box-shadow: 0 0 0 2px var(--accent-gold);
}

.mono-player-dock.bankrupt {
	opacity: 0.4;
	text-decoration: line-through;
}

.mono-player-label {
	display: flex;
	align-items: center;
	gap: 5px;
	font-weight: bold;
	font-size: 13px;
	padding: 2px 8px;
	border-radius: 10px;
	background: var(--panel-bg);
	box-shadow: var(--shadow-soft);
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
	white-space: nowrap;
}

.mono-player-dock.active .mono-player-label {
	box-shadow: 0 0 0 2px var(--accent-gold);
}

/* Win% + net worth folded into the dock (replaces the old top-center HUD scoreboard). Sits right
   under the name label on every edge (see the flex `order` block above). Win% is colored to match
   the player's seat; net worth is muted so cash-on-hand (the cash piles below) stays the headline. */
.mono-player-stats {
	display: flex;
	align-items: baseline;
	gap: 8px;
	font-size: 12px;
	line-height: 1.1;
	white-space: nowrap;
}

.mono-player-win {
	font-weight: bold;
	font-variant-numeric: tabular-nums;
}

.mono-player-worth {
	color: var(--sidebar-text-dim);
	font-variant-numeric: tabular-nums;
}

/* Marks a player's dock as affected by the trade currently being built in the modal (see
   MonopolyUI._tradePreview) - not yet-real state, so a dashed ring distinguishes it from .active. */
.mono-player-dock-preview .mono-player-label {
	outline: 2px dashed var(--accent-gold);
	outline-offset: 2px;
}

.mono-turn-dot {
	display: inline-block;
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--accent-gold);
	box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.15);
	flex-shrink: 0;
}

.mono-jail-indicator {
	font-size: 11px;
}

/* Cash piles: one clean, un-fanned stack per denomination, laid out in a row like real bank stacks.
   Sizes to its content (the box around it caps the width); no longer a fixed centerpiece width now
   that it lives inside the CASH box. */
.mono-cash-piles {
	display: flex;
	align-items: flex-end;
	justify-content: center;
	gap: 10px;
}

.mono-cash-pile-row {
	display: flex;
	align-items: flex-end;
	justify-content: center;
	flex-wrap: nowrap;
	gap: 4px;
}

/* Each pile is a fixed-structure column: the bill stack, then the count badge row below it. Using
   align-items:flex-end at the ROW level (above) would align whole piles by their outer box, which
   includes the badge row - a pile with a badge (taller box) and one without (shorter box) would
   then have their actual BILLS (the part that should visually line up as sitting on the same
   "table") at different heights. Instead, .mono-bill-stack is pushed to the bottom of its own pile
   via margin-top:auto, so bill bottoms always align across piles regardless of whether that
   particular pile happens to show a badge. */
.mono-bill-pile {
	display: flex;
	flex-direction: column;
	align-items: stretch;
}

.mono-bill-stack {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	margin-top: auto;
}

.mono-bill {
	width: 26px;
	height: 16px;
	border: 1px solid rgba(0, 0, 0, 0.6);
	border-radius: 2px;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 9px;
	font-weight: bold;
	color: rgba(0, 0, 0, 0.65);
	text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}

.mono-bill-stack .mono-bill + .mono-bill {
	margin-top: -11px;
}

/* Always present (a "xN" badge or an &nbsp; placeholder - see MonopolyUI._cashStackHtml) so every
   pile reserves the same badge-row height whether or not it actually has a count to show, keeping
   the bill stacks above it aligned regardless. */
.mono-bill-count {
	margin-top: 2px;
	font-size: 10px;
	font-weight: bold;
	color: var(--sidebar-text);
	text-align: center;
}

/* Colors follow the classic Monopoly bank note palette, so the denomination reads at a glance
   even before you see the printed number. */
.mono-bill-500 { background: repeating-linear-gradient(135deg, #f2d675, #f2d675 3px, #e8c85f 3px, #e8c85f 6px); }
.mono-bill-100 { background: repeating-linear-gradient(135deg, #f0ead8, #f0ead8 3px, #e2d9bf 3px, #e2d9bf 6px); }
.mono-bill-50 { background: repeating-linear-gradient(135deg, #7fc4e8, #7fc4e8 3px, #6bb3da 3px, #6bb3da 6px); }
.mono-bill-20 { background: repeating-linear-gradient(135deg, #f2a25c, #f2a25c 3px, #e88f42 3px, #e88f42 6px); }
.mono-bill-10 { background: repeating-linear-gradient(135deg, #f2e07a, #f2e07a 3px, #e6d160 3px, #e6d160 6px); }
.mono-bill-5 { background: repeating-linear-gradient(135deg, #f0a8c4, #f0a8c4 3px, #e691b3 3px, #e691b3 6px); }
.mono-bill-1 { background: repeating-linear-gradient(135deg, #f5f5f2, #f5f5f2 3px, #e6e6e0 3px, #e6e6e0 6px); }

:root[data-theme="dark"] .mono-bill {
	color: rgba(0, 0, 0, 0.7);
	border-color: rgba(0, 0, 0, 0.75);
}

.mono-cash-amount {
	font-weight: bold;
	font-size: 14px;
	color: var(--sidebar-text);
	white-space: nowrap;
	flex-shrink: 0;
	align-self: center;
}

/* Small title-deed card visual, still used by the bank deck (.mono-deck-card) and the flying-
   property animation (.mono-fly-prop). The dock property view no longer uses these - it uses the
   stacked group grid below - but these two consumers do. */
.mono-mini-prop {
	width: 34px;
	border: 1px solid var(--sidebar-card-border);
	border-radius: 3px;
	overflow: hidden;
	background: var(--sidebar-card-bg);
	position: relative;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

.mono-mini-prop-bar {
	height: 6px;
}

.mono-mini-prop-name {
	font-size: 6px;
	line-height: 1.15;
	padding: 2px 2px;
	min-height: 22px;
	color: var(--sidebar-text);
	word-break: break-word;
	text-align: center;
}

/* ---- PROPERTIES grid: a 2-row x 5-col layout of group cells (see _propertyRowHtml) ----
   Each of the 8 color groups + rails + utilities gets one cell; a player's properties in that group
   stack vertically with only the top card's color fully visible, plus a count. The grid sizes to the
   groups actually owned. Rotation is handled by the parent .mono-dock-assets, so this stays upright. */
.mono-prop-grid {
	display: grid;
	grid-template-columns: repeat(5, auto);
	grid-auto-rows: auto;
	gap: 4px;
	justify-content: center;
	/* At most 10 groups = 2 rows; cap the height (with scroll as a safety net) so the PROPERTIES box
	   - and therefore the dock - can never grow tall enough to push a dock off-screen. */
	max-height: 56px;
	overflow-y: auto;
}

.mono-pg-cell {
	position: relative;
	width: 22px;
	display: flex;
	align-items: center;
	justify-content: center;
}

/* A single-property group shows a full mini card (color bar + name) rather than a bare color
   swatch, so a lone holding is still readable; the cell widens to fit it. */
.mono-pg-cell.single {
	width: 34px;
}

.mono-pg-cell.single .mono-mini-prop {
	width: 34px;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

.mono-pg-cell.single .mono-mini-prop-bar {
	height: 6px;
}

/* Tighter name in the compact dock grid so a single-property card stays about the same height as a
   stacked group cell, keeping the 2-row grid short. */
.mono-pg-cell.single .mono-mini-prop-name {
	min-height: 0;
	font-size: 5.5px;
	line-height: 1.1;
	padding: 1px;
}

/* A full (completed) set gets a gold ring so a monopoly stands out at a glance. */
.mono-pg-cell.full .mono-pg-stack {
	box-shadow: 0 0 0 1.5px var(--accent-gold), 0 1px 2px rgba(0, 0, 0, 0.3);
}

.mono-pg-cell.single.full .mono-mini-prop {
	box-shadow: 0 0 0 1.5px var(--accent-gold), 0 1px 2px rgba(0, 0, 0, 0.3);
}

/* The group's cards stacked with a small vertical offset so only the TOP card's color shows fully;
   the ones behind peek out below it. Height grows with the number owned (--pg-n) up to the offset. */
.mono-pg-stack {
	position: relative;
	width: 20px;
	height: calc(22px + (var(--pg-n) - 1) * 3px);
	border-radius: 3px;
}

.mono-pg-card {
	position: absolute;
	left: 0;
	right: 0;
	/* Card 0 sits fully visible at the top; each later card is offset a few px DOWN and stacked
	   BEHIND (lower z-index) so only its bottom edge peeks out under the one in front - the top
	   card's color is the one that reads. */
	top: calc(var(--pg-i) * 3px);
	z-index: calc(var(--pg-n) - var(--pg-i));
	height: 22px;
	border-radius: 3px;
	background: var(--pg-color);
	border: 1px solid rgba(0, 0, 0, 0.45);
	background-size: 14px 14px;
	background-repeat: no-repeat;
	background-position: center;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
	display: flex;
	align-items: center;
	justify-content: center;
}

.mono-pg-card.mortgaged {
	opacity: 0.45;
}

.mono-pg-mark {
	font-size: 8px;
	font-weight: 800;
	color: #fff;
	text-shadow: 0 0 2px rgba(0, 0, 0, 0.9);
}

.mono-pg-count {
	position: absolute;
	right: -5px;
	bottom: -4px;
	min-width: 12px;
	height: 12px;
	padding: 0 2px;
	border-radius: 6px;
	background: var(--panel-bg);
	border: 1px solid var(--panel-border);
	font-size: 8px;
	font-weight: 800;
	line-height: 12px;
	text-align: center;
	color: var(--sidebar-text);
}

.mono-prop-list {
	max-height: 55vh;
	overflow-y: auto;
	margin: 10px 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
	gap: 8px;
}

/* Title-deed-style card: a color-bar header (matching the property's board group color) over a
   small body, standing in for a physical Monopoly deed card. */
.mono-prop-card {
	border: 1px solid var(--sidebar-card-border);
	border-radius: 6px;
	overflow: hidden;
	background: var(--sidebar-card-bg);
	box-shadow: var(--shadow-soft);
}

.mono-prop-card.mortgaged {
	opacity: 0.55;
}

.mono-prop-card-bar {
	height: 16px;
}

.mono-prop-card-body {
	padding: 6px 8px;
	font-size: 11px;
}

.mono-prop-card-name {
	font-weight: bold;
	color: var(--sidebar-text);
	margin-bottom: 3px;
	line-height: 1.2;
}

.mono-prop-card-row {
	display: flex;
	justify-content: space-between;
	gap: 6px;
}

.mono-prop-status {
	color: var(--hint-text);
	font-size: 10px;
	white-space: nowrap;
}

.mono-prop-rent {
	color: var(--sidebar-text-dim);
	font-size: 10px;
	white-space: nowrap;
}

.mono-controls {
	background: var(--panel-bg);
	color: var(--sidebar-text);
	border: 1px solid var(--panel-border);
	border-radius: 8px;
	padding: 12px;
	box-shadow: var(--shadow-soft);
}

/* During active play #mono-controls is empty (its only content, the AI-speed control, now lives in
   the top-right corner; the Start/Play-Again button only appears between games). Collapse it fully
   when empty so it adds no height or gap to the bottom dock. */
.mono-controls:empty {
	display: none;
}

/* Button system. Default = "primary" (the green table accent) so the main affirmative action in
   any modal (Buy, Send Offer, Roll, End Turn) reads as the obvious choice. `.secondary` is the
   quiet/neutral variant (Pass, Cancel, Withdraw); `.danger` is for destructive/risky choices
   ("Stop - risk bankruptcy"). All three share sizing, focus, and press behavior. */
.mono-btn {
	background: var(--btn-primary-bg);
	color: var(--btn-primary-text);
	border: 1px solid transparent;
	border-radius: var(--radius-sm);
	padding: 9px 14px;
	cursor: pointer;
	font-family: var(--font-ui);
	font-weight: 600;
	font-size: 13px;
	margin: 3px 3px 3px 0;
	transition: background-color 0.15s ease, color 0.15s ease, transform 0.08s ease, box-shadow 0.15s ease;
}

.mono-btn:hover {
	background: var(--btn-primary-hover-bg);
	color: var(--btn-primary-text);
}

.mono-btn:active {
	transform: translateY(1px);
}

.mono-btn:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
}

.mono-btn:disabled {
	opacity: 0.45;
	cursor: not-allowed;
	transform: none;
}

.mono-btn.secondary {
	background: var(--btn-secondary-bg);
	color: var(--btn-text);
	border-color: var(--btn-border);
}

.mono-btn.secondary:hover {
	background: var(--btn-hover-bg);
	color: var(--btn-hover-text);
}

.mono-btn.danger {
	background: var(--btn-danger-bg);
	color: var(--btn-danger-text);
}

.mono-btn.danger:hover {
	background: var(--btn-danger-hover-bg);
	color: var(--btn-danger-text);
}

/* Action-list buttons (build / mortgage / trade rows) - neutral by default so a long list doesn't
   read as a wall of green "primary" calls-to-action; the affirmative default green is reserved for
   the single main action in a modal (e.g. End Turn / Send Offer). */
.mono-btn.small {
	font-size: 11px;
	padding: 7px 10px;
	display: block;
	width: 100%;
	text-align: left;
	box-sizing: border-box;
	margin: 0 0 4px 0;
	background: var(--btn-bg);
	color: var(--btn-text);
	border-color: var(--btn-border);
}

.mono-btn.small:hover {
	background: var(--btn-hover-bg);
	color: var(--btn-hover-text);
}

.mono-speed-row {
	font-size: 12px;
	display: flex;
	align-items: center;
	gap: 6px;
	color: var(--sidebar-text);
}

.mono-speed-row select {
	background: var(--input-bg);
	color: var(--input-text);
	border: 1px solid var(--input-border);
	font-family: var(--font-ui);
	padding: 3px 5px;
}

/* ---- Persistent action bar (bottom dock; see MonopolyUI._renderActionBar) ----
   Replaces the old "choose an action" modal: always visible, shows whose turn it is, and - on the
   human's own turn - the Build / Manage / Trade / Roll|End controls. Non-modal, so the board stays
   clickable behind it (click-to-trade works the whole turn). */
.mono-action-bar {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 10px;
	min-height: 34px;
	padding: 6px 12px;
	border-radius: var(--radius-lg);
	background: var(--panel-bg);
	border: 1px solid var(--panel-border);
	box-shadow: var(--shadow-soft);
	font-family: var(--font-ui);
	position: relative;
	max-width: 640px;
	transition: box-shadow 0.2s ease, border-color 0.2s ease;
}

/* Human's interactive turn: a subtle gold ring so it's clear the ball is in your court. */
.mono-action-bar.you.interactive {
	border-color: var(--accent-gold);
	box-shadow: 0 0 0 2px rgba(224, 165, 0, 0.28), var(--shadow-soft);
}

.mono-action-status {
	font-size: 13px;
	font-weight: 700;
	color: var(--sidebar-text);
	font-variant-numeric: tabular-nums;
}

.mono-action-bar.ai .mono-action-status {
	color: var(--sidebar-text-dim);
	font-weight: 600;
}

.mono-action-btns {
	display: flex;
	align-items: center;
	gap: 6px;
	flex-wrap: wrap;
}

/* Ghost buttons for the secondary action triggers (Build/Manage/Trade) so the primary
   Roll/End button stays the clear focal call-to-action. */
.mono-btn.ghost {
	background: var(--btn-bg);
	color: var(--btn-text);
	border-color: var(--btn-border);
	margin: 0;
	width: auto;
	display: inline-block;
}

.mono-btn.ghost:hover:not(:disabled) {
	background: var(--btn-hover-bg);
	color: var(--btn-hover-text);
}

.mono-btn.small.ghost {
	padding: 6px 10px;
	font-size: 12px;
}

/* Primary variant flag (used for the pre-roll Roll button) - already the default green, this just
   nudges it a touch bigger so it reads as the main action. */
.mono-btn.primary {
	font-weight: 700;
}

/* Inline Build/Manage popover, anchored above the bar (not a modal). */
.mono-action-popover {
	position: absolute;
	bottom: calc(100% + 8px);
	left: 50%;
	transform: translateX(-50%);
	width: min(320px, 90vw);
	max-height: 300px;
	overflow-y: auto;
	background: var(--modal-bg);
	color: var(--modal-text);
	border: 1px solid var(--panel-border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-panel);
	padding: 10px;
	z-index: 60;
	animation: mono-pop-in 0.14s ease-out;
}

@keyframes mono-pop-in {
	from { opacity: 0; transform: translateX(-50%) translateY(6px); }
	to { opacity: 1; transform: translateX(-50%) translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
	.mono-action-popover { animation: none; }
}

.mono-action-popover-title {
	font-size: 10px;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--sidebar-text-dim);
	margin-bottom: 6px;
}

/* The event log (and the "Read more" about blurb, formerly a page-header paragraph - see
   MonopolyUI._toggleAboutPanel) are secondary now that screen space goes to the 4 docks - both
   tucked into the same bottom-right corner as a row of toggle buttons, collapsed by default,
   fully functional once opened. */
.mono-toggle-row {
	position: fixed;
	bottom: 10px;
	right: 10px;
	z-index: 90;
	display: flex;
	gap: 8px;
}

.mono-log-toggle {
	background: var(--btn-bg);
	color: var(--btn-text);
	border: 1px solid var(--btn-border);
	border-radius: 6px;
	padding: 7px 11px;
	cursor: pointer;
	font-family: var(--font-ui);
	font-size: 12px;
	box-shadow: var(--shadow-soft);
}

.mono-log-toggle:hover,
.mono-log-toggle.active {
	background: var(--btn-hover-bg);
	color: var(--btn-hover-text);
}

/* Compact icon-only variant for the low-key debug toggle - a small square bug button that sits
   quietly next to the Log button rather than carrying a "🐞 Debug" text label. */
.mono-log-toggle-icon {
	padding: 7px 8px;
	opacity: 0.6;
}

.mono-log-toggle-icon:hover,
.mono-log-toggle-icon.active {
	opacity: 1;
}

.mono-log-panel {
	position: fixed;
	bottom: 54px;
	right: 10px;
	width: 320px;
	max-width: calc(100vw - 20px);
	display: flex;
	flex-direction: column;
	gap: 6px;
	background: var(--panel-bg);
	border: 1px solid var(--panel-border);
	border-radius: 8px;
	padding: 10px;
	box-shadow: var(--shadow-panel);
	z-index: 90;
	transition: opacity 0.15s ease, transform 0.15s ease;
}

/* The about panel reuses .mono-log-panel's look but has no tabs, just a text blob + close
   button, and sits a bit narrower since it's prose rather than a scrolling log. */
#mono-about-panel {
	width: 300px;
}

#mono-about-panel .mono-log-panel-head {
	align-items: flex-start;
}

.mono-about-body {
	flex: 1;
	font-size: 12px;
	line-height: 1.5;
	color: var(--sidebar-text);
}

.mono-about-body a {
	color: var(--link-color);
}

.mono-about-body a:hover {
	color: var(--link-hover);
}

/* Debug log panel: reuses .mono-log-panel's look but wider (raw JSON-ish lines need room) and its
   body is a scrollable monospace textarea instead of the log's list of styled divs - readonly, so
   it's purely for selecting/copying out, not interaction. See MonopolyUI._dlog. */
#mono-debug-panel {
	width: 480px;
}

.mono-debug-text {
	flex: 1;
	width: 100%;
	height: 260px;
	resize: vertical;
	box-sizing: border-box;
	background: var(--log-bg);
	color: var(--log-text);
	font-family: ui-monospace, Menlo, Monaco, "Cascadia Code", Consolas, monospace;
	font-size: 10px;
	line-height: 1.4;
	padding: 8px;
	border: 1px solid var(--panel-border);
	border-radius: 6px;
	white-space: pre;
	overflow: auto;
}

.mono-log-panel.collapsed {
	display: none;
}

.mono-log-panel-head {
	display: flex;
	align-items: center;
	gap: 6px;
}

.mono-log-panel-head .mono-log-tabs {
	flex: 1;
}

.mono-log-close {
	background: transparent;
	border: none;
	color: var(--sidebar-text);
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
	padding: 2px 6px;
	border-radius: 4px;
	flex-shrink: 0;
}

.mono-log-close:hover {
	background: rgba(128, 128, 128, 0.2);
}

.mono-log-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
}

.mono-log-tab {
	--tab-color: var(--btn-border);
	background: var(--btn-bg);
	color: var(--btn-text);
	border: 1px solid var(--tab-color);
	border-radius: 4px;
	padding: 4px 9px;
	font-family: var(--font-ui);
	font-size: 11px;
	cursor: pointer;
	transition: background-color 0.15s ease, color 0.15s ease;
}

.mono-log-tab:hover {
	background: var(--tab-color);
	color: #fff;
}

.mono-log-tab.active {
	background: var(--tab-color);
	color: #fff;
	font-weight: bold;
}

.mono-log {
	background: var(--log-bg);
	color: var(--log-text);
	font-size: 11px;
	padding: 10px;
	height: 200px;
	overflow-y: auto;
	border: 1px solid var(--panel-border);
	border-radius: 8px;
	box-shadow: var(--shadow-soft);
}

.mono-log-line {
	margin-bottom: 3px;
	white-space: pre-wrap;
	line-height: 1.4;
}

.mono-modal-backdrop {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.6);
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 1000;
}

/* The properties viewer is informational and user-triggered (not gating any decision), so it
   must always render above the decision modal - a human peeking at holdings mid-decision should
   never lose their pending buy/trade/jail choice underneath it. */
#mono-props-modal-backdrop {
	z-index: 1100;
	background: rgba(0, 0, 0, 0.45);
}

/* Decision modals (buy/jail/action/trade/auction/trade-response) anchor just above the human's
   dock at the bottom of the board, so a choice reads as "made at your seat" rather than a
   disconnected popup - but only when there's realistically room for a modal above the dock
   without clipping. Below ~760px tall or ~760px wide that math gets unreliable (the dock, board,
   and modal all fight for the same space), so fall back to the simple centered overlay there
   rather than measuring exact geometry in JS. */
@media (min-height: 760px) and (min-width: 760px) {
	#mono-modal-backdrop {
		align-items: flex-end;
		padding-bottom: 4vh;
	}
}

.mono-modal {
	background: var(--modal-bg);
	color: var(--modal-text);
	border: var(--border-thick) solid var(--modal-border);
	border-radius: var(--radius-lg);
	animation: mono-modal-in 0.18s cubic-bezier(0.2, 0.9, 0.3, 1.2);
	padding: 18px 20px;
	max-width: 460px;
	width: 90%;
	max-height: 85vh;
	overflow-y: auto;
	font-size: 13px;
	box-shadow: var(--shadow-panel);
}

/* #mono-modal specifically (not props/event modals) also needs its own clamp in anchored mode -
   flex-end alignment above means it can grow upward off-screen instead of centering, so cap it
   a bit tighter than the general 85vh. */
@media (min-height: 760px) and (min-width: 760px) {
	#mono-modal {
		max-height: 70vh;
	}
}

@keyframes mono-modal-in {
	from { opacity: 0; transform: translateY(8px) scale(0.97); }
	to { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
	.mono-modal { animation: none; }
}

.mono-modal h3 {
	margin-top: 0;
}

.mono-modal-actions {
	display: flex;
	gap: 8px;
	margin-top: 14px;
	flex-wrap: wrap;
}

/* Grouped action-menu sections (Build / Manage / Trade) - a small uppercase heading over that
   category's buttons, so a long action list is scannable by type rather than a flat wall. */
.mono-action-section {
	margin-top: 12px;
}

.mono-action-heading {
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--sidebar-text-dim);
	margin-bottom: 5px;
}

/* the cost/gain figure trailing an action button, right-aligned and tabular so amounts line up */
.mono-action-cost {
	float: right;
	font-variant-numeric: tabular-nums;
	color: var(--sidebar-text-dim);
	font-weight: 700;
}

.mono-btn.small:hover .mono-action-cost {
	color: inherit;
}

.mono-modal-actions.vertical {
	flex-direction: column;
}

.mono-hint {
	color: var(--hint-text);
	font-size: 11px;
}

.mono-input {
	font-family: var(--font-ui);
	background: var(--input-bg);
	color: var(--input-text);
	padding: 5px 7px;
	border: 1px solid var(--input-border);
	border-radius: 4px;
	width: 100%;
	box-sizing: border-box;
	margin: 6px 0;
}

.mono-input.small {
	width: 100px;
}

.mono-trade-cols {
	display: flex;
	gap: 16px;
	margin-top: 10px;
}

/* Live "will they accept?" meter under the trade builder - color-coded by how the AI target's own
   valuation math scores the current offer (see MonopolyUI._updateTradeFairness). */
.mono-trade-fairness {
	margin-top: 12px;
	padding: 8px 10px;
	border-radius: var(--radius-sm);
	border: 1px solid var(--panel-border);
	background: var(--input-bg);
	font-size: 12px;
	min-height: 20px;
}

.mono-trade-fairness.good { border-color: #2f9e44; background: rgba(47, 158, 68, 0.12); }
.mono-trade-fairness.close { border-color: var(--accent-gold); background: rgba(224, 165, 0, 0.12); }
.mono-trade-fairness.bad { border-color: #c0392b; background: rgba(192, 57, 43, 0.12); }

.mono-fairness-label {
	font-weight: 700;
}

.mono-fairness-detail {
	font-size: 10.5px;
	color: var(--sidebar-text-dim);
	font-variant-numeric: tabular-nums;
	margin-top: 2px;
}

/* Notification for AI decisions and automatic game events (rent, tax, card draws, jail,
   bankruptcy, auction results, passing Go) - lives on the board itself, overlaid on the center
   logo area (see .mono-center-title, hidden while a notice is showing) rather than a blocking
   centered popup. Auto-dismisses after a short delay instead of requiring a click (click just
   skips the wait) - see MonopolyUI._drainEventQueue. Queued one at a time so the game effectively
   pauses until each is shown and cleared. */
.mono-event-notice {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 78%;
	max-width: 320px;
	background: var(--modal-bg);
	color: var(--modal-text);
	border: 3px solid var(--modal-border);
	border-radius: 10px;
	padding: 12px 14px;
	font-size: 12px;
	text-align: center;
	box-shadow: var(--shadow-panel);
	cursor: pointer;
	z-index: 5;
	animation: mono-notice-in 0.22s ease-out;
}

@keyframes mono-notice-in {
	from { opacity: 0; transform: translate(-50%, -50%) scale(0.92); }
	to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
	.mono-event-notice { animation: none; }
}

.mono-event-notice p {
	margin: 4px 0;
}

.mono-event-notice h3 {
	margin: 0 0 6px 0;
	font-size: 14px;
}

.mono-event-title {
	font-weight: 700;
	font-size: 14px;
	margin-bottom: 6px;
}

.mono-trade-cols > div {
	flex: 1;
}

/* Trade-response (AI-proposed) two-panel layout: what you'd receive vs give up, color-tinted. */
.mono-trade-response {
	display: flex;
	gap: 10px;
	margin: 12px 0;
}

.mono-trade-side {
	flex: 1;
	padding: 8px 10px;
	border-radius: var(--radius-sm);
	border: 1px solid var(--panel-border);
	font-size: 12px;
}

.mono-trade-side.get { background: rgba(47, 158, 68, 0.1); border-color: #2f9e44; }
.mono-trade-side.give { background: rgba(192, 57, 43, 0.08); border-color: #c0392b; }

.mono-trade-side-head {
	font-size: 10px;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--sidebar-text-dim);
	margin-bottom: 4px;
}

/* ---- Trade tray (docked side panel; see MonopolyUI._renderTradeTray) ----
   Non-modal, fixed to the right edge of the viewport so the live board stays visible and clickable
   behind it: clicking board tiles adds/removes them from the offer (_tradeAddProp). Slides in from
   the right. On narrow screens it drops to a bottom sheet. */
/* Centered trade panel. Kept narrow (320px) and WITHOUT a full-screen dimming backdrop so the board
   stays visible - and clickable - around it, preserving click-a-tile-to-add. It floats over the
   board's center; the board tiles around the edges remain reachable. */
.mono-trade-tray {
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 320px;
	max-width: calc(100vw - 32px);
	max-height: 88vh;
	overflow-y: auto;
	display: flex;
	flex-direction: column;
	gap: 8px;
	background: var(--modal-bg);
	color: var(--modal-text);
	border: 1px solid var(--panel-border);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-panel);
	padding: 14px;
	z-index: 900;
	animation: mono-tray-in 0.18s cubic-bezier(0.2, 0.9, 0.3, 1.1);
}

@keyframes mono-tray-in {
	from { opacity: 0; transform: translate(-50%, calc(-50% + 12px)); }
	to { opacity: 1; transform: translate(-50%, -50%); }
}

@media (prefers-reduced-motion: reduce) {
	.mono-trade-tray { animation: none; }
}

.mono-trade-tray-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
}

.mono-trade-tray-head h3 {
	margin: 0;
	font-size: 15px;
}

.mono-tray-close {
	background: none;
	border: none;
	color: var(--sidebar-text-dim);
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
	padding: 0 4px;
}

.mono-tray-close:hover { color: var(--sidebar-text); }

.mono-trade-target-row {
	font-size: 12px;
	display: flex;
	align-items: center;
	gap: 6px;
}

.mono-trade-target-row select {
	background: var(--input-bg);
	color: var(--input-text);
	border: 1px solid var(--input-border);
	font-family: var(--font-ui);
	padding: 3px 6px;
	flex: 1;
}

.mono-trade-help {
	margin: 0;
	font-size: 11px;
}

/* Each side of the deal (give / get) is its own tinted panel of removable property chips. */
.mono-trade-side-panel {
	padding: 8px 10px;
	border-radius: var(--radius-sm);
	border: 1px solid var(--panel-border);
}

.mono-trade-side-panel.give { background: rgba(192, 57, 43, 0.08); border-color: #c0392b; }
.mono-trade-side-panel.get { background: rgba(47, 158, 68, 0.1); border-color: #2f9e44; }

.mono-trade-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 5px;
	margin: 6px 0;
	min-height: 22px;
}

.mono-trade-chip {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	font-size: 11px;
	font-family: var(--font-ui);
	font-weight: 600;
	padding: 3px 7px;
	border-radius: 999px;
	border: 1px solid var(--panel-border);
	background: var(--input-bg);
	color: var(--body-text);
	cursor: pointer;
	transition: background-color 0.12s ease, border-color 0.12s ease;
}

.mono-trade-chip:hover {
	border-color: #c0392b;
	background: rgba(192, 57, 43, 0.12);
}

.mono-trade-chip-bar {
	width: 8px;
	height: 8px;
	border-radius: 2px;
	flex: 0 0 auto;
}

.mono-trade-chip-x {
	font-weight: 800;
	color: var(--sidebar-text-dim);
}

.mono-trade-chip-ask {
	font-size: 10px;
	color: var(--sidebar-text-dim);
	font-variant-numeric: tabular-nums;
}

.mono-trade-extras {
	display: flex;
	align-items: center;
	gap: 12px;
	font-size: 12px;
	flex-wrap: wrap;
}

.mono-trade-extras .mono-input.small {
	width: 72px;
}

.mono-trade-cardbox {
	display: inline-flex;
	align-items: center;
	gap: 4px;
}

.mono-trade-tray-actions {
	display: flex;
	gap: 8px;
	margin-top: 4px;
}

.mono-trade-tray-actions .mono-btn {
	flex: 1;
	margin: 0;
	text-align: center;
}

/* "Ask what they want for it" - full-width secondary action below the main Send/Cancel row. */
.mono-trade-ask {
	width: 100%;
	margin: 6px 0 0 0;
	text-align: center;
}

/* Selected-in-trade board tiles get a distinct green ring so you can see the deal on the board. */
.mono-cell-in-trade {
	box-shadow: inset 0 0 0 2px #2f9e44, 0 0 8px 1px rgba(47, 158, 68, 0.5) !important;
}

/* Narrow screens: dock the tray to the bottom as a full-width sheet instead of a right rail. */
@media (max-width: 700px) {
	.mono-trade-tray {
		top: auto;
		bottom: 0;
		right: 0;
		left: 0;
		width: 100%;
		max-width: 100%;
		max-height: 70vh;
		transform: none;
		border-radius: var(--radius-lg) var(--radius-lg) 0 0;
		animation: mono-tray-in-bottom 0.18s ease-out;
	}
	@keyframes mono-tray-in-bottom {
		from { opacity: 0; transform: translateY(24px); }
		to { opacity: 1; transform: translateY(0); }
	}
}

/* ---- Live auction room (see MonopolyUI._renderAuctionRoom) ---- */
.mono-auction-room {
	background: var(--modal-bg);
	color: var(--modal-text);
	border: var(--border-thick) solid var(--modal-border);
	border-radius: var(--radius-lg);
	padding: 18px 20px;
	max-width: 460px;
	width: 92%;
	max-height: 88vh;
	overflow-y: auto;
	font-size: 13px;
	box-shadow: var(--shadow-panel);
	animation: mono-modal-in 0.18s cubic-bezier(0.2, 0.9, 0.3, 1.2);
}

.mono-auction-room h3 { margin-top: 0; }

.mono-auc-high {
	text-align: center;
	font-size: 15px;
	margin: 10px 0;
	font-variant-numeric: tabular-nums;
}

/* per-player seats around the auction - shows who's still in, who holds the high bid, and cash */
.mono-auc-seats {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 6px;
	margin: 10px 0;
}

.mono-auc-seat {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 5px 8px;
	border-radius: var(--radius-sm);
	border: 1px solid var(--panel-border);
	background: var(--sidebar-card-bg);
	font-size: 12px;
	transition: box-shadow 0.15s ease, opacity 0.2s ease, background-color 0.2s ease;
}

.mono-auc-seat.high {
	background: var(--sidebar-card-active-bg);
	box-shadow: inset 0 0 0 2px var(--accent-gold);
}

.mono-auc-seat.out {
	opacity: 0.4;
}

.mono-auc-seat.you .mono-auc-name { text-decoration: underline; }

/* brief flash when a bidder's bid/pass just landed */
.mono-auc-seat.pinged {
	animation: mono-auc-ping 0.5s ease-out;
}

@keyframes mono-auc-ping {
	0% { transform: scale(1.06); box-shadow: 0 0 12px 2px rgba(224, 165, 0, 0.7); }
	100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
	.mono-auc-seat.pinged { animation: none; }
	.mono-auction-room { animation: none; }
}

.mono-auc-token { font-size: 14px; }
.mono-auc-name { font-weight: 700; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mono-auc-status { font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }
.mono-auc-cash { font-size: 10px; color: var(--sidebar-text-dim); font-variant-numeric: tabular-nums; }

.mono-auc-history {
	background: var(--input-bg);
	border: 1px solid var(--panel-border);
	border-radius: var(--radius-sm);
	padding: 6px 8px;
	margin: 10px 0;
	max-height: 90px;
	overflow-y: auto;
	font-size: 11px;
}

.mono-auc-hist-line { padding: 1px 0; font-variant-numeric: tabular-nums; }

.mono-auc-controls { margin-top: 12px; }

.mono-auc-quickrow {
	display: flex;
	gap: 6px;
	margin-bottom: 8px;
}

.mono-auc-quick { flex: 1; margin: 0; }

.mono-auc-customrow {
	display: flex;
	gap: 6px;
	align-items: center;
}

.mono-auc-customrow .mono-input { margin: 0; flex: 1; }
.mono-auc-customrow .mono-btn { margin: 0; }

.mono-auc-prompt {
	text-align: center;
	font-size: 11px;
	color: var(--hint-text);
	margin-top: 8px;
	min-height: 14px;
}

.mono-auc-result {
	text-align: center;
	font-size: 14px;
	font-weight: 700;
	padding: 10px;
	margin-bottom: 12px;
	border-radius: var(--radius-sm);
	background: var(--sidebar-card-active-bg);
	font-variant-numeric: tabular-nums;
}

.mono-auc-result.win {
	background: #2f9e44;
	color: #fff;
}

.mono-trade-cols h4 {
	margin: 4px 0;
	font-size: 12px;
}

.mono-checkbox-row {
	display: block;
	font-size: 11px;
	margin: 3px 0;
}

.mono-ask-price {
	margin: 2px 0 6px 18px;
	padding: 2px 8px;
	font-size: 10px;
}

.mono-ask-result {
	display: block;
	margin: 0 0 6px 18px;
}

@media (max-width: 900px) {
	.mono-cell-label {
		font-size: 6px;
	}
	.mono-dock-left .mono-player-dock,
	.mono-dock-right .mono-player-dock {
		max-width: 100px;
	}
	.mono-mini-prop {
		width: 26px;
	}
	.mono-mini-prop-name {
		font-size: 5px;
		min-height: 18px;
	}
	.mono-bill {
		width: 18px;
		height: 11px;
	}
	.mono-bill-stack .mono-bill + .mono-bill {
		margin-top: -7px;
	}
	.mono-log-panel {
		width: calc(100vw - 20px);
	}
}

/* Narrow enough that the board-fused side docks would overlap the board's own cells - drop the
   absolute positioning and let all 4 docks fall into normal document flow instead (top opponent,
   board, left/right opponents, human dock, in reading order) so nothing overlaps or clips. Property
   rows also drop their seat-facing rotation here: stacked in normal flow, upright reading order is
   more useful than seat-facing rotation once there's no board edge left to face. */
@media (max-width: 560px) {
	.mono-table {
		margin-top: 10px;
	}
	.mono-dock-top,
	.mono-dock-left,
	.mono-dock-right {
		position: static;
		transform: none;
		max-width: none;
		max-height: none;
		margin: 6px auto;
	}
	.mono-dock-left .mono-player-dock,
	.mono-dock-right .mono-player-dock {
		max-width: none;
	}
	/* No board to face in the stacked layout - every dock's asset boxes read upright rather than
	   rotated toward a seat, and the side docks' rotation viewport / out-of-flow positioning is no
	   longer needed. */
	.mono-dock-assets-180,
	.mono-dock-assets-left,
	.mono-dock-assets-right {
		transform: none;
	}
	.mono-dock-left .mono-dock-assets-viewport > .mono-dock-assets,
	.mono-dock-right .mono-dock-assets-viewport > .mono-dock-assets {
		position: static;
		top: auto;
		left: auto;
	}
	.mono-dock-assets-viewport,
	.mono-dock-left .mono-dock-assets-viewport,
	.mono-dock-right .mono-dock-assets-viewport {
		width: auto;
		height: auto;
	}
	.mono-dock-assets {
		flex-direction: column;
		align-items: center;
	}
}
