/* lobby.css - Lobby-specific styles and states */

/* Top-level lobby views: only one is shown at a time (the rest carry .hidden +
   the hidden attribute). The waiting room therefore never shows the games list. */
.lobby-view {
	display: block;
}

/* The home is a stack of named blocks — play, what is waiting, your tables, people — and each
   block is drawn as one so the eye groups what the headings already group for a reader. */
.home-block {
	margin-bottom: 1.75rem;
}

.home-block:last-child {
	margin-bottom: 0;
}

/* A hairline where the heading already says a new subject starts, so the eye groups what a
   reader hears grouped. Never the only cue: every block is named by its own heading. */
.home-block + .home-block {
	padding-top: 1.5rem;
	border-top: 1px solid var(--border);
}

.home-block__heading {
	margin: 0 0 0.75rem;
	font-size: 1.1rem;
	color: var(--text);
}

/* A block's row of ways in (create / join, or the three people screens). */
.home-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
}

.home-actions .home-action-btn {
	flex: 1 1 auto;
}

/* "Back to home" buttons on the create / join / waiting views. */
.lobby-back-btn {
	margin-bottom: 1rem;
}

/* Empty-state hint shown in the home view when there are no saved games. */
.your-games-empty {
	color: var(--text-muted);
	margin: 0 0 1.5rem;
}

.rules-details {
	margin-bottom: 1.5rem;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	background: var(--surface-2);
}

.rules-details > summary {
	padding: 0.75rem 1rem;
	cursor: pointer;
	font-weight: 600;
	color: var(--text);
}

.rules-details > summary:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring);
	border-radius: var(--radius-sm);
}

.rules-hint {
	margin: 0 1rem 1rem;
	color: var(--text-muted);
	font-size: 0.9rem;
}

.rules-fieldset {
	margin: 0 1rem 1rem;
	padding: 1rem;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
}

.rules-fieldset legend {
	padding: 0 0.5rem;
	font-weight: 600;
	color: var(--text);
}

/* A "choice" house rule: its options as a vertical radio group under the rule's name. */
.rule-choice {
	margin: 0 0 1rem;
	padding: 0.5rem 0.75rem;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
}
.rule-choice legend {
	padding: 0 0.35rem;
	font-weight: 600;
	color: var(--text);
}
.rule-choice__option {
	display: flex;
	align-items: flex-start;
	gap: 0.5rem;
	padding: 0.25rem 0;
	color: var(--text);
}
.rule-choice__option input[type="radio"] { margin-top: 0.2rem; }

.form-check {
	display: flex;
	align-items: flex-start;
	gap: 0.5rem;
	margin-bottom: 1rem;
}

.form-check input[type="checkbox"] {
	margin-top: 0.2rem;
	flex: 0 0 auto;
}

.form-check label {
	margin-bottom: 0;
	font-weight: 400;
}

.lobby-info {
	background: var(--surface-2);
	border: 1px solid var(--border);
	padding: 1.5rem;
	border-radius: var(--radius);
	margin-top: 1rem;
}

#lobby-details {
	background: var(--surface-2);
	border: 1px solid var(--border);
	padding: 1rem;
	border-radius: var(--radius-sm);
	margin-bottom: 1rem;
	list-style: none;
	padding-left: 1rem;
}

.detail-item {
	display: flex;
	justify-content: space-between;
	margin-bottom: 0.5rem;
}

.detail-item:last-child {
	margin-bottom: 0;
}

.invite-link {
	background: var(--accent-soft);
	border: 1px solid var(--border);
	padding: 1rem;
	border-radius: var(--radius-sm);
	margin: 1rem 0;
	word-break: break-all;
	font-family: monospace;
	color: var(--text);
}

.invite-code {
	background: var(--accent-soft);
	border: 1px solid var(--border);
	padding: 1rem;
	border-radius: var(--radius-sm);
	margin: 1rem 0;
	color: var(--text);
}

.invite-code h3 {
	margin: 0 0 0.5rem;
}

.invite-code__value {
	font-family: monospace;
	font-size: 1.5rem;
	font-weight: 700;
	letter-spacing: 0.15em;
	word-break: break-all;
	margin-bottom: 0.5rem;
}

.player-list ul {
	list-style: none;
	padding: 0;
	margin: 0;
}

#host-player-list,
#joined-player-list {
	list-style: none;
	padding: 0;
	margin: 0;
}

.player-list {
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	padding: 1rem;
	margin: 1rem 0;
}

