/* UNO Game — front-end styles. Mobile-first: this is a phone/party game. */
/* Fixed full-screen background layer, admin-configurable (solid /
 * gradient / image) — sits behind #ug-app, which goes transparent via
 * inline style in UG_Shortcode::render() so this shows through. Does
 * not affect .ug-screen--table's own felt-green gradient. */
.ug-bg-layer {
	position: fixed; inset: -20px; z-index: -1;
	background-repeat: no-repeat; background-size: auto 100%; background-position: center;
}

/* Color custom properties live on :root (not #ug-app) on purpose: any
 * modal/overlay/toast/flying-card element appended straight to
 * document.body (color picker, draw overlay, card-flight animation —
 * see game.js) is OUTSIDE the #ug-app subtree, and var(--ug-red) etc.
 * would resolve to nothing there if these were scoped to #ug-app only.
 * :root is a strict superset scope of #ug-app so nothing inside #ug-app
 * loses anything by this move (bug: 3 of 4 color-picker swatches were
 * invisible because of exactly this scoping mistake). */
:root {
	--ug-red: #e63946;
	--ug-red-dark: #b8202c;
	--ug-yellow: #ffc93c;
	--ug-yellow-dark: #d9a300;
	--ug-green: #2a9d5c;
	--ug-green-dark: #1c7a44;
	--ug-blue: #2472c8;
	--ug-blue-dark: #1a539c;
	/* Table-UI "action needed" accent (status bar / draw hint) — 2026-09-27. */
	--ug-orange: #ff8f1f;
	/* "ชมพูโอรส" (peach-pink) — setup-screen primary button — 2026-09-27. */
	--ug-peach: #ff9a8b;
	/* Admin-configurable outside-box text colour (see UG_Background::
	 * text_color()); the live value is also written straight into
	 * :root via an inline <style> from layer_html(), so it's correct
	 * even before this stylesheet finishes loading. Defaults to the
	 * plugin's original ink tone -- an untouched install looks exactly
	 * as before. */
	--ug-text: #1b1b1b;
}

#ug-app,
#ug-app *:not(h1, h2, h3, h4, h5, p) {
	font-family: 'db', 'SF Thonburi', 'Sarabun', sans-serif !important;
	font-weight: normal !important;
}

#ug-app {
	--ug-wild-1: #2b2b2b;
	--ug-wild-2: #000000;
	--ug-bg: #0e3b2e;
	--ug-bg-2: #12503d;
	--ug-panel: #ffffff;
	--ug-ink: #1b1b1b;
	--ug-muted: #6b7280;
	--ug-radius: 14px;
	--ug-shadow: 0 6px 18px rgba(0,0,0,.25);
	/* Outside-box text colour: falls back to the fixed ink tone if
	 * somehow unset. Elements on their own white panel/card background
	 * pin their own colour back to --ug-ink explicitly further down,
	 * so this only ever reaches text directly on the page background. */
	color: var(--ug-text, var(--ug-ink));
	max-width: 720px;
	margin: 0 auto;
	box-sizing: border-box;
}
#ug-app, #ug-app * { box-sizing: border-box; }
/* Outside-box text colour, not the fixed muted gray: sits directly on
 * the page background, no panel behind it. */
#ug-app .ug-loading { text-align: center; padding: 60px 0; color: var(--ug-text, var(--ug-muted)); }

#ug-app button {
	font-family: inherit;
	cursor: pointer;
	border: none;
	border-radius: 10px;
}
#ug-app input[type="text"] {
	font-family: inherit;
	font-size: 16px;
	padding: 12px 14px;
	border-radius: 10px;
	border: 2px solid #d8dde3;
	width: 100%;
}
#ug-app input[type="text"]:focus { outline: none; border-color: var(--ug-blue); }

/* ---------------------------------------------------------------
 * Screens shell
 * ------------------------------------------------------------- */
.ug-screen {
	min-height: 60vh;
	padding: 20px 16px 40px;
}
/* Setup/menu/lobby screens only (not the in-table felt or the
 * game-over screen, which keep their own layouts and colours):
 * user-requested layout (2026-09-27, revised same day to match the
 * other sibling plugins — หมากฮอส/อาตาริ/โดมิโน่/ผสมสิบ) — the back
 * button moves below the primary "start" button instead of sitting
 * above the form, restyled as a snug white pill (width fits its own
 * text, NOT full width like the primary button) with normal dark ink
 * text and rounded corners. Flex column + order (rather than
 * reordering markup in every screen's render function) so this
 * applies uniformly wherever the shared backButton() helper is used. */
.ug-screen:not(.ug-screen--table):not(.ug-gameover) {
	display: flex;
	flex-direction: column;
}
.ug-screen:not(.ug-screen--table):not(.ug-gameover) > .ug-back-btn {
	order: 2;
	align-self: flex-start;
}
.ug-screen--table {
	min-height: 100vh;
	padding: 12px 8px 130px;
	position: relative;
	isolation: isolate;
	overflow: hidden;
	border-radius: var(--ug-radius);
	/* Admin-configurable table felt (see UG_Background::table_*()) — the
	 * var()'s 2nd argument is today's exact dark-green felt, so with no
	 * admin config at all (no inline --ug-table-bg on #ug-app) this is
	 * pixel-identical to before. Solid/gradient modes just set this var
	 * straight from PHP; image mode instead leaves this as the fallback
	 * felt and drives the ::before layer below (so blur never touches
	 * the cards/text on top of it). */
	background: var(--ug-table-bg, radial-gradient(ellipse at center, var(--ug-bg-2) 0%, var(--ug-bg) 100%));
}
.ug-screen--table::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 0;
	border-radius: inherit;
	background-image: var(--ug-table-bg-image, none);
	background-size: cover;
	background-position: center;
	filter: var(--ug-table-bg-blur, none);
	pointer-events: none;
}
.ug-screen--table > * { position: relative; z-index: 1; }

/* Outside-box text colour, not the fixed muted gray: no panel behind
 * this button on the home screen (the in-table variant right below
 * keeps its own fixed white-on-felt colour, unaffected). */
.ug-back-btn {
	background: none;
	color: var(--ug-text, var(--ug-muted));
	font-size: 14px;
	padding: 8px 4px;
	margin-bottom: 8px;
}
.ug-back-btn:before { content: "← "; }
.ug-screen--table .ug-back-btn { color: rgba(255,255,255,.75); }

/* In-table "ย้อนกลับ" (was "ออกจากห้อง"), 2026-09-30: same black pill / white text
 * as the sibling games' leave button, sized to its text. */
.ug-screen--table .ug-back-btn.ug-leave-pill {
	background: #000; color: #fff; border-radius: 999px; padding: 10px 22px;
	font-size: 15px; font-weight: 600; line-height: 1.2; width: fit-content; align-self: flex-start;
}
.ug-screen--table .ug-back-btn.ug-leave-pill:before { content: none; }
.ug-screen--table .ug-back-btn.ug-leave-pill:hover { background: #1c1c1c; }

/* Setup/menu/lobby screens only — snug white pill, width fits its
 * own text, rounded corners, sits below the primary button (order:2
 * + align-self:flex-start above). Overrides the plain-text-link look
 * from the base .ug-back-btn rule just above, matching the style now
 * used across หมากฮอส/อาตาริ/โดมิโน่/ผสมสิบ. */
.ug-screen:not(.ug-screen--table):not(.ug-gameover) > .ug-back-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	background: #ffffff;
	border: 1.5px solid #e7e7e7;
	border-radius: 999px;
	color: var(--ug-ink);
	font-size: 14px;
	font-weight: 600;
	padding: 10px 18px;
	margin-top: 14px;
	margin-bottom: 0;
	cursor: pointer;
	box-shadow: var(--ug-shadow);
}

/* ---------------------------------------------------------------
 * Home / mode select
 * ------------------------------------------------------------- */