/* The name-your-bot dialog: label, box and the random-name hat, stacked. */
.bot-name-form {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.bot-name-form input {
	padding: 0.45rem 0.6rem;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	font-size: 1rem;
}

.player-item {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 0.5rem 0;
	border-bottom: 1px solid var(--border);
}

.player-item:last-child {
	border-bottom: none;
}

.player-info {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
}

.player-info .token-icon {
	width: 1.3rem;
	height: 1.3rem;
}

.player-status {
	color: var(--text-muted);
	font-size: 0.85rem;
}

.player-token-name {
	color: var(--accent);
	font-size: 0.85rem;
}

.player-name {
	font-weight: 500;
	color: var(--text);
}

.player-token {
	background: var(--accent);
	color: var(--on-accent);
	padding: 0.25rem 0.5rem;
	border-radius: var(--radius-sm);
	font-size: 0.8rem;
}

.host-badge {
	background: var(--warning);
	color: #ffffff;
	padding: 0.25rem 0.5rem;
	border-radius: var(--radius-sm);
	font-size: 0.8rem;
}

/* Application states */
.error {
	background: var(--danger-soft);
	color: var(--danger);
	padding: 1rem;
	border-radius: var(--radius-sm);
	margin: 1rem 0;
}

/* The message region is permanent so a screen reader has it before the text arrives (see
   ui.ts showError); with nothing to say it takes no space and paints nothing. */
.error:empty {
	display: none;
}

.success {
	background: var(--good-soft);
	color: var(--good);
	padding: 1rem;
	border-radius: var(--radius-sm);
	margin: 1rem 0;
}

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

/* The blocks own the rhythm between them, so their last child does not add a second gap. */
.home-block > .saved-game-list,
.home-block > .your-games-empty,
.home-block > .form-hint:last-child {
	margin-bottom: 0;
}

/* Saved games ("your tables") list */
.saved-game-list {
	list-style: none;
	padding: 0;
	margin: 0 0 1.5rem;
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

.saved-game-item {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	padding: 0.85rem 1rem;
	background: var(--surface-2);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
}

.saved-game-info {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 0.6rem;
	min-width: 0;
}

.saved-game-icon .token-icon {
	width: 1.4rem;
	height: 1.4rem;
}

.saved-game-name {
	font-weight: 600;
	color: var(--text);
	text-transform: capitalize;
}

.saved-game-status {
	color: var(--accent);
	font-size: 0.85rem;
}

.saved-game-connected {
	color: var(--text-muted);
	font-size: 0.85rem;
}

.saved-game-created {
	color: var(--text-muted);
	font-size: 0.85rem;
}

.saved-game-actions {
	display: flex;
	gap: 0.5rem;
	flex-wrap: wrap;
}

/* === Board package upload === */

/* With an uploaded package active, the board picker is hidden and replaced by this label so
   there's no stale built-in board on show. */
.board-uploaded-name {
	margin: 0;
	font-weight: 600;
}

.board-upload-status {
	margin: 0.35rem 0 0;
	font-size: 0.9rem;
	font-style: italic;
	opacity: 0.85;
}

.board-upload-status:empty {
	display: none;
}

.board-upload-remove {
	margin-top: 0.5rem;
}

/* While an uploaded package drives the rules, its declared rules render in #package-rules and
   the built-in fieldsets are hidden. Scope the hide to the panel's DIRECT-child fieldsets (the
   built-in ones) so it doesn't also hide the package's own rendered fieldsets nested in
   #package-rules — those reuse the same .rules-fieldset class. */
.rules-details--package > .rules-fieldset { display: none; }
.package-rules fieldset { margin-top: 0.5rem; }


/* ---- Combobox (the game picker) ---------------------------------------- */
/* The list is always on screen rather than a popup: this is a catalogue to browse, not a menu to
   dismiss. It is a real element in the flow, so nothing here traps or overlays anything. */

.combo {
	position: relative;
}

.combo-input {
	width: 100%;
}

.combo-listbox {
	max-height: 14rem;
	margin: 0.4rem 0 0;
	padding: 0.25rem;
	border: 1px solid var(--border);
	border-radius: var(--radius);
	background: var(--surface-2);
	list-style: none;
	overflow-y: auto;
}

.combo-listbox:empty {
	display: none;
}

.combo-option {
	padding: 0.45rem 0.6rem;
	border-radius: var(--radius-sm);
	color: var(--text);
	cursor: pointer;
}

.combo-option:hover {
	background: var(--surface);
}

/* Focus lives on the option itself here (the list is walked, not pointed at through
   aria-activedescendant), so it needs a real, visible focus ring. */
.combo-option:focus,
.combo-option:focus-visible {
	outline: 3px solid var(--focus, #ffd24d);
	outline-offset: -3px;
	background: var(--surface);
}

/* The chosen game keeps a mark that is not colour alone. */
.combo-option[aria-selected="true"] {
	background: var(--accent-soft);
	font-weight: 700;
}

.combo-option[aria-selected="true"]::before {
	content: "✓";
	margin-inline-end: 0.5em;
	color: var(--accent);
}

.combo-results {
	margin: 0.35rem 0 0;
	color: var(--text-muted);
	font-size: 0.85rem;
}

/* ---- Who is online ------------------------------------------------------ */
/* The same roster shape as the table and the in-game players panel, so somebody who has met one
   has met all three. The surface scrolls once the room is big; its rows are the focus stops. */

.online-surface,
.friends-surface {
	max-height: 22rem;
	overflow-y: auto;
	border: 1px solid var(--border);
	border-radius: var(--radius);
	background: var(--surface-2);
}

.online-list {
	margin: 0;
	padding: 0.25rem;
	list-style: none;
}

.online-player,
.friend-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem;
	padding: 0.55rem 0.7rem;
	border-radius: var(--radius-sm);
	color: var(--text);
}

.online-player + .online-player,
.friend-row + .friend-row {
	border-top: 1px solid var(--border);
}

/* Each person is one focus stop, so the row itself has to show where the keyboard is. */
.online-player:focus,
.online-player:focus-visible,
.friend-row:focus,
.friend-row:focus-visible {
	outline: 3px solid var(--focus, #ffd24d);
	outline-offset: -3px;
	background: var(--surface);
}

.online-player__actions,
.friend-row__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

/* The row owns the tab order, so a button never shows focus of its own until the keyboard is
   actually inside the row's toolbar — where it must be unmistakable. */
.online-player__btn,
.friend-row__btn {
	padding: 0.3rem 0.6rem;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	background: var(--surface);
	color: var(--text);
	font-size: 0.9rem;
	cursor: pointer;
}

.online-player__btn:hover,
.friend-row__btn:hover {
	background: var(--surface-2);
}

.online-player__btn:focus,
.online-player__btn:focus-visible,
.friend-row__btn:focus,
.friend-row__btn:focus-visible {
	outline: 3px solid var(--focus, #ffd24d);
	outline-offset: 1px;
}

/* The line is what a screen reader reads; it takes the space the buttons do not need. */
.online-player__line,
.friend-row__line {
	flex: 1 1 auto;
	min-width: 0;
}

/* ---- Rows in a box: messages, and the tables waiting for you ------------- */
/* Both are lists whose ROWS are the focus stops (a roving list), so the box needs no tabindex of
   its own; it scrolls once the list is long. One shape for both, because a reader who has met the
   message log has met the invitations too. */

.lobby-roster-log {
	margin: 0.5rem 0;
	padding: 0.25rem;
	max-height: 12rem;
	overflow-y: auto;
	list-style: none;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	background: var(--surface);
}

.lobby-chat__line,
.lobby-invite {
	padding: 0.35rem 0.5rem;
	border-radius: var(--radius-sm);
	color: var(--text);
}

/* An invitation is a line plus its answers, side by side like every other roster row. */
.lobby-invite {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem;
}

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

.lobby-invite__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

.lobby-invite__btn {
	padding: 0.3rem 0.6rem;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	background: var(--surface-2);
	color: var(--text);
	font-size: 0.9rem;
	cursor: pointer;
}

.lobby-invite__btn:hover {
	background: var(--surface);
}

.lobby-chat__line + .lobby-chat__line,
.lobby-invite + .lobby-invite {
	border-top: 1px solid var(--border);
}

/* Every focus stop shows where the keyboard is — the rows, and the buttons inside a row's
   toolbar once the keyboard is actually in there. */
.lobby-chat__line:focus,
.lobby-chat__line:focus-visible,
.lobby-invite:focus,
.lobby-invite:focus-visible {
	outline: 3px solid var(--focus, #ffd24d);
	outline-offset: -3px;
	background: var(--surface-2);
}

.lobby-invite__btn:focus,
.lobby-invite__btn:focus-visible {
	outline: 3px solid var(--focus, #ffd24d);
	outline-offset: 1px;
}

/* A whole screen has room to show more of a conversation than a panel wedged into the home
   page ever did. */
#view-messages .lobby-roster-log {
	max-height: 18rem;
}

/* Writing is what this screen is for, so the box takes the width of one. */
.lobby-chat__input {
	width: 100%;
	padding: 0.5rem 0.6rem;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	background: var(--surface);
	color: var(--text);
	font: inherit;
	resize: vertical;
}

.lobby-chat__suggestions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem;
	margin: 0.35rem 0;
}

.lobby-chat__suggestion {
	padding: 0.3rem 0.6rem;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	background: var(--surface);
	color: var(--text);
	cursor: pointer;
}

.lobby-chat__suggestion:focus,
.lobby-chat__suggestion:focus-visible {
	outline: 3px solid var(--focus, #ffd24d);
	outline-offset: 1px;
}