.ug-logo {
	text-align: center;
	font-weight: 900;
	font-size: 56px;
	letter-spacing: 4px;
	margin: 10px 0 4px;
	line-height: 1;
}
.ug-logo span { display: inline-block; padding: 2px 10px; border-radius: 10px; color: #fff; text-shadow: 0 2px 0 rgba(0,0,0,.2); }
.ug-logo .u { background: var(--ug-red); transform: rotate(-6deg); }
.ug-logo .n { background: var(--ug-yellow); color: #2b2b2b; text-shadow: none; }
.ug-logo .o { background: var(--ug-blue); transform: rotate(6deg); }
.ug-logo img { width: 220px; max-width: 80%; height: auto; display: inline-block; }
.ug-home-title { text-align: center; font-size: 24px; font-weight: 800; margin: 8px 0 4px; }
/* Outside-box text colour, not the fixed muted gray: both sit directly
 * on the home-screen background, no panel behind either. */
.ug-subtitle { text-align: center; color: var(--ug-text, var(--ug-muted)); margin-bottom: 28px; }
/* Snug white pill, rounded corners, black ink, centered under the mode
 * list (user request 2026-09-27: unify "กลับหน้าหลัก" across
 * uno-game/domino-game/phom-sib-game as a white/rounded/black-text
 * button sized to its own text, kept centered) -- was a plain
 * underline-free text link with a top divider border; `display:flex`
 * + `width:fit-content` + `margin:auto` centers a shrink-to-fit block
 * without needing a wrapper element. */
/* .ug-customize-toggle (🎨 ปรับแต่งสี) now sits paired with this button in
 * one row (see .ug-home-btn-row below, 2026-09-28 request, same layout as
 * phom-sib-game's home screen) — both share this look, each taking half
 * the row's width instead of .ug-home-link's old shrink-to-fit/centered
 * sizing. */
.ug-home-btn-row { display: flex; gap: 10px; margin: 18px 0 0; }
.ug-home-link,
.ug-customize-toggle {
	flex: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	background: #ffffff;
	border: 1.5px solid #e7e7e7;
	border-radius: 999px;
	color: var(--ug-ink);
	font-size: 14px;
	font-weight: 600;
	padding: 10px 18px;
	text-decoration: none;
	box-shadow: var(--ug-shadow);
	cursor: pointer;
}

.ug-mode-list { display: flex; flex-direction: column; gap: 14px; }
.ug-mode-btn {
	display: flex;
	align-items: center;
	gap: 14px;
	background: var(--ug-panel);
	border: 2px solid #eceff2;
	border-radius: var(--ug-radius);
	padding: 16px 18px;
	text-align: left;
	box-shadow: var(--ug-shadow);
	transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.ug-mode-btn:active { transform: scale(.98); }
.ug-mode-btn:hover { border-color: var(--ug-blue); transform: translateY(-1px); box-shadow: 0 10px 22px rgba(20,30,60,.18); }
.ug-mode-btn .ug-mode-icon {
	width: 46px; height: 46px; border-radius: 50%; flex: 0 0 auto;
	display: flex; align-items: center; justify-content: center;
	background: #ffffff; color: var(--ug-blue);
	border: 1px solid #eceff2; box-shadow: 0 2px 6px rgba(20,30,60,.10);
}
.ug-mode-btn .ug-mode-icon svg { width: 24px; height: 24px; }

/* Mode-select icons (2026-09-30): white line icon on a diagonal
 * (top-left -> bottom-right) gradient disc, same in all card games.
 * vs computer = blue-green, same device = yellow-orange, online = pink-purple. */
.ug-mode-btn .ug-mode-icon.ug-mode-icon--computer, .ug-mode-btn .ug-mode-icon.ug-mode-icon--phone, .ug-mode-btn .ug-mode-icon.ug-mode-icon--globe { color: #ffffff; border-color: transparent; }
.ug-mode-btn .ug-mode-icon.ug-mode-icon--computer { background: linear-gradient(135deg, #29b6f6 0%, #12c98b 100%); box-shadow: 0 3px 8px rgba(18,201,139,.35); }
.ug-mode-btn .ug-mode-icon.ug-mode-icon--phone { background: linear-gradient(135deg, #ffd23f 0%, #ff8a1f 100%); box-shadow: 0 3px 8px rgba(255,138,31,.35); }
.ug-mode-btn .ug-mode-icon.ug-mode-icon--globe { background: linear-gradient(135deg, #ff5fa2 0%, #8b5cf6 100%); box-shadow: 0 3px 8px rgba(139,92,246,.35); }
.ug-mode-btn .ug-mode-title { font-weight: 700; font-size: 17px; color: var(--ug-ink); }
.ug-mode-btn .ug-mode-hint { color: var(--ug-muted); font-size: 13px; margin-top: 2px; }

/* ---------------------------------------------------------------
 * Setup / form screens
 * ------------------------------------------------------------- */
.ug-field { margin-bottom: 18px; }
/* Outside-box text colour: .ug-screen has no card background of its
 * own, so these labels (nickname, number of players, per-player
 * names, room code) sit directly on the page background. */
.ug-field label { display: block; font-weight: 700; margin-bottom: 6px; font-size: 14px; color: var(--ug-text, var(--ug-ink)); }

.ug-stepper { display: flex; align-items: center; gap: 14px; }
.ug-stepper button {
	width: 40px; height: 40px; font-size: 20px; font-weight: 700;
	background: #eef1f4; color: var(--ug-ink);
}
.ug-stepper .ug-stepper-val { font-size: 20px; font-weight: 700; min-width: 24px; text-align: center; }

.ug-primary-btn {
	width: 100%;
	padding: 15px;
	font-size: 17px;
	font-weight: 700;
	color: #fff;
	background: var(--ug-green);
	box-shadow: var(--ug-shadow);
	margin-top: 6px;
	border: 1.5px solid transparent;
	transition: transform .12s ease, box-shadow .12s ease, filter .12s ease;
}
.ug-primary-btn:hover:not(:disabled) { filter: brightness(1.08); transform: translateY(-1px); }
.ug-primary-btn:disabled { background: #b7c0c9; box-shadow: none; cursor: not-allowed; }
/* Requested 2026-09-27: every green "start" button on the pre-game setup
 * screens (vs-computer, pass & play, and online create/join/lobby — all
 * share this same .ug-primary-btn class) becomes peach-pink instead.
 * Scoped to exclude .ug-gameover so "เล่นอีกครั้ง" (play again), which
 * shares the class but sits on a different screen the user didn't
 * mention, keeps its original green look — same :not() convention this
 * file already uses elsewhere to separate setup screens from game-over. */
.ug-screen:not(.ug-gameover) .ug-primary-btn { background: var(--ug-accent, var(--ug-peach)); }
.ug-screen:not(.ug-gameover) .ug-primary-btn:disabled { background: #b7c0c9; }
.ug-secondary-btn {
	width: 100%;
	padding: 13px;
	font-size: 15px;
	font-weight: 600;
	color: var(--ug-ink);
	background: #eef1f4;
	margin-top: 10px;
}

.ug-two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.ug-error-msg {
	background: #fdecea;
	color: #b8202c;
	border-radius: 8px;
	padding: 10px 12px;
	font-size: 14px;
	margin: 10px 0;
}

/* ---------------------------------------------------------------
 * Online lobby
 * ------------------------------------------------------------- */
.ug-room-code-box {
	text-align: center;
	background: var(--ug-panel);
	border-radius: var(--ug-radius);
	padding: 20px;
	box-shadow: var(--ug-shadow);
	margin-bottom: 18px;
}
.ug-room-code-box .ug-room-code {
	font-size: 40px;
	font-weight: 900;
	letter-spacing: 8px;
	color: var(--ug-blue);
}
.ug-room-code-box .ug-room-code-hint { color: var(--ug-muted); font-size: 13px; margin-top: 6px; }

.ug-lobby-list { display: flex; flex-direction: column; gap: 8px; margin: 16px 0; }
/* Fixed ink, not --ug-text: white panel. */
.ug-lobby-player {
	display: flex; align-items: center; gap: 10px;
	background: var(--ug-panel);
	border-radius: 10px;
	padding: 10px 14px;
	box-shadow: 0 2px 6px rgba(0,0,0,.08);
	color: var(--ug-ink);
}
.ug-avatar {
	width: 36px; height: 36px; border-radius: 50%;
	background: var(--ug-blue); color: #fff;
	display: flex; align-items: center; justify-content: center;
	font-weight: 700; font-size: 15px; flex: 0 0 auto;
}
.ug-lobby-player .ug-tag {
	margin-left: auto; font-size: 12px; color: var(--ug-muted); background: #f0f2f5; padding: 3px 8px; border-radius: 20px;
}

/* ---------------------------------------------------------------
 * Table
 * ------------------------------------------------------------- */
.ug-opponents {
	display: flex;
	justify-content: center;
	gap: 10px;
	flex-wrap: wrap;
	padding: 8px 4px 18px;
}
.ug-opponent {
	background: rgba(255,255,255,.08);
	border: 2px solid transparent;
	border-radius: 12px;
	padding: 8px 10px;
	text-align: center;
	color: #fff;
	min-width: 74px;
	position: relative;
	transition: border-color .2s ease, background .2s ease;
}
.ug-opponent.is-turn {
	border-color: var(--ug-yellow);
	background: rgba(255,201,60,.18);
	box-shadow: 0 0 14px rgba(255,201,60,.5);
}
.ug-opponent .ug-avatar { margin: 0 auto 4px; }
.ug-opponent .ug-nickname { font-size: 12px; font-weight: 600; max-width: 74px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 2-player game (1 opponent): expand that opponent's box to fill the
 * whole top edge, on EVERY screen size — not just the desktop/landscape
 * grid breakpoint further down (2026-09-27 request: "ถ้าเล่นสองคน ...
 * ขยายพื้นที่คู่ต่อสู้ด้านบน ให้กว้างเต็มพื้นที่", explicitly "ทั้งคอมและ
 * มือถือ"). On plain portrait mobile .ug-opponents is still a simple
 * flex row, so a width:100% child just takes the whole row; the
 * desktop/landscape grid block below only needs to add its own
 * grid-specific placement, not repeat this layout. */
.ug-opp-layout-1 .ug-opponent--top {
	width: 100%;
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: center;
	gap: 16px;
	min-width: 0;
}
.ug-opp-layout-1 .ug-opponent--top .ug-nickname { max-width: none; }
.ug-opp-layout-1 .ug-opponent--top .ug-hand-fan { margin: 0; }
/* Avatar+nickname travel together as one flex item (see game.js) so
 * wrapping the top opponent row onto 2 lines on narrow portrait phones
 * (below) never separates the avatar from the name. */
.ug-opponent-id { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ug-opponent-id .ug-avatar { margin: 0; }
/* Bot "thinking…" status line — the old numeric "เหลือ N ใบ" count that
 * used to share this same slot (.ug-hand-count) was removed in Phase 6:
 * the enlarged card-back fan below the name is now the only hand-size
 * indicator, per the request to drop the text entirely. */
.ug-opponent .ug-opponent-status {
	font-size: 11px; color: #cfe9d8; margin-top: 2px;
}
.ug-opponent .ug-uno-flag {
	position: absolute; top: -8px; right: -6px;
	background: var(--ug-red); color: #fff; font-size: 10px; font-weight: 800;
	padding: 3px 6px; border-radius: 20px; box-shadow: 0 2px 6px rgba(0,0,0,.3);
	animation: ug-pulse 1s infinite;
}
.ug-opponent .ug-catch-btn {
	margin-top: 6px; font-size: 11px; padding: 5px 8px; background: var(--ug-red); color: #fff; font-weight: 700;
}
/* "UNO!" called badge -- an orange speech bubble telling everyone a
 * player has called UNO (2026-09-26 4th follow-up). Used both on an
 * opponent's panel and, inline, in place of the self call button; the
 * small triangular tail always points up toward that player's cards. */
.ug-uno-called-badge {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	margin-top: 10px;
	background: #ff8f1f;
	color: #fff;
	font-weight: 800;
	font-size: 12px;
	letter-spacing: .5px;
	padding: 5px 14px;
	border-radius: 16px;
	box-shadow: 0 3px 10px rgba(0,0,0,.35);
	animation: ug-pulse 1.2s infinite;
}
.ug-uno-called-badge::after {
	content: '';
	position: absolute;
	top: -6px;
	left: 50%;
	transform: translateX(-50%);
	border-width: 0 6px 6px 6px;
	border-style: solid;
	border-color: transparent transparent #ff8f1f transparent;
}
.ug-opponent .ug-bot-flag { font-size: 10px; color: #cfe9d8; }

/* Fanned card-back stack — a quick "this player has cards" read at a
 * glance. 2026-09-27: shows the REAL hand count (no more 6-card cap) and
 * is sized to match the player's own hand cards below (.ug-card) at
 * every breakpoint ("ขยายไพ่ด้านบนให้ใหญ่ขึ้นเท่าด้านล่าง"); a big hand
 * gets a tighter overlap via .is-dense/.is-very-dense so it still fits
 * ("ถ้าไพ่เยอะก็บีบกันเข้าได้") instead of overflowing the box. */
.ug-hand-fan {
	display: flex;
	justify-content: center;
	align-items: flex-end;
	height: 70px;
	margin: 4px 0 2px;
}
.ug-mini-card {
	width: 64px;
	aspect-ratio: 259 / 400;
	border-radius: 8px;
	background: radial-gradient(circle at center, #2b2b2b 0%, #000 100%);
	box-shadow: 0 1px 5px rgba(0,0,0,.45);
	position: relative;
	overflow: hidden;
	margin-left: -45px;
	flex: 0 0 auto;
	transform: none;
	z-index: 1;
}
.ug-mini-card:first-child { margin-left: 0; }
.ug-mini-card .ug-mini-card-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ug-mini-card .ug-mini-card-mark {
	position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
	color: var(--ug-red); font-size: 10px; font-weight: 900; font-style: italic;
}
/* 2026-09-28: overlap now scales with how many cards are shown instead of
 * a flat value — a few cards spread out more (~70%, the base margin-left
 * above), climbing to ~80%/~90%/~95% as the hand grows ("ถ้าไพ่เหลือน้อย
 * ก็คลี่ไพ่ทับกันสัก 80 หรือ 70 ... ไว้ทับ 90% เมื่อไพ่มีจำนวนมาก ตั้งแต่
 * 6-7 ใบขึ้นไป"); thresholds set in game.js's handFanEl(). */
.ug-hand-fan.is-medium .ug-mini-card { margin-left: -51px; }
.ug-hand-fan.is-dense .ug-mini-card { margin-left: -58px; }
.ug-hand-fan.is-very-dense .ug-mini-card { margin-left: -61px; }
.ug-hand-fan .ug-mini-card:nth-child(1) { transform: rotate(-12deg) translateY(3px); z-index: 1; }
.ug-hand-fan .ug-mini-card:nth-child(2) { transform: rotate(-7deg) translateY(1px); z-index: 2; }
.ug-hand-fan .ug-mini-card:nth-child(3) { transform: rotate(-2deg) translateY(-1px); z-index: 3; }
.ug-hand-fan .ug-mini-card:nth-child(4) { transform: rotate(3deg) translateY(-1px); z-index: 4; }
.ug-hand-fan .ug-mini-card:nth-child(5) { transform: rotate(8deg) translateY(1px); z-index: 5; }
.ug-hand-fan .ug-mini-card:nth-child(6) { transform: rotate(13deg) translateY(3px); z-index: 6; }
.ug-hand-fan .ug-mini-card:nth-child(n+7) { z-index: 7; }

/* Top opponent: cards stay upright and simply overlap left-to-right,
 * the same overlap technique used for the player's own hand below —
 * no fan rotation (2026-09-26 request: "ไพ่ด้านบน ... เหมือนการ์ด
 * ด้านล่าง"). */
#ug-app .ug-opponent--top .ug-hand-fan .ug-mini-card {
	transform: none;
}
/* 2026-09-28: the top opponent's row always spans the FULL row width
 * ("top top"/"top top top" in every .ug-opp-layout-N grid), so unlike the
 * cramped side columns it has plenty of spare width — the generic 70-95%
 * .ug-hand-fan overlap above was needlessly cramming it tight regardless
 * ("ด้านบน เหลือพื้นที่มาก แต่ทับกันเกินไป ใช้สูตรเดียวกับไพ่หลักด้านล่าง
 * ได้"). Re-uses the exact same lower overlap steps as the player's own
 * hand (.ug-hand) instead, capped at "dense" (is-very-dense maps to the
 * same value — no extra squeeze past 6+ cards, it just keeps spilling
 * outward like the hand does). Side (left/right) opponents keep the
 * original tighter 70-95% scheme further down since their columns are
 * genuinely narrow. */
.ug-opponent--top .ug-hand-fan .ug-mini-card { margin-left: -22px; }
.ug-opponent--top .ug-hand-fan.is-medium .ug-mini-card { margin-left: -29px; }
.ug-opponent--top .ug-hand-fan.is-dense .ug-mini-card,
.ug-opponent--top .ug-hand-fan.is-very-dense .ug-mini-card { margin-left: -35px; }

@keyframes ug-pulse {
	0%, 100% { transform: scale(1); }
	50% { transform: scale(1.12); }
}

.ug-center {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 22px;
	padding: 18px 0 22px;
	position: relative;
}
.ug-direction {
	position: absolute;
	top: -6px;
	font-size: 22px;
	color: rgba(255,255,255,.55);
}
.ug-direction.reverse { transform: scaleX(-1); }

/* Big center-screen "reverse" flash (2026-09-27 request) — fires once
 * when a Reverse card is actually played (see runTableAnimation() /
 * Anim.showReverseFlash() in game.js), then fades away and only then
 * does play resume in the new direction. The small ↻ icon above stays
 * as a quiet persistent "which way is play going" reference; this is
 * the one-time, hard-to-miss cue for the moment it actually flips. */
.ug-reverse-flash {
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%) scale(.6);
	font-size: 120px;
	line-height: 1;
	color: #fff;
	text-shadow: 0 4px 24px rgba(0,0,0,.55);
	opacity: 0;
	z-index: 60;
	pointer-events: none;
	transition: opacity .25s ease, transform .25s ease;
}
.ug-reverse-flash.is-visible {
	opacity: .92;
	transform: translate(-50%, -50%) scale(1);
}

.ug-pile { text-align: center; position: relative; }
/* "จั่วไพ่" draw hint — 2026-09-27: only rendered (in JS) while the
 * player actually needs to draw, so styled as an attention badge rather
 * than the old permanent caption underneath the pile. Moved ABOVE the
 * deck stack (margin-bottom instead of margin-top) so it pairs visually
 * with the current-color chip sitting above the discard pile right next
 * to it (2026-09-27 follow-up #2). ALWAYS present in the DOM now (game.js
 * never removes it) so the draw pile reserves the same vertical space as
 * the discard pile's color chip at all times — only opacity toggles via
 * "is-visible", so the draw and discard piles stay the same height
 * whether or not the hint text is actually showing (2026-09-27
 * follow-up #3: "กองจั่ว กับ ไพ่ที่กำลังเล่น สูงและใหญ่เท่ากัน"). */
/* Requested 2026-09-27: style this exactly like .ug-color-chip (its
 * paired badge above the discard pile) — same height/padding/font-
 * weight/radius/shadow at every breakpoint, only the background color
 * differs (solid orange here vs the chip's dark translucent panel).
 * Kept as its own rule (not a shared class) because behavior differs:
 * this one starts hidden (opacity:0) and pulses once visible, which
 * the color chip never does. */
.ug-draw-hint {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	height: 28px;
	background: var(--ug-accent, var(--ug-orange));
	color: #2b2b2b;
	font-size: 11px;
	font-weight: 700;
	padding: 0 10px;
	border-radius: 12px;
	box-shadow: 0 2px 8px rgba(0,0,0,.35);
	opacity: 0;
	transition: opacity .2s ease;
}
.ug-draw-hint.is-visible {
	opacity: 1;
	animation: ug-pulse 1.2s infinite;
}

.ug-current-color-ring {
	display: inline-block;
	padding: 6px;
	border-radius: 16px;
	border: 3px solid #fff;
}
.ug-current-color-ring.ug-c-red { border-color: var(--ug-red); }
.ug-current-color-ring.ug-c-yellow { border-color: var(--ug-yellow); }
.ug-current-color-ring.ug-c-green { border-color: var(--ug-green); }
.ug-current-color-ring.ug-c-blue { border-color: var(--ug-blue); }

/* Both piles: a small badge above (draw hint / current-color chip), the
 * card below. display:inline-grid with a single implicit column sizes
 * that column to its widest child (the card) — justify-items:stretch
 * then makes the width-less badge above it fill that exact same width,
 * and both piles share the same badge height (.ug-draw-hint /
 * .ug-color-chip) so the draw pile and the discard pile always come out
 * the same overall height, badge showing or not (2026-09-27 follow-up
 * #3: "กองจั่ว กับ ไพ่ที่กำลังเล่น สูงและใหญ่เท่ากัน"). */
#ug-draw-pile, #ug-discard-anchor {
	display: inline-grid;
	justify-items: stretch;
	gap: 6px;
}

/* Current-color chip — an unambiguous, always-readable "the color in
 * force right now is X" indicator paired with the discard pile. */
.ug-color-chip {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	height: 28px;
	gap: 5px;
	background: rgba(0,0,0,.62);
	color: #fff;
	padding: 0 10px;
	border-radius: 12px;
	font-size: 11px;
	font-weight: 700;
	white-space: nowrap;
	box-shadow: 0 2px 8px rgba(0,0,0,.35);
}
.ug-color-chip-dot {
	width: 16px; height: 16px; border-radius: 50%; flex: 0 0 auto;
	box-shadow: inset 0 0 0 2px rgba(255,255,255,.7);
}
.ug-color-chip.ug-c-red .ug-color-chip-dot { background: var(--ug-red); }
.ug-color-chip.ug-c-yellow .ug-color-chip-dot { background: var(--ug-yellow); }
.ug-color-chip.ug-c-green .ug-color-chip-dot { background: var(--ug-green); }
.ug-color-chip.ug-c-blue .ug-color-chip-dot { background: var(--ug-blue); }

/* Card */
.ug-card {
	width: 64px;
	aspect-ratio: 259 / 400; /* matches assets/img/cards/*.webp exactly — height derives from this, never hand-set */
	border-radius: 8px;
	background: #fff;
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 3px 8px rgba(0,0,0,.3);
	overflow: hidden;
	font-weight: 800;
	user-select: none;
	flex: 0 0 auto;
}
.ug-card .ug-card-img {
	width: 100%; height: 100%;
	object-fit: contain;
	display: block;
	pointer-events: none; /* clicks/drags stay on the .ug-card wrapper */
}

.ug-card--back {
	background: radial-gradient(circle at center, #2b2b2b 0%, #000 100%);
	display: flex; align-items: center; justify-content: center;
}
.ug-card--back .ug-card-back-mark {
	color: var(--ug-red);
	font-weight: 900;
	font-size: 15px;
	font-style: italic;
	transform: rotate(-14deg);
	text-shadow: 0 0 4px rgba(255,255,255,.4);
}
/* Admin-uploaded card-back image (UG_Background::card_back_image_url())
 * — same .ug-card box/aspect-ratio as a face, image just fills it
 * edge-to-edge (cover, not contain: a back design has no content that
 * must avoid cropping, unlike a face's rank/symbol). Falls back to the
 * CSS radial-gradient "UNO" mark above when no image is configured. */
.ug-card--back-image { background: #000; }
.ug-card--back-image .ug-card-img { object-fit: cover; }

.ug-card--playable { cursor: pointer; }
.ug-card--disabled { filter: brightness(.72) saturate(.7); cursor: not-allowed; }

.ug-deck-stack { position: relative; width: 64px; aspect-ratio: 259 / 400; cursor: pointer; }
.ug-deck-stack .ug-card { position: absolute; top: 0; left: 0; }
.ug-deck-stack .ug-card:nth-child(2) { top: -3px; left: 2px; }

/* ---------------------------------------------------------------
 * Own hand
 * ------------------------------------------------------------- */
.ug-hand-wrap {
	position: fixed;
	left: 0; right: 0; bottom: 0;
	max-width: 720px;
	margin: 0 auto;
	padding: 10px 6px 14px;
	z-index: 20;
}
/* Status bar (2026-09-27): 2-column bar above the hand — left cell is
 * the turn status ("ตาคุณเล่น!" / waiting text), right cell is the pass
 * action (label shortened to just "ผ่าน"). Both default to a light-gray
 * overlay; each cell turns orange independently ("is-active") only when
 * it's the thing to actually do right now — see game.js. */
.ug-status-bar {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 8px;
	margin-bottom: 8px;
}
.ug-status-cell {
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(255,255,255,.14);
	border-radius: 10px;
	color: #fff;
	font-weight: 700;
	font-size: 14px;
	min-height: 20px;
	padding: 8px 10px;
	transition: background .2s ease, color .2s ease;
}
.ug-status-cell--turn.is-active { background: var(--ug-accent, var(--ug-orange)); color: #2b2b2b; }
.ug-status-cell--pass { min-width: 88px; }
.ug-status-cell--pass .ug-pass-btn {
	background: transparent;
	border: none;
	color: inherit;
	font-weight: 800;
	font-size: 14px;
	width: 100%;
	height: 100%;
	padding: 4px 6px;
	cursor: not-allowed;
	opacity: .6;
}
.ug-status-cell--pass.is-active { background: var(--ug-accent, var(--ug-orange)); color: #2b2b2b; }
.ug-status-cell--pass.is-active .ug-pass-btn { cursor: pointer; opacity: 1; }

.ug-hand {
	display: flex;
	justify-content: center;
	flex-wrap: nowrap;
	/* 2026-09-28 (was overflow-x:auto): a scrollbar under a big hand read
	 * as "cut off" and ugly ("ไม่เอาแบบมีสกรอ มันขาด และไม่สวยงาม"). No
	 * overflow rule at all now (default visible) so a long hand just
	 * overlaps its cards tighter (.is-dense/.is-very-dense below, same
	 * technique already used for the opponents' fans) and is free to
	 * spill past .ug-hand-wrap's own max-width, same as the opponents'
	 * top-row fan already does by design — never clipped, never scrolled.
	 * padding-top must clear the hover/select lift (translateY(-12px)
	 * below) plus the card's own box-shadow, or the lifted card's top
	 * gets clipped. */
	padding: 22px 10px 4px;
	gap: 0;
}
.ug-hand .ug-card { margin-left: -22px; transition: transform .12s ease; }
.ug-hand .ug-card:first-child { margin-left: 0; }
.ug-hand.is-medium .ug-card { margin-left: -29px; }
.ug-hand.is-dense .ug-card { margin-left: -35px; }
.ug-hand .ug-card--playable:hover,
.ug-hand .ug-card--playable:active { transform: translateY(-12px); z-index: 5; }

/* Circular "call UNO!" button — Phase 6: now sits right beside the draw
 * pile itself (a normal flex child of .ug-center, immediately after the
 * deck pile), rather than floating full-width between the pile row and
 * the hand like before.
 * #ug-app-prefixed so this beats the generic "#ug-app button" reset
 * above (an id selector always outweighs a bare class one) — without
 * this, border-radius: 50% below was silently losing to that rule's
 * border-radius: 10px and the button rendered as a rounded square. */
#ug-app .ug-uno-btn {
	width: 68px; height: 68px; border-radius: 50%;
	padding: 0; display: flex; align-items: center; justify-content: center;
	text-align: center; line-height: 1.1;
	font-weight: 800; font-size: 13px; color: #fff;
	background: var(--ug-red); border: 3px solid rgba(255,255,255,.85);
	box-shadow: 0 4px 14px rgba(0,0,0,.4);
	animation: ug-pulse 1.2s infinite;
	flex: 0 0 auto;
}
/* Pausing the pulse while pressed is what makes the press-down feedback
 * actually visible -- otherwise the next animation frame just
 * overwrites a plain :active transform immediately. */
#ug-app .ug-uno-btn:active {
	animation-play-state: paused;
	transform: scale(.88);
}
#ug-app .ug-uno-btn--inline { width: 56px; height: 56px; font-size: 11px; align-self: center; }

/* ---------------------------------------------------------------
 * Color picker modal
 * ------------------------------------------------------------- */
.ug-modal-overlay {
	position: fixed; inset: 0; background: rgba(0,0,0,.55);
	display: flex; align-items: center; justify-content: center;
	z-index: 50; padding: 20px;
}
.ug-modal {
	background: #fff; border-radius: var(--ug-radius); padding: 20px;
	max-width: 340px; width: 100%; text-align: center;
}
.ug-modal h3 { margin-top: 0; }
.ug-color-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 14px; }
.ug-color-swatch {
	height: 72px; border-radius: 12px; color: #fff; font-weight: 800; font-size: 15px;
	display: flex; align-items: center; justify-content: center;
	box-shadow: 0 3px 8px rgba(0,0,0,.25);
}
.ug-color-swatch.ug-c-red { background: var(--ug-red); }
.ug-color-swatch.ug-c-yellow { background: var(--ug-yellow); color: #2b2b2b; }
.ug-color-swatch.ug-c-green { background: var(--ug-green); }
.ug-color-swatch.ug-c-blue { background: var(--ug-blue); }

/* Player felt/accent theme customize panel (2026-09-28 request), reuses
 * .ug-modal-overlay/.ug-modal above — ported from phom-sib-game's own
 * .psg-preset-grid/.psg-preset-swatch/.psg-color-row. */
.ug-customize-modal h3 { color: #2b2b2b; }
.ug-preset-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin: 14px 0; }
.ug-preset-swatch { height: 44px; border-radius: 8px; border: 2px solid transparent; cursor: pointer; }
.ug-preset-swatch.ug-active { border-color: #2b2b2b; }
.ug-color-row { display: flex; align-items: center; justify-content: space-between; margin: 10px 0; color: #2b2b2b; font-size: 14px; }
.ug-color-row input[type="color"] { width: 46px; height: 34px; border: none; background: none; cursor: pointer; }
.ug-customize-actions { display: flex; gap: 10px; margin-top: 10px; }
.ug-customize-actions .ug-customize-close { flex: 1; width: auto; margin-top: 0; }
.ug-customize-close {
	width: 100%; margin-top: 10px; padding: 10px 18px;
	background: #eef1f4; color: var(--ug-ink); border-radius: 10px; font-weight: 700;
}
/* 2026-09-30: panel buttons (ค่าเริ่มต้น / ปิด) use phom-sib-game's secondary
 * button look — white, thin warm-grey border, 10px corners. Doubled class +
 * !important so the WordPress theme's own site-wide button styling (dark
 * 2px border, square corners) can't override it. */
.ug-modal .ug-customize-close.ug-customize-close {
	background: #fff !important; border: 1.5px solid #d9cdb6 !important; border-radius: 10px !important;
	color: #2c2416 !important; box-shadow: none !important; padding: 12px 16px !important;
	font-size: 15px; font-weight: 700; cursor: pointer;
}
.ug-modal .ug-customize-close.ug-customize-close:hover { border-color: var(--ug-accent, #ff8f1f) !important; }
/* 🎨 ปรับแต่งสี and กลับหน้าหลัก: both fully rounded (pill), regardless of
 * theme button styles (the toggle is a <button> and was picking up square
 * corners from the site theme). */
.ug-home-btn-row .ug-home-link.ug-home-link,
.ug-home-btn-row .ug-customize-toggle.ug-customize-toggle {
	border-radius: 999px !important; border: 1.5px solid #e7e7e7 !important; background: #fff !important;
}

/* ---------------------------------------------------------------
 * Card-movement animation (draw / play flights) + forced-draw toast
 * — see the Anim module in game.js. Cloned .ug-flying-card elements
 * are appended straight to document.body (not #ug-app) since they can
 * cross screens/overlays; that's exactly the case the :root color-var
 * scoping fix above protects.
 * ------------------------------------------------------------- */
.ug-flying-card {
	position: fixed;
	top: 0; left: 0;
	z-index: 999;
	pointer-events: none;
	margin: 0;
	will-change: transform;
}
/* A flying face-up card doesn't need .ug-card's opaque white backing
 * (that's only there so a static card's box never shows as blank
 * before its image loads) -- transparent here removes the white
 * strips/frame that showed behind/around a moving card (2026-09-26
 * follow-up, items 2 & 3). Back-facing clones keep their own dark
 * background. */
.ug-flying-card.ug-card:not(.ug-card--back):not(.ug-card--back-image) {
	background: transparent;
	box-shadow: none;
}
.ug-draw-toast {
	position: fixed;
	top: 18%;
	left: 50%;
	transform: translate(-50%, -10px);
	background: rgba(0,0,0,.72);
	color: #fff;
	font-size: 14px;
	font-weight: 700;
	padding: 10px 18px;
	border-radius: 24px;
	box-shadow: 0 6px 18px rgba(0,0,0,.4);
	z-index: 998;
	pointer-events: none;
	opacity: 0;
	transition: opacity .18s ease, transform .18s ease;
}
.ug-draw-toast.is-visible { opacity: 1; transform: translate(-50%, 0); }

/* Flip-to-reveal draw animation (item 5, 2026-09-26): a 3D flip card
 * over the deck that shows the drawn card's face, then slides into the
 * hand -- see Anim.flipDrawnCardToHand() in game.js. The stage keeps
 * the exact width/height of the deck pile for its whole lifetime (only
 * ever translated/rotated, never scaled), per the request that the
 * card's size never changes during the animation. */
.ug-draw-flip-stage {
	perspective: 800px;
}
.ug-draw-flip-inner {
	position: relative;
	width: 100%;
	height: 100%;
	transform-style: preserve-3d;
}
.ug-draw-flip-face {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	backface-visibility: hidden;
	border-radius: 8px;
	overflow: hidden;
	box-shadow: 0 3px 8px rgba(0,0,0,.3);
}
/* Guaranteed fallback cue (2026-09-26 3rd follow-up, item 1's own
 * suggested fallback: "ถ้าทำให้เคลื่อนที่ไม่ได้ ก็ให้กองจั่วกระดกขึ้น"):
 * the live deck pile itself gives a quick tilt/pop the instant a card
 * is drawn, on top of (never instead of) the flip+slide above -- so
 * there's always a visible draw cue even if anything about the flip
 * stage's sizing is ever off again. */
.ug-deck-pop {
	animation: ug-deck-pop .32s ease;
}
@keyframes ug-deck-pop {
	0% { transform: scale(1) rotate(0deg); }
	45% { transform: scale(1.08) rotate(-8deg); }
	100% { transform: scale(1) rotate(0deg); }
}
.ug-draw-flip-front {
	transform: rotateY(180deg);
}

/* ---------------------------------------------------------------
 * Pass & play privacy cover
 * ------------------------------------------------------------- */
.ug-cover {
	position: fixed; inset: 0; z-index: 60;
	background: linear-gradient(160deg, var(--ug-bg-2), var(--ug-bg));
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	color: #fff; text-align: center; padding: 24px;
}
.ug-cover .ug-cover-name { font-size: 26px; font-weight: 800; margin: 10px 0; }
.ug-cover .ug-cover-hint { color: #cfe9d8; margin-bottom: 26px; }
.ug-cover .ug-cover-btn {
	padding: 16px 30px; font-size: 16px; font-weight: 700;
	background: var(--ug-yellow); color: #2b2b2b;
}

/* ---------------------------------------------------------------
 * Game over
 * ------------------------------------------------------------- */
.ug-gameover { text-align: center; padding-top: 40px; }
.ug-gameover .ug-gameover-title { font-size: 30px; font-weight: 900; margin-bottom: 26px; }
.ug-gameover .ug-final-scores { margin: 20px 0; }

/* ---------------------------------------------------------------
 * Small screens
 * ------------------------------------------------------------- */
@media (max-width: 380px) {
	.ug-card { width: 54px; }
	.ug-deck-stack { width: 54px; }
	.ug-hand .ug-card { margin-left: -19px; }
	.ug-hand.is-medium .ug-card { margin-left: -24px; }
	.ug-hand.is-dense .ug-card { margin-left: -30px; }
	.ug-logo { font-size: 44px; }
	.ug-hand-fan { height: 58px; }
	.ug-mini-card { width: 54px; margin-left: -38px; }
	.ug-hand-fan.is-medium .ug-mini-card { margin-left: -43px; }
	.ug-hand-fan.is-dense .ug-mini-card { margin-left: -49px; }
	.ug-hand-fan.is-very-dense .ug-mini-card { margin-left: -51px; }
	.ug-opponent--top .ug-hand-fan .ug-mini-card { margin-left: -19px; }
	.ug-opponent--top .ug-hand-fan.is-medium .ug-mini-card { margin-left: -24px; }
	.ug-opponent--top .ug-hand-fan.is-dense .ug-mini-card,
	.ug-opponent--top .ug-hand-fan.is-very-dense .ug-mini-card { margin-left: -30px; }
	#ug-app .ug-uno-btn--inline { width: 48px; height: 48px; font-size: 10px; }
}

/* On mobile (below the desktop breakpoint below), no left/right padding
 * on the two screen wrappers -- user-requested 2026-09-26, same change
 * as the sibling thai-checkers-game/atari-go-game plugins. #ug-app
 * itself carries no horizontal padding of its own; it lives on
 * .ug-screen (home/menu) and .ug-screen--table (in-game), so both are
 * zeroed here. Top/bottom padding on each is untouched. */
@media (max-width: 1023px) {
	.ug-screen { padding-left: 0; padding-right: 0; }
	.ug-screen--table { padding-left: 0; padding-right: 0; }

	/* Requested 2026-09-27: on phones the table should fill the whole
	 * screen edge-to-edge with zero margin/padding around it, so the
	 * site's own page background (.ug-bg-layer, or the theme behind
	 * #ug-app) is never visible during gameplay — previously #ug-app's
	 * 720px max-width + auto margins plus this screen's own
	 * min-height:100vh/border-radius/side padding left a visible strip
	 * of page background above/below/around the felt on narrow or
	 * short phone viewports. Fixed + inset:0 takes the table out of
	 * #ug-app's centered box entirely and pins it straight to the
	 * viewport, independent of #ug-app's max-width. Only .ug-screen
	 * --table is affected; the menu/lobby/game-over screens keep their
	 * normal in-flow centered layout untouched. */
	.ug-screen--table {
		position: fixed;
		inset: 0;
		width: 100%;
		height: 100vh;
		height: 100dvh;
		margin: 0;
		border-radius: 0;
		padding-top: 8px;
	}
}

/* Requested 2026-09-27: portrait phones have plenty of vertical room, so
 * enlarge only the center-pile cards (draw pile + the in-play/discard
 * card) — the hand cards (.ug-hand .ug-card) and opponent mini-cards are
 * deliberately untouched here, matching every earlier round's rule of
 * scoping a size change to exactly the piece that was asked for. Also
 * moves the inline "call UNO" button to sit below the draw pile instead
 * of beside both piles, and lets the 2-player top opponent's
 * name/avatar wrap onto a 2nd line above its card fan instead of
 * overflowing the row — landscape phones (excluded by the orientation
 * check) keep the original compact single-row layout since they don't
 * have the spare height for any of this. */
@media (orientation: portrait) and (max-width: 1023px) {
	#ug-draw-pile .ug-card,
	#ug-draw-pile .ug-deck-stack,
	#ug-discard-anchor .ug-card {
		width: 84px;
	}

	.ug-center {
		display: grid;
		grid-template-columns: auto auto;
		grid-template-areas: "draw discard" "uno discard";
		align-items: center;
		justify-content: center;
		column-gap: 22px;
		row-gap: 10px;
	}
	.ug-center #ug-draw-pile { grid-area: draw; }
	.ug-center #ug-discard-anchor { grid-area: discard; align-self: center; }
	.ug-center .ug-uno-btn--inline { grid-area: uno; justify-self: center; align-self: start; }

	.ug-opp-layout-1 .ug-opponent--top {
		flex-wrap: wrap;
		/* .ug-hand-fan is a fixed-height box shorter than its own mini
		 * cards (by design, so the cards visually "spill" past the fan's
		 * own box edge when this box sits alone on one flat row) — with
		 * 2 rows now stacked, that spill would climb into the name row
		 * right above it, so this row-gap is sized to clear it rather
		 * than the small 8px used elsewhere. */
		row-gap: 36px;
	}
}

/* ---------- Desktop (>=1024px): wider table + larger cards/text ----------
 * Requested 2026-09-25: on screens wide enough to be "a computer" (not a
 * tablet/phone), let the table grow from the mobile 720px cap to 1000px
 * and scale up the card art and key text to fill that space. Everything
 * below the breakpoint (all phones, and portrait tablets up to 1023px)
 * is completely untouched. */
@media (min-width: 1024px) {
	#ug-app { max-width: 1000px; }
	.ug-hand-wrap { max-width: 1000px; }
	.ug-logo { font-size: 72px; }
	.ug-logo img { width: 260px; }
	.ug-subtitle { font-size: 16px; }
	.ug-mode-btn { padding: 20px 22px; }
	.ug-mode-btn .ug-mode-icon { width: 56px; height: 56px; }
	.ug-mode-btn .ug-mode-icon svg { width: 28px; height: 28px; }
	.ug-mode-btn .ug-mode-title { font-size: 19px; }
	.ug-mode-btn .ug-mode-hint { font-size: 14px; }
	.ug-room-code-box .ug-room-code { font-size: 52px; letter-spacing: 10px; }
	.ug-primary-btn, .ug-secondary-btn { font-size: 18px; padding: 17px; }
	.ug-opponent { min-width: 92px; padding: 10px 14px; }
	.ug-opponent .ug-avatar { width: 44px; height: 44px; font-size: 17px; }
	.ug-opponent .ug-nickname { font-size: 14px; max-width: 92px; }
	.ug-opponent .ug-opponent-status { font-size: 13px; }
	.ug-card { width: 92px; }
	.ug-deck-stack { width: 92px; }
	.ug-hand { padding-top: 26px; }
	.ug-hand .ug-card { margin-left: -32px; }
	.ug-hand.is-medium .ug-card { margin-left: -41px; }
	.ug-hand.is-dense .ug-card { margin-left: -51px; }
	.ug-hand .ug-card--playable:hover,
	.ug-hand .ug-card--playable:active { transform: translateY(-14px); }
	.ug-status-cell { font-size: 16px; padding: 12px 16px; }
	.ug-status-cell--pass .ug-pass-btn { font-size: 16px; }
	.ug-draw-hint { height: 34px; font-size: 13px; padding: 0 12px; }
	#ug-app .ug-uno-btn { width: 82px; height: 82px; font-size: 15px; }
	.ug-color-swatch { height: 90px; font-size: 17px; }
	.ug-color-chip { height: 34px; font-size: 13px; padding: 0 12px; }
	.ug-color-chip-dot { width: 18px; height: 18px; }
	.ug-hand-fan { height: 100px; }
	.ug-mini-card { width: 92px; margin-left: -64px; }
	.ug-hand-fan.is-medium .ug-mini-card { margin-left: -74px; }
	.ug-hand-fan.is-dense .ug-mini-card { margin-left: -83px; }
	.ug-hand-fan.is-very-dense .ug-mini-card { margin-left: -87px; }
	.ug-opponent--top .ug-hand-fan .ug-mini-card { margin-left: -32px; }
	.ug-opponent--top .ug-hand-fan.is-medium .ug-mini-card { margin-left: -41px; }
	.ug-opponent--top .ug-hand-fan.is-dense .ug-mini-card,
	.ug-opponent--top .ug-hand-fan.is-very-dense .ug-mini-card { margin-left: -51px; }
	.ug-gameover .ug-gameover-title { font-size: 36px; }
	#ug-app .ug-uno-btn--inline { width: 64px; height: 64px; font-size: 13px; }
	/* Side (left/right) opponents' card-back stack, sized to match this
	 * desktop tier's card width (92px) instead of the smaller mid-tier
	 * default below — 2026-09-28: "ไพ่ด้านข้างซ้าย-ขวา ขยายความใหญ่ขึ้น
	 * ให้ใกล้เคียงกับไพ่บนและล่าง". Extra `.ug-screen--table` qualifier
	 * only to out-specificity the shared opp-layout block's own side-card
	 * rule further down the file (same properties, mid-tier values) —
	 * without it, that later rule would win the tie and silently
	 * override these desktop numbers. */
	#ug-app .ug-screen--table .ug-opponent--left .ug-mini-card,
	#ug-app .ug-screen--table .ug-opponent--right .ug-mini-card { margin-top: -99px; }
	#ug-app .ug-screen--table .ug-opponent--left .ug-hand-fan.is-medium .ug-mini-card,
	#ug-app .ug-screen--table .ug-opponent--right .ug-hand-fan.is-medium .ug-mini-card { margin-top: -114px; }
	#ug-app .ug-screen--table .ug-opponent--left .ug-hand-fan.is-dense .ug-mini-card,
	#ug-app .ug-screen--table .ug-opponent--right .ug-hand-fan.is-dense .ug-mini-card { margin-top: -128px; }
	#ug-app .ug-screen--table .ug-opponent--left .ug-hand-fan.is-very-dense .ug-mini-card,
	#ug-app .ug-screen--table .ug-opponent--right .ug-hand-fan.is-very-dense .ug-mini-card { margin-top: -135px; }
}

/* ---------- Opponent-position grid layout (Phase 6, item 3) ----------
 * Player-count-aware seat layout: 1 opponent expands across the top
 * edge; 2 opponents keep one at top and move the other to a side; 3
 * opponents (a 4-player game) spread left/top/right, leaving the bottom
 * edge to the player's own hand (which stays a fixed-position bar below
 * and isn't part of this grid). Fires on real desktop AND on a phone
 * turned landscape once it's wide enough to fit side columns (item 4:
 * "ในมือถือให้เล่นแนวนอน ก็จะจัดวางได้ลงตัว") — portrait phones under
 * 1024px are completely untouched and keep the simple stacked row from
 * the base styles above. */
@media (min-width: 1024px), (orientation: landscape) and (min-width: 560px) {
	.ug-screen--table {
		display: grid;
		grid-template-rows: auto 1fr;
		align-items: stretch;
		gap: 8px 14px;
		padding-top: 44px; /* clear the absolutely-positioned back button below */
	}
	.ug-screen--table.ug-opp-layout-1 {
		grid-template-columns: 1fr;
		grid-template-areas: "top" "center";
	}
	.ug-screen--table.ug-opp-layout-2 {
		grid-template-columns: 1fr minmax(150px, 220px);
		grid-template-areas: "top top" "center right";
	}
	.ug-screen--table.ug-opp-layout-3 {
		grid-template-columns: minmax(150px, 220px) 1fr minmax(150px, 220px);
		grid-template-areas: "top top top" "left center right";
	}
	/* The fixed-position hand bar (status bar + cards) spans the whole
	 * viewport by default, which — once side opponents exist — visually
	 * overlaps their left/right columns. Narrow it so it stays inside the
	 * "center" column's own area, safely clear of the side players
	 * (2026-09-27 request: "ไม่ยาวล้นไปถึงผู้เล่นซ้ายขวา"). 2026-09-28: the
	 * side cards were briefly shrunk down to free extra width here, but
	 * the user then asked them back up to near full card size ("ขยายความ
	 * ใหญ่ขึ้น ให้ใกล้เคียงกับไพ่บนและล่าง") — columns back to their
	 * original width, and the hand's own scrollbar-avoidance now comes
	 * from its own tighter card overlap (.ug-hand.is-dense etc.) instead
	 * of stolen side-column space. These caps assume the side columns at
	 * their WIDEST (220px each, the minmax ceiling), so on a narrower
	 * viewport where the side columns shrink toward their 150px floor the
	 * bar ends up a bit narrower than it strictly needs to be — safe,
	 * since it only ever stays clear of the sides rather than risking an
	 * overlap. */
	.ug-screen--table.ug-opp-layout-2 .ug-hand-wrap { max-width: 640px; }
	.ug-screen--table.ug-opp-layout-3 .ug-hand-wrap { max-width: 520px; }
	/* The back button becomes a corner overlay instead of a grid item —
	 * left in normal flow it would auto-place into the first grid cell
	 * and sit on top of whatever opponent box occupies "top"/"left".
	 * Scoped to .ug-screen--table specifically (bug fixed 2026-09-27):
	 * a bare `.ug-back-btn` selector here was forcing position:absolute
	 * on the SETUP screens' back button too at this same breakpoint,
	 * with no positioned ancestor to anchor to — it escaped to the
	 * page's top-left corner, outside the centered content column,
	 * instead of sitting below the "start game" button as styled
	 * elsewhere in this file. */
	.ug-screen--table .ug-back-btn { position: absolute; top: 8px; left: 8px; z-index: 5; }

	.ug-opponents { display: contents; }
	.ug-opponent--top { grid-area: top; }
	.ug-opponent--left { grid-area: left; }
	.ug-opponent--right { grid-area: right; }
	.ug-opponent--left, .ug-opponent--right {
		display: flex; flex-direction: column; align-items: center; justify-content: center;
		min-height: 100%;
	}
	/* Side opponents: cards are turned on their side ("horizontal" card
	 * orientation) and stacked straight up the edge -- no per-card tilt.
	 * 2026-09-28: sized to match the top/bottom cards at this tier (no
	 * width override — inherits the same responsive .ug-mini-card width
	 * as everywhere else, per "ไพ่ด้านข้างซ้าย-ขวา ขยายความใหญ่ขึ้น ให้
	 * ใกล้เคียงกับไพ่บนและล่าง") with a graduated vertical overlap instead:
	 * spread out (~70%) with just a couple of cards, tightening to ~90%
	 * from 6-7 cards up ("เหลือน้อยก็คลี่ออก ... ไว้ทับ 90% เมื่อไพ่มี
	 * จำนวนมาก") — same .is-medium/.is-dense/.is-very-dense thresholds as
	 * the other fans, just applied to margin-top instead of margin-left
	 * since these stack vertically. Desktop's own (larger-card) numbers
	 * are set separately, further up in the file's desktop-only block. */
	.ug-opponent--left .ug-hand-fan, .ug-opponent--right .ug-hand-fan {
		flex-direction: column; height: auto; align-items: center; margin-top: 6px;
	}
	#ug-app .ug-opponent--left .ug-mini-card, #ug-app .ug-opponent--right .ug-mini-card {
		margin-left: 0;
		margin-top: -69px; /* ~70% overlap of a 64px-wide card's ~99px height */
		transform: rotate(90deg);
	}
	#ug-app .ug-opponent--left .ug-hand-fan.is-medium .ug-mini-card,
	#ug-app .ug-opponent--right .ug-hand-fan.is-medium .ug-mini-card { margin-top: -79px; }
	#ug-app .ug-opponent--left .ug-hand-fan.is-dense .ug-mini-card,
	#ug-app .ug-opponent--right .ug-hand-fan.is-dense .ug-mini-card { margin-top: -89px; }
	#ug-app .ug-opponent--left .ug-hand-fan.is-very-dense .ug-mini-card,
	#ug-app .ug-opponent--right .ug-hand-fan.is-very-dense .ug-mini-card { margin-top: -94px; }
	.ug-opponent--left .ug-mini-card:first-child, .ug-opponent--right .ug-mini-card:first-child { margin-top: 0; }

	/* A single opponent's box already stretches full-width and uses a row
	 * layout at every breakpoint (see the generic .ug-opp-layout-1
	 * .ug-opponent--top rule near the top of this file); on desktop we
	 * just give it roomier padding/gap and cards matching the larger
	 * desktop hand-card size (92px, same as .ug-card at this breakpoint). */
	.ug-opp-layout-1 .ug-opponent--top { gap: 20px; padding: 16px 20px; }
	/* width only — the overlap margin comes from the .ug-opponent--top
	 * .ug-hand-fan rule above now (same formula as the own hand), which
	 * already applies here too; a duplicate margin-left here would tie in
	 * specificity and silently win back the old tight value by source
	 * order, so it's deliberately left out. */
	.ug-opp-layout-1 .ug-opponent--top .ug-mini-card { width: 92px; }

	.ug-center-col { grid-area: center; display: flex; flex-direction: column; justify-content: center; }
}

/* A phone turned landscape is short, not just wide — the grid layout
 * above uses full-size (mobile-portrait-scale) cards/avatars, which is
 * too tall to fit next to the fixed-position hand bar on a ~360-420px
 * viewport height and was clipping/overlapping (bug found while
 * screenshot-testing Phase 6). This tier only ever matches alongside
 * the grid block above (same orientation:landscape condition, just a
 * height cap added), so it never touches real desktop, and shrinks
 * everything enough to fit a short landscape phone screen. */
@media (orientation: landscape) and (max-height: 520px) {
	.ug-screen--table { padding-top: 38px; }
	.ug-opponent { padding: 4px 8px; }
	.ug-opponent .ug-avatar { width: 24px; height: 24px; font-size: 11px; }
	.ug-opponent .ug-nickname { font-size: 10px; max-width: 64px; }
	.ug-hand-fan { height: 46px; margin: 2px 0 0; }
	.ug-mini-card { width: 42px; margin-left: -29px; }
	.ug-hand-fan.is-medium .ug-mini-card { margin-left: -34px; }
	.ug-hand-fan.is-dense .ug-mini-card { margin-left: -38px; }
	.ug-hand-fan.is-very-dense .ug-mini-card { margin-left: -40px; }
	.ug-opponent--top .ug-hand-fan .ug-mini-card { margin-left: -15px; }
	.ug-opponent--top .ug-hand-fan.is-medium .ug-mini-card { margin-left: -19px; }
	.ug-opponent--top .ug-hand-fan.is-dense .ug-mini-card,
	.ug-opponent--top .ug-hand-fan.is-very-dense .ug-mini-card { margin-left: -23px; }
	#ug-app .ug-opponent--left .ug-mini-card, #ug-app .ug-opponent--right .ug-mini-card { margin-top: -45px; }
	#ug-app .ug-opponent--left .ug-hand-fan.is-medium .ug-mini-card,
	#ug-app .ug-opponent--right .ug-hand-fan.is-medium .ug-mini-card { margin-top: -52px; }
	#ug-app .ug-opponent--left .ug-hand-fan.is-dense .ug-mini-card,
	#ug-app .ug-opponent--right .ug-hand-fan.is-dense .ug-mini-card { margin-top: -58px; }
	#ug-app .ug-opponent--left .ug-hand-fan.is-very-dense .ug-mini-card,
	#ug-app .ug-opponent--right .ug-hand-fan.is-very-dense .ug-mini-card { margin-top: -62px; }
	.ug-opp-layout-1 .ug-opponent--top { padding: 8px 14px; gap: 12px; }
	.ug-opp-layout-1 .ug-opponent--top .ug-mini-card { width: 42px; }
	.ug-center { padding: 4px 0; gap: 12px; }
	.ug-card { width: 42px; }
	.ug-deck-stack { width: 42px; }
	#ug-draw-pile, #ug-discard-anchor { gap: 3px; }
	.ug-draw-hint { height: 18px; font-size: 9px; padding: 0 8px; }
	.ug-color-chip { height: 18px; font-size: 9px; padding: 0 8px; }
	.ug-color-chip-dot { width: 12px; height: 12px; }
	#ug-app .ug-uno-btn--inline { width: 38px; height: 38px; font-size: 9px; border-width: 2px; }
	.ug-hand-wrap { padding: 4px 6px 6px; }
	.ug-status-cell { font-size: 11px; min-height: 14px; padding: 5px 8px; }
	.ug-status-bar { margin-bottom: 4px; }
	.ug-status-cell--pass .ug-pass-btn { font-size: 11px; }
	.ug-hand { padding: 12px 6px 2px; }
	.ug-hand .ug-card { margin-left: -15px; }
	.ug-hand.is-medium .ug-card { margin-left: -19px; }
	.ug-hand.is-dense .ug-card { margin-left: -23px; }
	.ug-hand .ug-card--playable:hover,
	.ug-hand .ug-card--playable:active { transform: translateY(-8px); }
}

/* ---------- Shared room chat (2026-09-28 request, ported from the
 * phom-sib-game/atari-go-game/thai-checkers-game/domino-game sibling
 * plugins) ---------- */
/* .ug-chat-root sits OUTSIDE #ug-app (a sibling — see game.js) so its
 * own <input> never gets torn down by #ug-app's frequent full rebuilds.
 * Being outside #ug-app also means it does NOT inherit that element's
 * CSS custom properties or its own font-family rule above, so
 * everything here uses fixed colors/fonts instead — always legible
 * regardless of the admin's theme. */
.ug-chat-root, .ug-chat-root * {
	font-family: 'db', 'SF Thonburi', 'Sarabun', 'Noto Sans Thai', sans-serif;
	box-sizing: border-box;
}
.ug-chat-root { position: fixed; right: 16px; bottom: 16px; z-index: 55; display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }
.ug-chat-fab {
	/* Gradient speech-bubble fab with 3 white dots inside, kept still, with an orange glow burst every 5s (see
	 * glow burst via the chat-glow animation
	 * below. */
	position: relative; width: 56px; height: 52px; border: none; cursor: pointer;
	background: transparent; padding: 0; display: flex; align-items: flex-start; justify-content: center;
	isolation: isolate; overflow: visible;
}
.ug-chat-fab-icon { position: relative; z-index: 1; display: block; width: 52px; height: 47px; }
.ug-chat-fab-icon svg { width: 100%; height: 100%; display: block; }
/* Orange glow burst instead of the old up/down bob (no layout/transform
 * jitter on the button itself): every 5s a soft orange light spreads out
 * from behind the bubble and fades, then stays still until the next
 * burst. Only opacity/transform are animated, so it stays on the
 * compositor and never stutters. */
.ug-chat-fab::before,
.ug-chat-fab::after {
	content: ""; position: absolute; left: 50%; top: 45%; width: 56px; height: 56px;
	margin: -28px 0 0 -28px; border-radius: 50%; pointer-events: none; z-index: 0;
	background: radial-gradient(circle, rgba(255,150,30,.85) 0%, rgba(255,122,0,.45) 40%, rgba(255,122,0,0) 70%);
	opacity: 0; transform: scale(.7); will-change: transform, opacity;
	animation: ug-chat-glow 5s ease-out infinite;
}
.ug-chat-fab::after { animation-delay: .35s; }
@keyframes ug-chat-glow {
	0%   { opacity: 0;   transform: scale(.7); }
	6%   { opacity: .9;  transform: scale(1.1); }
	26%  { opacity: 0;   transform: scale(2.8); }
	100% { opacity: 0;   transform: scale(2.8); }
}
@media (prefers-reduced-motion: reduce) {
	.ug-chat-fab::before, .ug-chat-fab::after { animation: none; opacity: 0; }
}
.ug-chat-badge {
	position: absolute; top: -2px; right: 0; min-width: 18px; height: 18px; padding: 0 4px;
	background: #ff5a36; color: #000; font-size: 11px; font-weight: 800; line-height: 18px;
	border-radius: 999px; text-align: center; box-shadow: 0 0 0 2px #fff;
}
.ug-chat-panel {
	width: 300px; max-width: calc(100vw - 32px); height: 380px; max-height: 60vh;
	background: #fff; color: #2c2416; border-radius: 14px; box-shadow: 0 8px 30px rgba(0,0,0,.35);
	display: flex; flex-direction: column; overflow: hidden;
}
.ug-chat-header {
	display: flex; align-items: center; justify-content: space-between; padding: 10px 14px;
	background: #2c2416; color: #fff; font-weight: 700; font-size: 14px;
}
/* Down-pointing triangle "▼" — reads as "collapse" rather than "close". */
.ug-chat-close { background: none; border: none; color: #fff; font-size: 12px; line-height: 1; cursor: pointer; padding: 0 4px; }
.ug-chat-messages { flex: 1; overflow-y: auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
.ug-chat-empty { color: #9a8f7a; font-size: 13px; text-align: center; margin-top: 20px; }
.ug-chat-msg { max-width: 82%; background: #f3ede0; border-radius: 10px; padding: 6px 10px; align-self: flex-start; }
.ug-chat-msg-mine { background: #fff1c4; align-self: flex-end; }
.ug-chat-msg-name { font-size: 11px; font-weight: 800; color: #7a6f5c; margin-bottom: 2px; }
.ug-chat-msg-text { font-size: 14px; word-break: break-word; white-space: pre-wrap; }
.ug-chat-form { display: flex; gap: 6px; padding: 8px; border-top: 1px solid #eee2cc; }
.ug-chat-input {
	/* font-size MUST be >= 16px — below that, iOS Safari (and some
	 * Android browsers) auto-zoom the whole page in the moment this
	 * field gets focus. */
	flex: 1; min-width: 0; border: 1px solid #e0d6bd; border-radius: 999px; padding: 8px 12px; font-size: 16px; color: #2c2416; background: #fff;
}
.ug-chat-input:focus { outline: none; border-color: #c7bb9e; }
.ug-chat-send {
	border: none; border-radius: 999px; padding: 8px 16px; background: #ffb600; color: #fff; font-weight: normal; font-size: 14px; cursor: pointer;
}
.ug-chat-send:hover { background: linear-gradient(135deg, #ffd400, #ff7a00); }
.ug-chat-send:active { transform: scale(.97); }
@media (max-width: 1023px) {
	.ug-chat-root { right: 12px; bottom: 12px; }
	.ug-chat-panel { width: calc(100vw - 24px); height: 50vh; }
}

/* Home screen (2026-09-30): the 3 mode cards and the 2 buttons below them
 * (🎨 ปรับแต่งสี / กลับหน้าหลัก) all lift 3px on hover and take a colored
 * border (all keep a visible border at rest). !important on the buttons only
 * because their border is itself forced with !important further up. */
.ug-home-btn-row .ug-home-link.ug-home-link,
.ug-home-btn-row .ug-customize-toggle.ug-customize-toggle {
	transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.ug-mode-btn:hover {
	transform: translateY(-3px);
}
.ug-mode-btn:active {
	transform: scale(.98);
}
.ug-home-btn-row .ug-home-link.ug-home-link:hover,
.ug-home-btn-row .ug-customize-toggle.ug-customize-toggle:hover {
	transform: translateY(-3px);
	border-color: var(--ug-accent, #ff8f1f) !important;
	box-shadow: 0 10px 22px rgba(20,30,60,.18);
}
