/* ═══════════════════════════════════════════════════════════════════════════
   main.css — Monopoly Client Styles
   Dark green felt theme; board uses CSS Grid for all 40 squares.
═══════════════════════════════════════════════════════════════════════════ */

/* ── reset & variables ────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --bg:           #0E1A40;
  --surface:      #16224F;
  --surface2:     #1D2C5E;
  --border:       #33447A;
  --text:         #E8ECFA;
  --text-muted:   #93A0C4;
  --accent:       #4F8FE0;
  --accent-hover: #6FA6EA;
  --danger:       #e53935;
  --warning:      #ffa726;
  --info:         #29b6f6;

  /* Property group colours */
  --brown:        #8B4513;
  --lightblue:    #87CEEB;
  --pink:         #FF69B4;
  --orange:       #FF8C00;
  --red:          #DC143C;
  --yellow:       #FFD700;
  --green:        #228B22;
  --darkblue:     #00008B;

  /* Board fills available space: min(width-after-sidebar, height-after-header, hard-max) */
  --board-size:   min(calc(100vw - 312px), calc(100dvh - 86px), 960px);
  --corner-size:  calc(var(--board-size) * 0.121);
  --side-size:    calc((var(--board-size) - 2 * var(--corner-size)) / 9);
}

html, body {
  height: 100%;
  font-family: 'Segoe UI', system-ui, sans-serif;
  font-size: 14px;
  background: var(--bg);
  color: var(--text);
  overflow-x: hidden;
}

/* ── screen management ────────────────────────────────────────────────────── */

.screen        { display: none; }
.screen.active { display: block; }

/* ── buttons ──────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: 6px;
  border: none;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  transition: background 0.15s, opacity 0.15s;
}
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary   { background: var(--accent);  color: #fff; }
.btn-primary:hover:not(:disabled)  { background: var(--accent-hover); }
.btn-danger    { background: var(--danger);  color: #fff; }
.btn-danger:hover:not(:disabled)   { background: #ef5350; }
.btn-outline   { background: transparent; color: var(--text); border: 1px solid var(--border); }
.btn-outline:hover:not(:disabled)  { background: var(--surface2); }
.btn-full      { width: 100%; }
.btn-sm        { padding: 5px 10px; font-size: 12px; }
.mt-2          { margin-top: 8px; }

/* ── form elements ────────────────────────────────────────────────────────── */

.form-group     { margin-bottom: 14px; }
.form-group label { display: block; margin-bottom: 4px; color: var(--text-muted); font-size: 12px; }
input[type="text"],
input[type="password"],
input[type="number"],
select {
  width: 100%;
  padding: 9px 12px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--surface2);
  color: var(--text);
  font-size: 14px;
}
input:focus, select:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.checkbox-group label { display: flex; align-items: center; gap: 8px; color: var(--text); }
.form-error { color: var(--danger); font-size: 12px; min-height: 18px; margin-bottom: 8px; }

/* ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ──
   AUTH SCREEN
── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── */

#auth-screen {
  min-height: 100vh;
  /* display is controlled by .screen / .screen.active — do NOT set it here
     because an ID selector beats the class selector and the screen would
     stay visible even after logout */
  align-items: center;
  justify-content: center;
  background: radial-gradient(ellipse at center, #16224F 0%, #06102A 100%);
}
#auth-screen.active {
  display: flex;
}

.auth-container {
  width: 360px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 36px 32px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.auth-title    { font-size: 36px; text-align: center; margin-bottom: 4px; }
.auth-subtitle { text-align: center; color: var(--text-muted); margin-bottom: 24px; }

.auth-divider {
  display: flex;
  align-items: center;
  text-align: center;
  color: var(--text-muted);
  font-size: 12px;
  margin: 20px 0 12px;
}
.auth-divider::before,
.auth-divider::after {
  content: '';
  flex: 1;
  border-bottom: 1px solid var(--border);
}
.auth-divider span { padding: 0 10px; }

.tab-bar { display: flex; border-bottom: 1px solid var(--border); margin-bottom: 20px; }
.tab-btn {
  flex: 1;
  padding: 10px;
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  border-bottom: 2px solid transparent;
  transition: color 0.15s, border-color 0.15s;
}
.tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }

.auth-form         { display: none; }
.auth-form.active  { display: block; }

/* ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ──
   LOBBY SCREEN
── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── */

#lobby-screen.active { display: flex; flex-direction: column; min-height: 100vh; }

.lobby-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 24px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.lobby-header .logo { font-size: 24px; }
.header-user { display: flex; align-items: center; gap: 12px; }

.lobby-body {
  display: flex;
  gap: 24px;
  padding: 24px;
  flex: 1;
  overflow: auto;
}

.lobby-games {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.lobby-create {
  width: 320px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 20px;
  align-self: flex-start;
}
.lobby-create h2 { margin-bottom: 16px; }

.section-header { display: flex; align-items: center; justify-content: space-between; }
.section-header h2 { font-size: 18px; }

.games-list { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }

.game-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.game-card-info h4 { font-size: 15px; margin-bottom: 2px; }
.game-card-info p  { font-size: 12px; color: var(--text-muted); }
.game-type-badge {
  display: inline-block;
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 10px;
  background: var(--surface2);
  color: var(--text-muted);
  text-transform: capitalize;
  margin-top: 3px;
}
.game-card-status {
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 20px;
  font-weight: 600;
  text-transform: uppercase;
}
.status-waiting { background: #1b5e20; color: #69f0ae; }
.status-playing { background: #1a237e; color: #82b1ff; }
.status-paused  { background: #4e342e; color: #ffab91; }

.empty-state { color: var(--text-muted); font-style: italic; padding: 12px 0; }

.saved-games-section h3 { font-size: 15px; color: var(--text-muted); margin-top: 16px; }

.collapsible-btn {
  background: none;
  border: 1px dashed var(--border);
  color: var(--text-muted);
  padding: 8px 12px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  width: 100%;
  text-align: left;
  margin-bottom: 10px;
}
.config-panel { padding: 10px 0; }
.plugin-config-step {
  min-width: 0;
  margin: 0 0 14px;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: 12px;
}
.plugin-config-step legend {
  padding: 0 6px;
  color: var(--text);
  font-size: 16px;
  font-weight: 700;
}
.plugin-config-step[hidden] { display: none; }
.plugin-config-step .form-group:last-child { margin-bottom: 0; }
.plugin-config-step .form-group label { color: var(--text); font-size: 16px; }
.plugin-config-navigation { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.plugin-config-navigation .btn { flex: 0 0 auto; }
.plugin-config-navigation [hidden], #create-game-submit[hidden] { display: none; }
.plugin-config-progress { color: var(--text-muted); text-align: center; font-size: 16px; }
.plugin-config-description {
  margin: 6px 0 0;
  color: var(--text-muted);
  font-size: 16px;
  line-height: 1.45;
}

/* ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ──
   WAITING ROOM SCREEN
── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── */

#waiting-screen.active { display: flex; flex-direction: column; min-height: 100vh; }

.waiting-body {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.waiting-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 36px 40px;
  min-width: 360px;
  text-align: center;
}
.waiting-card h3 { font-size: 20px; margin-bottom: 20px; }
.players-waiting-list { list-style: none; margin-bottom: 24px; }
.players-waiting-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 15px;
}
.players-waiting-list li:last-child { border-bottom: none; }
.remove-bot-btn { margin-left: auto; padding: 2px 8px; font-size: 13px; }
#add-bot-btn { margin-bottom: 16px; }
.player-token-badge {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  flex-shrink: 0;
}
.waiting-hint { color: var(--text-muted); margin-bottom: 16px; font-size: 13px; }
.waiting-card .form-error { color: #ffc5bb; font-size: 16px; line-height: 1.5; text-align: left; }

/* ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ──
   GAME SCREEN
── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── */

/* Die Höhe zweimal, mit Absicht: 100vh zählt auf dem Handy den Bereich hinter
   der einklappbaren Adressleiste mit. Die Spielfläche wird dadurch höher als
   das Sichtbare, die Seite fängt an zu scrollen, und oben wie unten wird
   etwas abgeschnitten — bei Garfeln die Zuganzeige, bei anderen Spielen der
   untere Brettrand. 100dvh misst, was wirklich zu sehen ist; die erste Zeile
   bleibt als Rückfall für Browser ohne dvh stehen. */
#game-screen.active {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.game-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.game-header-left  { display: flex; align-items: center; gap: 12px; }
.game-header-right { display: flex; gap: 8px; }

.turn-indicator {
  font-size: 12px;
  padding: 3px 10px;
  border-radius: 20px;
  background: var(--surface2);
  border: 1px solid var(--border);
}
.turn-indicator.my-turn { background: #1B3E78; color: #BFE0FF; border-color: var(--accent); }

.game-layout {
  display: flex;
  flex: 1;
  overflow: hidden;
}

/* ── board ────────────────────────────────────────────────────────────────── */

.board-wrapper {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  overflow: auto;
  background: var(--bg);
}

.board {
  display: grid;
  grid-template-columns: var(--corner-size) repeat(9, var(--side-size)) var(--corner-size);
  grid-template-rows:    var(--corner-size) repeat(9, var(--side-size)) var(--corner-size);
  width:  var(--board-size);
  height: var(--board-size);
  border: 3px solid #111;
  border-radius: 4px;
  background: #d4edda;
  flex-shrink: 0;
  position: relative;
}


.dice-display { display: flex; gap: 10px; }
.die {
  width: 44px;
  height: 44px;
  border-radius: 8px;
  background: #fff;
  border: 2px solid #333;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  font-weight: 700;
  color: #333;
  box-shadow: 2px 2px 4px rgba(0,0,0,0.2);
}


/* ── sidebar ──────────────────────────────────────────────────────────────── */

.game-sidebar {
  width: 280px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--border);
  overflow-y: auto;
  background: var(--surface);
}

.players-section,
.action-section,
.log-section,
.chat-section {
  border-bottom: 1px solid var(--border);
  padding: 12px 14px;
}

.players-section h3,
.action-section h3,
.log-section h3,
.chat-section h3 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); margin-bottom: 10px; }

/* Collapsible Spielverlauf/Chat/game-header (phone only — Nutzervorgabe: on
   a phone these sections eat space a game's own board/hand often needs
   more, and the player should be able to peek at them without a game
   forcing a whole different mobile view (see Kniffel-Quadro's
   kq-mobile-focus, which hides them outright instead of offering a manual
   toggle). Desktop is untouched: the .collapsed class has no effect outside
   this breakpoint, so these sections always stay expanded there regardless
   of state — the caret is hidden by default for exactly the same reason
   (it otherwise leaks into the desktop header with no function there). */
.collapse-caret {
  display: none;
}

@media (max-width: 700px) {
  .collapsible-header {
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    user-select: none;
  }
  .collapse-caret {
    display: inline-block;
    transition: transform 0.15s;
  }
  .collapsible-section.collapsed .collapse-caret {
    transform: rotate(-90deg);
  }
  .collapsible-section.collapsed > *:not(.collapsible-header) {
    display: none;
  }
  .collapsible-section.collapsed h3 {
    margin-bottom: 0;
  }

  /* .game-header-left has 3 children (title, turn badge, caret) instead of
     log/chat's 2 (label, caret) — space-between would center the turn
     badge away from the title instead of keeping them grouped. */
  .game-header-left.collapsible-header {
    justify-content: flex-start;
  }
  .game-header-left.collapsible-header .collapse-caret {
    margin-left: auto;
  }
}

/* Player panel cards */
.players-panel { display: flex; flex-direction: column; gap: 8px; }

.player-card {
  border-radius: 8px;
  border: 2px solid transparent;
  padding: 8px 10px;
  background: var(--surface2);
  transition: border-color 0.2s;
}
.player-card.active-turn { border-color: var(--accent); }
.player-card.dimmed      { opacity: 0.45; }

.player-card-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}
.player-color-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  flex-shrink: 0;
}
.player-card-name  { font-weight: 700; font-size: 13px; flex: 1; }
.player-card-money { font-weight: 700; color: var(--accent); font-size: 13px; }
.player-card-props { font-size: 11px; color: var(--text-muted); }

/* Small cards under a player's name — what they currently hold, readable at
   a glance (see getPlayerCardData's optional `chips`). */
.player-card-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  margin-top: 5px;
}
.player-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  padding: 2px 6px 2px 3px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 10px;
  line-height: 1.35;
}
.player-chip-band {
  width: 4px;
  align-self: stretch;
  min-height: 12px;
  border-radius: 2px;
  flex: 0 0 auto;
}
.player-chip-label {
  color: var(--text, #e6edf3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.player-chip-note {
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.player-jail-badge {
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 10px;
  background: var(--danger);
  color: #fff;
}

/* Action buttons area */
.action-buttons { display: flex; flex-direction: column; gap: 8px; }
.action-buttons .btn { text-align: left; justify-content: flex-start; }

.dice-display {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}

/* Die face: 3×3 grid of pip slots */
.die {
  width: 58px;
  height: 58px;
  background: #fffff8;
  border: 2px solid #bbb;
  border-radius: 10px;
  box-shadow: 3px 4px 8px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.8);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  padding: 7px;
  gap: 3px;
  user-select: none;
  flex-shrink: 0;
}

/* Each pip slot — pip shown when .pip class is present */
.pip-slot {
  display: flex;
  align-items: center;
  justify-content: center;
}
.pip-slot::after {
  content: '';
  display: none;
  width: 10px;
  height: 10px;
  background: #1a1a1a;
  border-radius: 50%;
}
.pip-slot.pip::after {
  display: block;
}

.doubles-badge {
  font-size: 0.7rem;
  font-weight: 700;
  color: #2e7d32;
  background: #e8f5e9;
  border: 1px solid #a5d6a7;
  padding: 2px 7px;
  border-radius: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Game log — card-style container, newest entry on top */
.game-log {
  height: 210px;
  overflow-y: auto;
  font-size: 12px;
  line-height: 1.4;
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  gap: 3px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px;
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.35);
}

.log-entry {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 8px;
  border-left: 3px solid transparent;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.02);
  transition: background 0.2s;
}
.log-entry:hover {
  background: rgba(255, 255, 255, 0.06);
}
.log-icon {
  flex-shrink: 0;
  width: 16px;
  text-align: center;
  font-size: 12px;
  line-height: 1.4;
}
.log-msg { flex: 1; min-width: 0; word-break: break-word; }

.log-entry.type-dice     { border-color: #5c8dd6; color: #aac4f0; }
.log-entry.type-move     { color: var(--text-muted); font-size: 11px; }
.log-entry.type-money    { border-color: #4caf50; color: #a5d6a7; }
.log-entry.type-property { border-color: #f9c74f; color: #fff59d; }
.log-entry.type-jail     { border-color: #e57373; color: #ef9a9a; }
.log-entry.type-card     { border-color: #ba68c8; color: #ce93d8; }
.log-entry.type-trade    { border-color: #4dd0e1; color: #80deea; }
.log-entry.type-auction  { border-color: #ffb300; color: #ffcc80; }
.log-entry.type-score    { border-color: #66bb6a; color: #c8e6c9; }
.log-entry.type-game     { border-color: #ffd700; color: #fff; font-weight: 700; background: rgba(255, 215, 0, 0.10); }
.log-entry.type-info     { color: var(--text-muted); font-size: 11px; background: transparent; }

/* Newest entry: brief highlight flash so it's obvious what just landed on
   top, fading back into the normal entry styling after ~1.2s. */
.log-entry-new {
  animation: logEntryNew 1.2s ease-out;
}
@keyframes logEntryNew {
  0%   { background: rgba(255, 193, 7, 0.35); }
  100% { background: rgba(255, 255, 255, 0.02); }
}

/* Turn separator — horizontal rule with player name centred */
.log-entry.type-turn {
  border-left: none;
  background: transparent;
  padding: 6px 6px 2px;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  font-style: italic;
  color: var(--text-muted);
}
.log-entry.type-turn:hover { background: transparent; }
.log-entry.type-turn::before,
.log-entry.type-turn::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}
.log-divider-text { white-space: nowrap; flex-shrink: 0; }

/* Chat */
.chat-messages {
  height: 120px;
  overflow-y: auto;
  font-size: 12px;
  margin-bottom: 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.chat-msg { }
.chat-msg-name { font-weight: 700; color: var(--accent); }
.chat-msg-text { color: var(--text); }

.chat-form { display: flex; gap: 6px; }
.chat-form input { flex: 1; }
.chat-form .btn  { flex-shrink: 0; }

/* ── modals ───────────────────────────────────────────────────────────────── */

.modal {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.modal-content {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  width: 420px;
  max-width: 95vw;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.modal-wide { width: 640px; }

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.modal-header h3 { font-size: 16px; }
.modal-close {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 18px;
  cursor: pointer;
  padding: 0 4px;
}
.modal-body   { padding: 20px; }

/* Leaderboard */
.leaderboard-body { margin-top: 12px; max-height: 420px; overflow-y: auto; }
.leaderboard-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.leaderboard-table th,
.leaderboard-table td {
  padding: 8px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.leaderboard-table th {
  color: var(--text-muted);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.leaderboard-table td:first-child,
.leaderboard-table td:nth-child(3),
.leaderboard-table td:nth-child(4),
.leaderboard-table td:nth-child(5) { text-align: center; }
.leaderboard-row-me { background: rgba(79, 143, 224, 0.12); font-weight: 700; }
.leaderboard-row-me td:first-child { color: var(--accent-hover); }
.modal-footer {
  display: flex;
  gap: 10px;
  padding: 16px 20px;
  border-top: 1px solid var(--border);
  justify-content: flex-end;
}

/* Game-over modal */
.game-over-message {
  text-align: center;
  font-size: 18px;
  font-weight: 700;
  margin-bottom: 4px;
}
.game-over-standings {
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.game-over-standing-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 14px;
}
.game-over-standing-winner {
  background: rgba(255, 215, 0, 0.12);
  border-color: #C9A227;
  font-weight: 700;
}
.game-over-standing-name { color: var(--text); }
.game-over-standing-score { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.game-over-standing-winner .game-over-standing-score { color: #ffd700; }

/* My Properties modal */
.my-props-list { display: flex; flex-direction: column; gap: 8px; max-height: 60vh; overflow-y: auto; }
.my-prop-row { display: flex; align-items: center; gap: 10px; padding: 8px; background: var(--surface2); border-radius: 6px; }
.my-prop-color { width: 12px; height: 36px; border-radius: 3px; flex-shrink: 0; }
.my-prop-info { flex: 1; min-width: 0; }
.my-prop-name { font-weight: 700; font-size: 13px; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.my-prop-status { font-size: 11px; color: var(--text-muted); }
.my-prop-btns { display: flex; gap: 6px; flex-shrink: 0; }

/* Property detail modal */
.prop-detail-card { background: var(--surface2); border-radius: 8px; padding: 16px; }
.prop-color-stripe { height: 24px; border-radius: 4px; margin-bottom: 12px; }
.prop-detail-row { display: flex; justify-content: space-between; font-size: 13px; padding: 4px 0; border-bottom: 1px solid var(--border); }
.prop-detail-row:last-child { border-bottom: none; }
.prop-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }

/* Trade modal */
.trade-columns { display: flex; gap: 0; align-items: flex-start; }
.trade-col { flex: 1; padding: 0 12px; }
.trade-col:first-child { padding-left: 0; }
.trade-col:last-child  { padding-right: 0; }
.trade-col-center { display: flex; align-items: center; font-size: 28px; color: var(--text-muted); padding: 0 4px; align-self: center; }
.trade-col h4 { font-size: 14px; margin-bottom: 10px; }
.trade-select { margin-bottom: 10px; }
.trade-props-list { display: flex; flex-direction: column; gap: 4px; max-height: 160px; overflow-y: auto; }
.trade-prop-item { display: flex; align-items: center; gap: 6px; font-size: 12px; padding: 4px; border-radius: 4px; cursor: pointer; }
.trade-prop-item:hover { background: var(--surface2); }
.trade-prop-item input[type=checkbox] { width: auto; }
.trade-prop-color { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.trade-input { margin-bottom: 10px; }

/* Game over */
.game-over-message { font-size: 20px; text-align: center; padding: 20px 0; color: var(--accent); font-weight: 700; }

/* ── Connect Four board ───────────────────────────────────────────────────── */
/* --cf-cell drives both the drop-buttons and the grid so they always stay
   aligned; the phone breakpoint below is the only place that shrinks it —
   everywhere else it's the original fixed 54px, unchanged. */

.connect-four-wrapper {
  --cf-cell: 54px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 16px;
  gap: 6px;
}

.cf-col-buttons {
  display: grid;
  gap: 4px;
  width: fit-content;
}

.cf-col-btn {
  width: var(--cf-cell);
  height: 32px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  cursor: pointer;
  font-size: 14px;
  transition: background 0.15s, color 0.15s;
}

.cf-col-btn:hover:not(:disabled) {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.cf-col-btn:disabled {
  opacity: 0.25;
  cursor: not-allowed;
}

.cf-grid {
  display: grid;
  gap: 5px;
  background: #1565c0;
  padding: 10px;
  border-radius: 10px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.5);
  width: fit-content;
}

.cf-cell {
  width: var(--cf-cell);
  height: var(--cf-cell);
  background: #0d1b2a;
  border-radius: 50%;
  transition: background 0.2s;
  box-shadow: inset 0 3px 6px rgba(0,0,0,0.6);
}

.cf-cell.filled {
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.4), 0 0 6px rgba(255,255,255,0.1);
}

/* Phone: 7 * 54px cells (428px) overflows a 375px viewport with no shrink
   mechanism at all — this was the reported bug. min() keeps it viewport-
   relative down to very narrow phones instead of a single fixed value. */
@media (max-width: 700px) {
  .connect-four-wrapper { padding: 8px; gap: 4px; }
  .connect-four-wrapper {
    /* 7 cells + 6 gaps(3px) + grid padding(6px*2) + wrapper padding(8px*2)
       + a small safety margin for scrollbar/browser chrome. */
    --cf-cell: min(54px, calc((100vw - 56px) / 7));
  }
  .cf-col-buttons, .cf-grid { gap: 3px; }
  .cf-grid { padding: 6px; }
}

/* ── Tic-Tac-Toe board ────────────────────────────────────────────────────── */

.tic-tac-toe-wrapper {
  --ttt-cell: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 16px;
}

/* Phone: 3 * 96px cells + padding/gaps + wrapper padding lands right at the
   edge of a 375px viewport (borderline, but with no margin for browser
   chrome) — shrink slightly for a comfortable fit. */
@media (max-width: 700px) {
  .tic-tac-toe-wrapper {
    padding: 10px;
    --ttt-cell: min(96px, calc((100vw - 20px - 20px - 12px) / 3));
  }
  .ttt-cell { font-size: min(56px, calc(var(--ttt-cell) * 0.58)); }
}

.ttt-grid {
  display: grid;
  gap: 6px;
  background: #1565c0;
  padding: 10px;
  border-radius: 10px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.5);
  width: fit-content;
}

.ttt-cell {
  width: var(--ttt-cell);
  height: var(--ttt-cell);
  background: #0d1b2a;
  border: none;
  border-radius: 8px;
  color: #fff;
  font-size: 56px;
  line-height: 1;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s, transform 0.08s;
  box-shadow: inset 0 3px 6px rgba(0,0,0,0.6);
  font-family: var(--font-mono, monospace);
}

.ttt-cell:hover:not(:disabled):not(.filled) {
  background: #15273b;
  transform: scale(1.03);
}

.ttt-cell:disabled:not(.filled) {
  cursor: not-allowed;
  opacity: 0.55;
}

.ttt-cell.filled {
  cursor: default;
}

/* ── Yahtzee ──────────────────────────────────────────────────────────────── */

.yahtzee-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  height: 100%;
  padding: 14px 12px;
  gap: 14px;
  overflow-y: auto;
}

.yz-sheet-wrap {
  width: 100%;
  display: flex;
  justify-content: center;
}

.yz-sheet {
  border-collapse: separate;
  border-spacing: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 3px 10px rgba(0,0,0,0.35);
  font-size: 13px;
  min-width: 420px;
  max-width: 100%;
}

.yz-sheet th, .yz-sheet td {
  padding: 6px 10px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

/* Phone: the sheet's own 420px min-width already exceeds a 375px viewport
   — shrink font/padding to bring it closer, and make the remaining
   horizontal scroll both visible (own scroll container, not just relying
   on the generic .board-wrapper one) and discoverable (text hint, shown
   only while the sheet is actually wider than the screen). */
@media (max-width: 700px) {
  .yz-sheet-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    justify-content: flex-start;
    padding-bottom: 4px;
  }
  .yz-sheet { font-size: 11px; min-width: 360px; }
  .yz-sheet th, .yz-sheet td { padding: 5px 6px; }
  .yahtzee-wrapper::before {
    content: '↔ Zum Scrollen wischen';
    font-size: 11px;
    color: var(--text-muted);
    text-align: center;
  }
}

.yz-sheet thead th {
  background: var(--surface2);
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

.yz-sheet .yz-cat-col, .yz-sheet .yz-cat-label {
  text-align: left;
  color: var(--text);
  font-weight: 600;
  background: var(--surface2);
}

.yz-sheet .yz-hint, .yz-sheet .yz-hint-col {
  text-align: left;
  font-size: 11px;
  color: var(--text-muted);
  font-style: italic;
  font-weight: normal;
}

.yz-sheet .yz-col-current {
  background: rgba(79, 143, 224, 0.10);
}

.yz-sheet .yz-col-me {
  font-weight: 600;
}

.yz-sheet .yz-col-winner {
  background: rgba(255, 215, 0, 0.18);
}

.yz-sheet thead th.yz-col-winner {
  color: #ffd700;
}

.yz-score-cell {
  cursor: default;
  color: var(--text);
}

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

.yz-cell-scored {
  color: var(--text);
  font-weight: 600;
}

.yz-cell-locked {
  cursor: default;
}

.yz-cell-preview {
  cursor: pointer;
  color: var(--accent-hover);
  background: rgba(79, 143, 224, 0.05);
}

.yz-cell-preview:hover {
  background: rgba(79, 143, 224, 0.22);
  outline: 1px solid var(--accent);
}

.yz-cell-selected {
  background: var(--accent);
  color: #fff;
  outline: 2px solid var(--accent-hover);
}

.yz-cell-flash {
  animation: yzCellFlash 0.8s ease-out;
}

@keyframes yzCellFlash {
  0%   { background: #fff8a0; color: #000; }
  100% { background: transparent; color: inherit; }
}

.yz-row-sep td {
  padding: 0;
  height: 4px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}

.yz-summary-row {
  background: var(--surface2);
}

.yz-summary-row .yz-summary-cell {
  font-weight: 600;
  color: var(--text);
}

.yz-grand-row .yz-cat-label,
.yz-grand-row .yz-summary-cell {
  font-size: 14px;
  background: #0B1330;
  color: #fff;
}

/* ── dice tray ──────────────────────────────────────────────────────────── */

.yz-tray {
  display: flex;
  gap: 14px;
  justify-content: center;
  align-items: center;
  padding: 12px 16px;
  background: #0B1330;
  border-radius: 10px;
  border: 1px solid var(--border);
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.4);
  transition: outline 0.15s;
}

.yz-die {
  width: 64px;
  height: 64px;
  background: #fafafa;
  border-radius: 12px;
  border: 2px solid #d0d0d0;
  padding: 8px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 2px;
  cursor: pointer;
  transition: transform 0.12s, border-color 0.15s, box-shadow 0.15s;
  box-shadow: 0 2px 4px rgba(0,0,0,0.3);
}

.yz-die:hover:not(:disabled) {
  transform: translateY(-2px);
  border-color: var(--accent);
}

.yz-die:disabled {
  cursor: default;
}

.yz-die.yz-die-empty {
  background: #22335E;
  border-color: var(--border);
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.5);
}

.yz-die.yz-die-empty .yz-pip-slot.pip::after {
  background: transparent;
}

.yz-die.yz-die-held {
  border-color: var(--accent);
  background: #E3EEFC;
  box-shadow: 0 0 8px rgba(79, 143, 224, 0.6), 0 2px 4px rgba(0,0,0,0.3);
}

.yz-die.yz-die-rolling {
  animation: yzRoll 0.25s linear infinite;
}

/* Schmale Anzeigen: die Würfel müssen mitwachsen.
 *
 * Bewusst hier und nicht oben bei den übrigen Yahtzee-Regeln für schmale
 * Anzeigen: die Grundregel `.yz-die { width: 64px }` steht darüber, und bei
 * gleicher Spezifität gewinnt die spätere. Weiter oben eingefügt blieb diese
 * Regel wirkungslos.
 *
 * Gemessen bei 375 px: fünf Würfel à 64 px plus vier Abstände à 14 px ergeben
 * 376 px — schon ohne den Rand des Tabletts mehr, als der Bildschirm hat. Der
 * erste und der letzte Würfel wurden angeschnitten. */
@media (max-width: 700px) {
  .yz-tray {
    gap: clamp(4px, 2vw, 14px);
    padding: 10px clamp(6px, 2vw, 16px);
  }

  .yz-die {
    width: clamp(42px, 15.5vw, 64px);
    height: clamp(42px, 15.5vw, 64px);
    padding: clamp(4px, 1.4vw, 8px);
  }
}

@keyframes yzRoll {
  0%   { transform: rotate(0deg)   translateY(0); }
  25%  { transform: rotate(-8deg)  translateY(-3px); }
  50%  { transform: rotate(0deg)   translateY(0); }
  75%  { transform: rotate(8deg)   translateY(-3px); }
  100% { transform: rotate(0deg)   translateY(0); }
}

.yz-pip-slot {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.yz-pip-slot.pip::after {
  content: '';
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #222;
}

.yz-die.yz-die-held .yz-pip-slot.pip::after {
  background: #1b5e20;
}

/* ── roll button ────────────────────────────────────────────────────────── */

.yz-roll-wrap {
  display: flex;
  justify-content: center;
}

.yz-roll-btn {
  min-width: 240px;
  padding: 12px 24px;
  font-size: 15px;
  font-weight: 600;
}

/* ── Kniffel-Quadro ─────────────────────────────────────────────────────── */

.kq-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  height: 100%;
  padding: 14px 12px;
  gap: 14px;
  overflow-y: auto;
}

.kq-boards {
  width: 100%;
  display: flex;
  gap: 12px;
  overflow-x: auto;
  padding-bottom: 6px;
  -webkit-overflow-scrolling: touch;
}

.kq-board {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.kq-total-board {
  align-self: flex-start;
}

.kq-board-title {
  text-align: center;
  font-weight: 700;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

.kq-sheet {
  border-collapse: separate;
  border-spacing: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 3px 10px rgba(0,0,0,0.35);
  font-size: 12px;
}

.kq-sheet th, .kq-sheet td {
  padding: 5px 8px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.kq-sheet thead th {
  background: var(--surface2);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
}

/* Sticky category column so row identity survives horizontal scroll on
   narrow (phone) viewports — the 4-board layout is much wider than a
   single Yahtzee sheet, so this matters far more here. */
.kq-sheet .kq-cat-col,
.kq-sheet .kq-cat-label {
  text-align: left;
  color: var(--text);
  font-weight: 600;
  background: var(--surface2);
  position: sticky;
  left: 0;
  z-index: 1;
  /* Short abbreviations/die-icons replace the old full category names —
     pin the column to a narrow width so all 4 boards need less overall
     horizontal scrolling (Nutzervorgabe: "problemlos alle Spalten sehen"). */
  width: 54px;
  max-width: 54px;
  padding-left: 6px;
  padding-right: 4px;
  font-size: 11px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Small static die-face icon used as the row label for the six upper
   (Einser–Sechser) categories instead of a text word. */
.kq-mini-die {
  display: inline-grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  width: 20px;
  height: 20px;
  padding: 2px;
  gap: 1px;
  background: #fafafa;
  border: 1px solid #bbb;
  border-radius: 4px;
  vertical-align: middle;
}
.kq-mini-pip {
  display: block;
}
.kq-mini-pip.pip {
  border-radius: 50%;
  background: #1a1a1a;
}

.kq-sheet .kq-col-current {
  background: rgba(79, 143, 224, 0.10);
}

.kq-sheet .kq-col-me {
  font-weight: 600;
}

.kq-sheet .kq-col-winner {
  background: rgba(255, 215, 0, 0.18);
}

.kq-sheet thead th.kq-col-winner {
  color: #ffd700;
}

.kq-score-cell {
  cursor: default;
  color: var(--text);
}

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

.kq-cell-scored {
  color: var(--text);
  font-weight: 600;
}

.kq-cell-locked {
  cursor: default;
}

/* Every currently-clickable cell commits IMMEDIATELY on a single click —
   no select-then-confirm step. All eligible cells share one bold, solid
   bronze fill so they're unmistakable at a glance, regardless of which
   column (Normal, Pflicht-open "?", Down, Up) they belong to.
   Selectors are prefixed with `.kq-sheet` (matching `.kq-sheet
   .kq-col-current`'s specificity above) and placed after it in source
   order — these highlight cells always ALSO carry `.kq-col-current`
   (it's always your own turn when a cell is eligible), so without this
   the fainter column tint would silently win and wash the fill out to a
   thin outline with no background. */
.kq-sheet .kq-cell-preview-normal,
.kq-sheet .kq-cell-announceable,
.kq-sheet .kq-cell-preview-down,
.kq-sheet .kq-cell-preview-up {
  cursor: pointer;
  font-weight: 700;
  color: #fff;
  background: #946B2D;
  outline: 2px solid #6B4E1F;
  box-shadow: 0 0 6px rgba(148, 107, 45, 0.5);
}
.kq-sheet .kq-cell-preview-normal:hover,
.kq-sheet .kq-cell-announceable:hover,
.kq-sheet .kq-cell-preview-down:hover,
.kq-sheet .kq-cell-preview-up:hover {
  background: #B0873F;
  outline-color: #533C18;
}

/* Preview visible to spectators / other players during someone else's
   turn — same info as the bronze preview cells but not clickable (only
   the active player can actually commit), so it stays muted. */
.kq-sheet .kq-cell-preview-readonly {
  cursor: default;
  color: var(--text-muted);
  font-style: italic;
  background: rgba(255, 255, 255, 0.03);
}

/* Pflicht has been announced this turn: this is the ONLY cell still in
   play (everything else is hidden — see score-sheet.js paint()). A
   deeper, darker bronze than the "pick one of these" state above signals
   "locked in, no longer a choice" — one more click commits the final
   score. */
.kq-sheet .kq-cell-locked-pflicht {
  cursor: pointer;
  color: #fff;
  background: #6B4E1F;
  font-weight: 700;
  outline: 2px solid #C9A227;
  box-shadow: 0 0 8px rgba(107, 78, 31, 0.6);
}
.kq-sheet .kq-cell-locked-pflicht:hover {
  background: #83612A;
}

.kq-sheet .kq-cell-locked-pflicht-readonly {
  cursor: default;
  color: #946B2D;
  background: rgba(148, 107, 45, 0.15);
  font-weight: 700;
  font-style: italic;
}

.kq-cell-flash {
  animation: kqCellFlash 0.8s ease-out;
}

@keyframes kqCellFlash {
  0%   { background: #fff8a0; color: #000; }
  100% { background: transparent; color: inherit; }
}

.kq-row-sep td {
  padding: 0;
  height: 4px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}

.kq-summary-row {
  background: var(--surface2);
}

.kq-summary-row .kq-summary-cell {
  font-weight: 600;
  color: var(--text);
}

.kq-grand-row .kq-cat-label,
.kq-grand-row .kq-summary-cell {
  font-size: 13px;
  background: #0B1330;
  color: #fff;
}

.kq-total-sheet {
  min-width: 140px;
}

/* ── column identity colors ───────────────────────────────────────────────
   Nutzervorgabe: on narrow screens the 4 boards (Normal/Pflicht/Down/Up)
   are hard to tell apart while horizontally scrolling — only part of a
   table may be visible at a time, with no strong cue for which one it is.
   Each board gets a whole-table color wash (a translucent tint layered
   over the existing dark background via background-image, so the base
   surface color and text contrast are untouched) plus a solid top edge and
   a matching title color. Colors are chosen to stay clearly distinct from
   the bronze "eligible cell" fill (#946B2D) and the gold winner highlight
   (#ffd700) used elsewhere on the same sheets. Gesamt/total is left
   neutral — it isn't one of the four columns players confuse. */
.kq-board[data-column='normal'] .kq-board-title {
  color: #7fb2f0;
}
.kq-board[data-column='pflicht'] .kq-board-title {
  color: #e0a33c;
}
.kq-board[data-column='down'] .kq-board-title {
  color: #5ac482;
}
.kq-board[data-column='up'] .kq-board-title {
  color: #aa6ee0;
}

.kq-sheet[data-column='normal'] {
  border-top: 3px solid #4f8fe0;
  background-image: linear-gradient(rgba(79, 143, 224, 0.08), rgba(79, 143, 224, 0.08));
}
.kq-sheet[data-column='pflicht'] {
  border-top: 3px solid #e0a33c;
  background-image: linear-gradient(rgba(224, 163, 60, 0.09), rgba(224, 163, 60, 0.09));
}
.kq-sheet[data-column='down'] {
  border-top: 3px solid #5ac482;
  background-image: linear-gradient(rgba(90, 196, 130, 0.08), rgba(90, 196, 130, 0.08));
}
.kq-sheet[data-column='up'] {
  border-top: 3px solid #aa6ee0;
  background-image: linear-gradient(rgba(170, 110, 224, 0.09), rgba(170, 110, 224, 0.09));
}

/* thead + the sticky category column set their own opaque background
   (var(--surface2)) — tint those explicitly too so header/left-spine/body
   read as one consistently colored block instead of the tint stopping at
   the first data row. */
.kq-sheet[data-column='normal'] thead th,
.kq-sheet[data-column='normal'] .kq-cat-col,
.kq-sheet[data-column='normal'] .kq-cat-label {
  background-image: linear-gradient(rgba(79, 143, 224, 0.16), rgba(79, 143, 224, 0.16));
}
.kq-sheet[data-column='pflicht'] thead th,
.kq-sheet[data-column='pflicht'] .kq-cat-col,
.kq-sheet[data-column='pflicht'] .kq-cat-label {
  background-image: linear-gradient(rgba(224, 163, 60, 0.18), rgba(224, 163, 60, 0.18));
}
.kq-sheet[data-column='down'] thead th,
.kq-sheet[data-column='down'] .kq-cat-col,
.kq-sheet[data-column='down'] .kq-cat-label {
  background-image: linear-gradient(rgba(90, 196, 130, 0.16), rgba(90, 196, 130, 0.16));
}
.kq-sheet[data-column='up'] thead th,
.kq-sheet[data-column='up'] .kq-cat-col,
.kq-sheet[data-column='up'] .kq-cat-label {
  background-image: linear-gradient(rgba(170, 110, 224, 0.18), rgba(170, 110, 224, 0.18));
}

/* ── dice tray / roll button — identical mechanics to Yahtzee ────────────── */

.kq-tray {
  display: flex;
  gap: 14px;
  justify-content: center;
  align-items: center;
  padding: 12px 16px;
  background: #0B1330;
  border-radius: 10px;
  border: 1px solid var(--border);
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.4);
  transition: outline 0.15s;
}

.kq-die {
  width: 64px;
  height: 64px;
  background: #fafafa;
  border-radius: 12px;
  border: 2px solid #d0d0d0;
  padding: 8px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 2px;
  cursor: pointer;
  transition: transform 0.12s, border-color 0.15s, box-shadow 0.15s;
  box-shadow: 0 2px 4px rgba(0,0,0,0.3);
}

.kq-die:hover:not(:disabled) {
  transform: translateY(-2px);
  border-color: var(--accent);
}

.kq-die:disabled {
  cursor: default;
}

.kq-die.kq-die-empty {
  background: #22335E;
  border-color: var(--border);
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.5);
}

.kq-die.kq-die-empty .kq-pip-slot.pip::after {
  background: transparent;
}

.kq-die.kq-die-held {
  border-color: #e8c428;
  border-width: 3px;
  background: #fff8e1;
  box-shadow: 0 0 10px rgba(232, 196, 40, 0.7), 0 2px 4px rgba(0,0,0,0.3);
}

.kq-die.kq-die-rolling {
  animation: kqRoll 0.25s linear infinite;
}

@keyframes kqRoll {
  0%   { transform: rotate(0deg)   translateY(0); }
  25%  { transform: rotate(-8deg)  translateY(-3px); }
  50%  { transform: rotate(0deg)   translateY(0); }
  75%  { transform: rotate(8deg)   translateY(-3px); }
  100% { transform: rotate(0deg)   translateY(0); }
}

.kq-pip-slot {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.kq-pip-slot.pip::after {
  content: '';
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #222;
}

.kq-die.kq-die-held .kq-pip-slot.pip::after {
  background: #a8860a;
}

.kq-roll-wrap {
  display: flex;
  justify-content: center;
}

.kq-roll-btn {
  min-width: 240px;
  padding: 12px 24px;
  font-size: 15px;
  font-weight: 600;
}

/* Phones: shrink dice and sheet font further so 4 boards + totals stay
   scannable in the horizontal scroller instead of ballooning the page. */
@media (max-width: 700px) {
  .kq-sheet { font-size: 11px; }
  .kq-sheet th, .kq-sheet td { padding: 4px 6px; }
  .kq-die { width: 48px; height: 48px; }
  .kq-roll-btn { min-width: 200px; padding: 10px 18px; font-size: 14px; }
}

/* ── Battleship ───────────────────────────────────────────────────────────── */

.battleship-wrapper {
  --bs-cell: 36px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  height: 100%;
  padding: 12px;
  gap: 12px;
  overflow-y: auto;
  user-select: none;
}

/* ── grid primitive ─────────────────────────────────────────────────────── */

.bs-grid {
  display: grid;
  gap: 2px;
  padding: 6px;
  background: #0B1330;
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.4);
  width: fit-content;
}

.bs-cell {
  width: var(--bs-cell);
  height: var(--bs-cell);
  background: #22335E;
  border-radius: 3px;
  position: relative;
  transition: background 0.12s;
}

.bs-grid-dimmed .bs-cell {
  background: #1c2a1f;
  opacity: 0.55;
}

.bs-grid-active.bs-grid-opp .bs-cell:not(.bs-cell-shot-disabled):hover {
  background: #4a6750;
  cursor: crosshair;
  box-shadow: inset 0 0 0 2px var(--accent);
}

.bs-grid-inactive {
  opacity: 0.55;
  filter: grayscale(0.4);
}

/* Own ships visible */
.bs-cell.bs-cell-ship {
  background: var(--accent);
}
.bs-cell.bs-cell-ship-pickup {
  cursor: grab;
}
.bs-cell.bs-cell-ship-pickup:active {
  cursor: grabbing;
}

/* Drag ghost — green when placement valid, red when invalid */
.bs-cell.bs-cell-ghost-valid {
  background: rgba(76, 175, 80, 0.65);
  box-shadow: inset 0 0 0 2px var(--accent-hover);
}
.bs-cell.bs-cell-ghost-invalid {
  background: rgba(229, 57, 53, 0.55);
  box-shadow: inset 0 0 0 2px #e53935;
}

/* Shot markers */
.bs-cell.bs-cell-miss::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #c0c8c0;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.bs-cell.bs-cell-hit::after {
  content: '✕';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ff5252;
  font-weight: 700;
  font-size: 22px;
  text-shadow: 0 0 4px rgba(0,0,0,0.5);
}
/* One-shot impact flash added by onEvent('SHOT_FIRED') only, never by
   the state-driven paint loop — keeps the animation from replaying on
   every update tick. */
.bs-cell.bs-cell-hit-flash::after {
  animation: bsImpact 0.2s ease-out;
}
@keyframes bsImpact {
  0%   { transform: scale(1.8); opacity: 0; }
  60%  { transform: scale(0.85); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* Sunk: persistent ship outline + faint red wash */
.bs-cell.bs-cell-sunk {
  background: rgba(127, 29, 29, 0.85);
  box-shadow: inset 0 0 0 1px #fca5a5;
}
.bs-cell.bs-cell-sunk-flash {
  animation: bsSunkFlash 1s ease-out;
}
@keyframes bsSunkFlash {
  0%   { background: #fef08a; }
  100% { background: rgba(127, 29, 29, 0.85); }
}

.bs-cell.bs-cell-shot-disabled {
  cursor: default;
}

/* ── section labels ─────────────────────────────────────────────────────── */

.bs-section-label {
  margin: 0 0 6px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}

/* ── setup phase ────────────────────────────────────────────────────────── */

.bs-setup {
  display: grid;
  grid-template-columns: auto 280px;
  gap: 24px;
  align-items: start;
  justify-content: center;
}

/* Phone: neither the setup grid (board + 280px side panel) nor the firing
   grid (two full boards) fit side-by-side on a narrow screen even after
   shrinking cells — stack them instead, matching the game's own turn-based
   flow (you either place ships or watch/fire, never both boards at once). */
@media (max-width: 700px) {
  .battleship-wrapper { padding: 8px; gap: 8px; }
  .battleship-wrapper {
    /* 10 cells, 9 gaps(2px), grid padding(6px*2) — safety margin included. */
    --bs-cell: min(36px, calc((100vw - 40px) / 10));
  }
  .bs-setup,
  .bs-firing {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 16px;
  }
  .bs-unplaced-panel { width: 100%; max-width: calc(10 * var(--bs-cell) + 9 * 2px + 12px); }
}

.bs-setup-col {
  display: flex;
  flex-direction: column;
}

.bs-setup-status {
  margin-top: 10px;
  font-size: 14px;
  color: var(--text);
}

.bs-ready-btn {
  margin-top: 10px;
  width: fit-content;
  padding: 10px 24px;
  font-weight: 600;
}

.bs-unplaced-panel {
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px;
  margin-bottom: 16px;
}

.bs-hint {
  margin: 0 0 8px;
  font-size: 11px;
  color: var(--text-muted);
  font-style: italic;
}

.bs-unplaced-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 6px;
  border-radius: 4px;
  cursor: grab;
  transition: background 0.12s;
}
.bs-unplaced-row:hover {
  background: var(--surface2);
}
.bs-unplaced-row.bs-unplaced-placing {
  opacity: 0.55;
  cursor: default;
}
.bs-unplaced-row:active {
  cursor: grabbing;
}

.bs-ship-preview {
  display: flex;
  gap: 2px;
}
.bs-ship-seg {
  width: 14px;
  height: 14px;
  background: var(--ship-color, var(--accent));
  border-radius: 2px;
}

.bs-ship-label {
  font-size: 13px;
  color: var(--text);
  font-weight: 500;
}
.bs-ship-placing {
  margin-left: auto;
  font-size: 11px;
  color: var(--text-muted);
  font-style: italic;
}

.bs-opp-placeholder {
  position: relative;
}
.bs-opp-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 8px;
  background: rgba(22, 41, 26, 0.75);
  color: var(--text);
  font-size: 13px;
  border-radius: 6px;
}

/* ── firing phase ───────────────────────────────────────────────────────── */

.bs-firing {
  display: grid;
  grid-template-columns: auto auto;
  gap: 24px;
  align-items: start;
  justify-content: center;
}

.bs-firing-col {
  display: flex;
  flex-direction: column;
}

.bs-firing-status {
  margin-bottom: 6px;
  font-size: 13px;
  color: var(--text-muted);
  min-height: 18px;
}

/* ── game-over banner ───────────────────────────────────────────────────── */

.bs-game-over {
  grid-column: 1 / -1;
  margin-top: 12px;
  padding: 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  text-align: center;
}
.bs-game-over-headline {
  font-size: 22px;
  font-weight: 700;
  color: var(--accent);
}
.bs-game-over-sub {
  margin-top: 6px;
  font-size: 13px;
  color: var(--text-muted);
}

/* ── Risk board ──────────────────────────────────────────────────────────── */

.risk-wrapper {
  position: relative;
  width:    100%;
  height:   100%;
  display:  flex;
  align-items:     center;
  justify-content: center;
  background:      #1a2a3a;
  overflow:        hidden;
}

.risk-map-host {
  width:  100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.risk-map-host svg {
  max-width:  100%;
  max-height: 100%;
}

.risk-map-host path {
  stroke:       #2a3a4a;
  stroke-width: 1.2;
  transition:   fill 0.2s, stroke-width 0.15s, filter 0.15s;
}

.risk-map-host path.risk-mine {
  stroke:       #ffffff;
  stroke-width: 3.5;
  filter:       drop-shadow(0 0 4px rgba(255,255,255,0.55));
}

.risk-map-host path:hover {
  stroke:       #fff;
  stroke-width: 3.2;
  filter:       brightness(1.22);
}

.risk-map-host path.risk-selected {
  stroke:       #ffeb3b;
  stroke-width: 4;
  filter:       drop-shadow(0 0 8px rgba(255, 235, 59, 0.85)) brightness(1.2);
}

.risk-loading {
  color:       var(--text-muted);
  font-style:  italic;
  font-size:   14px;
}

.risk-btn {
  margin-bottom: 6px;
}

.risk-help {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--text-muted);
}

/* ── turn-timer warning banner ───────────────────────────────────────────── */

.turn-warning {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  padding: 10px 18px;
  background: rgba(120, 53, 15, 0.95);
  color: #fff;
  border: 1px solid var(--warning);
  border-radius: 6px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
  font-size: 14px;
  font-weight: 500;
  pointer-events: none;
  max-width: calc(100vw - 32px);
  text-align: center;
}

.turn-warning.turn-warning-me {
  background: rgba(153, 27, 27, 0.95);
  border-color: #f87171;
  animation: turnWarningPulse 1s ease-in-out infinite;
}

@keyframes turnWarningPulse {
  0%, 100% { box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45); }
  50%      { box-shadow: 0 4px 18px rgba(248, 113, 113, 0.55), 0 4px 14px rgba(0, 0, 0, 0.45); }
}

/* ── The Game of Life ─────────────────────────────────────────────────────── */
/*
 * Life renderer is split across four files (renderer / board-view /
 * action-panel / card-display) so the CSS is grouped here by what each
 * sub-view owns.
 *
 * Layout: .life-wrapper holds the board on the left and the inventory
 * panel on the right.  At narrow viewports the inventory wraps below.
 */

.life-wrapper {
  display: flex;
  flex-direction: row;
  gap: 12px;
  width: 100%;
  height: 100%;
  padding: 12px;
  box-sizing: border-box;
  overflow: auto;
}

.life-board-container {
  flex: 1 1 auto;
  min-width: 0;
  overflow: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px;
}

.life-inventory-container {
  flex: 0 0 280px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px;
}

/* ── board grid ─────────────────────────────────────────────────────────── */

.life-board {
  --life-col: 64px;
  --life-row: 56px;
  display: grid;
  grid-template-columns: repeat(23, var(--life-col));
  grid-template-rows: repeat(11, var(--life-row));
  gap: 4px;
  position: relative;
  min-width: max-content;
}

/* Phone: 23 columns can never fit a phone screen at a legible size (even at
   a minimal cell size the board stays far wider than the viewport) — this
   is inherent to the game, not a bug, so the fix is smaller cells (more of
   the board visible per screen) plus explicit smooth touch-scrolling and a
   visible hint, matching the Kniffel-Quadro convention of "shrink as far
   as reasonable, then scroll clearly" rather than forcing an unreadable fit. */
@media (max-width: 700px) {
  .life-board { --life-col: 40px; --life-row: 36px; gap: 2px; }
  .life-square { font-size: 8px; padding: 2px; }
  .life-board-container {
    -webkit-overflow-scrolling: touch;
    padding: 8px;
  }
  .life-wrapper::before {
    content: '↔ Spielfeld zum Scrollen wischen';
    font-size: 11px;
    color: var(--text-muted);
    text-align: center;
    display: block;
    margin-bottom: 4px;
  }
}

.life-square {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px;
  font-size: 10px;
  line-height: 1.1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  cursor: default;
  overflow: hidden;
  transition: outline-color 200ms ease;
  outline: 2px solid transparent;
}

.life-square-icon {
  font-size: 14px;
  margin-bottom: 2px;
}

.life-square-label {
  font-size: 9px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
}

/* Square-type accents — light bg tinting so a glance at the board reveals
 * the rhythm of paydays, fork choices, and effect-heavy squares.  Kept
 * subtle so the player cars (which use vivid full-color fills) stay the
 * focal point. */
.life-square-payday               { background: #2d4a2d; }
.life-square-collect-bank         { background: #29402f; }
.life-square-pay-bank             { background: #4a2d2d; }
.life-square-pay-tax-by-salary    { background: #4a2d2d; }
.life-square-pay-loans            { background: #4a2d2d; }
.life-square-pay-each-player      { background: #4a2d2d; }
.life-square-collect-each-player  { background: #29402f; }
.life-square-spin-again           { background: #3a3a5c; }
.life-square-marry                { background: #5c3a5c; }
.life-square-have-baby            { background: #5c3a5c; }
.life-square-have-twins           { background: #5c3a5c; }
.life-square-buy-house            { background: #4a4023; }
.life-square-auto-accident        { background: #5c2d2d; }
.life-square-life-accident        { background: #5c2d2d; }
.life-square-career-fork          { background: #3a3a3a; font-weight: bold; }
.life-square-draw-career-no-degree { background: #2f4a4a; }
.life-square-draw-career-degree   { background: #2f4a4a; }
.life-square-retirement-fork      { background: #5c4a2d; font-weight: bold; }
.life-square-countryside-retirement { background: #2d5c3a; font-weight: bold; }
.life-square-millionaire-retirement { background: #5c4a2d; font-weight: bold; }

/* Active player's "you are here, decide now" emphasis. */
.life-square-highlight {
  outline: 2px solid #f8c43c;
  box-shadow: 0 0 0 2px rgba(248, 196, 60, 0.35);
}

/* ── player cars ────────────────────────────────────────────────────────── */

.life-car {
  width: 28px;
  height: 22px;
  border-radius: 6px;
  border: 2px solid #222;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: #fff;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.6);
  pointer-events: none;
  /* No transition by default so update() can snap cars to state without
   * triggering animation.  The .life-car-stepping class scopes the
   * deceleration transition to animation steps only.  See board-view.js. */
  align-self: center;
  justify-self: center;
  position: relative;
}

.life-car-stepping {
  transition: all 140ms cubic-bezier(0.4, 0.0, 0.2, 1);
}

.life-car-token {
  display: inline-block;
}

.life-car-pegs {
  position: absolute;
  bottom: -4px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 7px;
  color: #fff;
  white-space: nowrap;
}

.life-car-me {
  box-shadow: 0 0 0 2px #f8c43c, 0 1px 4px rgba(0, 0, 0, 0.4);
}

.life-car-retired {
  opacity: 0.45;
  filter: grayscale(0.6);
}

.life-car-retired-badge {
  position: absolute;
  top: -8px;
  right: -8px;
  background: #48bb78;
  color: #fff;
  border-radius: 50%;
  width: 14px;
  height: 14px;
  font-size: 10px;
  line-height: 14px;
  text-align: center;
  font-weight: bold;
}

/* ── inventory panel ────────────────────────────────────────────────────── */

.life-inventory { font-size: 12px; }

.life-my-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px;
  margin-bottom: 12px;
}

.life-card-name {
  margin: 0 0 8px 0;
  font-size: 14px;
  color: var(--text);
}

.life-card-row {
  display: flex;
  justify-content: space-between;
  padding: 3px 0;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.05);
  font-size: 11px;
}

.life-card-row:last-child { border-bottom: none; }

.life-card-row label {
  color: var(--text-muted);
  font-weight: 600;
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: 0.04em;
}

.life-card-row span,
.life-card-row strong { color: var(--text); }

.life-card-tiles { flex-direction: column; align-items: flex-start; gap: 4px; }

.life-tiles-stack {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
}

.life-tile-face-down {
  display: inline-block;
  background: #3a3a3a;
  border: 1px solid #555;
  border-radius: 3px;
  padding: 2px 5px;
  font-size: 11px;
  color: var(--text-muted);
}

.life-retired-tag {
  margin-top: 8px;
  background: #48bb78;
  color: #fff;
  border-radius: 4px;
  padding: 3px 6px;
  font-size: 11px;
  text-align: center;
  font-weight: bold;
}

.life-opponents h4 {
  font-size: 12px;
  margin: 0 0 6px 0;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

.life-opp-row {
  display: grid;
  grid-template-columns: 12px 1fr auto;
  gap: 6px;
  align-items: center;
  padding: 5px 6px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  margin-bottom: 4px;
}

.life-opp-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.3);
}

.life-opp-name { font-size: 12px; }

.life-opp-retired {
  display: inline-block;
  margin-left: 6px;
  background: #48bb78;
  color: #fff;
  font-size: 9px;
  padding: 1px 4px;
  border-radius: 3px;
}

.life-opp-cash {
  font-weight: bold;
  font-size: 11px;
}

.life-opp-meta {
  grid-column: 1 / -1;
  font-size: 10px;
  color: var(--text-muted);
  margin-top: 2px;
}

/* ── action panel: spinner ─────────────────────────────────────────────── */

.life-spinner-box {
  position: relative;
  width: 150px;
  height: 150px;
  margin: 0 auto 12px auto;
}

.life-spinner-wheel {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: radial-gradient(circle at center, #2a3441, #1a212a);
  border: 4px solid #f8c43c;
  position: relative;
  /* The deceleration curve gives the wheel that "spinning down" feel:
   * fast start, slow stop, settles cleanly on the result.  1.5s total. */
  transition: transform 1.5s cubic-bezier(0.05, 0.6, 0.3, 1);
}

.life-spinner-seg {
  position: absolute;
  top: 0;
  left: 50%;
  width: 0;
  height: 75px;
  border-left: 0;
  transform-origin: 50% 100%;
}

.life-spinner-num {
  position: absolute;
  top: 8px;
  left: -8px;
  width: 16px;
  text-align: center;
  font-size: 13px;
  font-weight: bold;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}

.life-spinner-pointer {
  position: absolute;
  top: -10px;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 12px solid transparent;
  border-right: 12px solid transparent;
  border-top: 20px solid #e94235;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.6));
  z-index: 2;
}

/* ── action panel: buttons + messages ──────────────────────────────────── */

.life-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.life-actions-message {
  font-size: 12px;
  color: var(--text-muted);
  text-align: center;
  padding: 12px 0;
  margin: 0;
}

.life-spin-btn {
  font-size: 16px;
  padding: 12px;
}

.life-purchase-btn {
  font-size: 12px;
  padding: 8px;
}

.life-card-choice {
  text-align: left;
  font-size: 12px;
  padding: 10px;
  line-height: 1.3;
}

.life-card-choice small {
  display: block;
  color: var(--text-muted);
  margin-top: 2px;
  font-size: 10px;
}

.life-fork-choice {
  font-size: 14px;
  padding: 12px;
}

.life-retirement-banner {
  background: linear-gradient(135deg, #5c4a2d, #2d5c3a);
  border: 2px solid #f8c43c;
  border-radius: 6px;
  padding: 10px;
  font-size: 11px;
  margin-bottom: 8px;
  line-height: 1.4;
  color: #fff;
}

.life-retirement-banner strong {
  display: block;
  font-size: 13px;
  margin-bottom: 4px;
  color: #f8c43c;
}

.life-retirement-choice {
  font-size: 16px;
  padding: 16px;
  font-weight: bold;
}

.life-stock-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
  margin: 8px 0;
}

.life-stock-cell {
  padding: 8px;
  font-size: 14px;
  font-weight: bold;
}

/* ── game over panel ───────────────────────────────────────────────────── */

.life-game-over {
  margin-top: 16px;
  background: var(--bg);
  border: 2px solid #f8c43c;
  border-radius: 6px;
  padding: 12px;
}

.life-game-over h3 {
  margin: 0 0 12px 0;
  text-align: center;
  color: #f8c43c;
}

.life-score-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 10px;
  margin-bottom: 8px;
}

.life-score-row h4 {
  margin: 0 0 6px 0;
  font-size: 14px;
}

.life-score-line {
  font-size: 11px;
  color: var(--text-muted);
  padding: 2px 0;
}

.life-score-total {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
  font-size: 13px;
}

.life-score-total strong { color: #f8c43c; }

.life-score-melost { opacity: 0.7; }

.life-melost-note { color: #e94235; font-size: 10px; }

.life-winner-badge { margin-right: 6px; }

.life-tile-reveal-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}

.life-tile-revealed {
  display: inline-block;
  background: #2d4a2d;
  border: 1px solid #48bb78;
  border-radius: 4px;
  padding: 4px 6px;
  font-size: 10px;
  line-height: 1.2;
}

@keyframes lifeTileFlipIn {
  from { transform: rotateY(180deg) scale(0.5); opacity: 0; }
  to   { transform: rotateY(0deg)   scale(1);   opacity: 1; }
}

.life-tile-flip-in {
  animation: lifeTileFlipIn 350ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

.life-tile-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}

/* Responsive: stack inventory below the board on narrow viewports. */
@media (max-width: 1100px) {
  .life-wrapper { flex-direction: column; }
  .life-inventory-container { flex: 1 1 auto; width: 100%; }
}

/* ── scrollbar styling ────────────────────────────────────────────────────── */

::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ──
   SPECTATOR MODE
── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── */

/* Banner across the top of the game screen while spectating.  Toggled by
   UIManager.applySpectatorChrome — default hidden, flipped to flex when
   the local viewer joined via the spectate flow rather than as a player. */
#spectator-banner {
  align-items: center;
  justify-content: center;
  padding: 8px 16px;
  background: linear-gradient(90deg, var(--surface2), var(--surface));
  border-bottom: 1px solid var(--accent);
  color: var(--text);
  font-size: 13px;
}
.spectator-banner-text {
  letter-spacing: 0.3px;
}

/* ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ──
   HELP OVERLAY  (used by help-system.js)
── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── */

/* The little "?" trigger that lives next to game-type names in the lobby
   and as a sidebar button during gameplay.  Same .btn family as the rest
   of the framework — circular variant for the lobby form factor. */
.help-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-weight: 700;
  font-size: 13px;
  cursor: pointer;
  padding: 0;
  margin-left: 6px;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.help-btn:hover {
  background: var(--surface2);
  color: var(--text);
  border-color: var(--accent);
}

/* Lobby: the select + ? button sit on one row; the type's metadata
   description shows underneath the row as a one-line hint. */
.game-type-row { display: flex; align-items: center; gap: 6px; }
.game-type-row select { flex: 1; }
.game-type-description {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 6px;
  min-height: 16px;
}

/* Per-card "?" button on game-card listings — sits inside the badge cluster. */
.game-card .help-btn {
  width: 20px;
  height: 20px;
  font-size: 11px;
  margin-left: 4px;
}

.help-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.65);
  align-items: center;
  justify-content: center;
  z-index: 2000;
}
.help-overlay-content {
  width: min(80vw, 760px);
  height: 80vh;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.6);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.help-overlay-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--surface2);
  flex-shrink: 0;
}
.help-overlay-title { font-size: 16px; color: var(--text); }
.help-overlay-close {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 18px;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
}
.help-overlay-close:hover { background: var(--border); color: var(--text); }

.help-overlay-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px 28px;
  color: var(--text);
  line-height: 1.55;
}
.help-overlay-body h1 { font-size: 22px; margin: 4px 0 14px;  color: var(--accent); }
.help-overlay-body h2 { font-size: 18px; margin: 22px 0 8px;  color: var(--accent-hover); border-bottom: 1px solid var(--border); padding-bottom: 4px; }
.help-overlay-body h3 { font-size: 16px; margin: 18px 0 6px;  color: var(--text); }
.help-overlay-body h4 { font-size: 14px; margin: 14px 0 4px;  color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }
.help-overlay-body p  { margin: 0 0 10px; }
.help-overlay-body ul,
.help-overlay-body ol { margin: 0 0 12px 22px; }
.help-overlay-body li { margin-bottom: 4px; }
.help-overlay-body strong { color: var(--text); }
.help-overlay-body em     { color: var(--text-muted); font-style: italic; }
.help-overlay-body hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 18px 0;
}
.help-overlay-body .help-table {
  border-collapse: collapse;
  width: 100%;
  margin: 10px 0 16px;
  font-size: 13px;
}
.help-overlay-body .help-table th,
.help-overlay-body .help-table td {
  border: 1px solid var(--border);
  padding: 6px 10px;
  text-align: left;
}
.help-overlay-body .help-table th {
  background: var(--surface2);
  color: var(--text);
}
.help-overlay-body .help-loading,
.help-overlay-body .help-error {
  color: var(--text-muted);
  text-align: center;
  padding: 40px 0;
}
.help-overlay-body .help-error { color: var(--danger); }

@media (max-width: 700px) {
  .help-overlay-content { width: 95vw; height: 90vh; }
  .help-overlay-body { padding: 16px 18px; }
}

/* ── Checkers board ──────────────────────────────────────────────────────── */

.checkers-wrapper {
  --ck-cell: 62px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 16px;
  gap: 8px;
}

/* Phone: 8 * 62px cells (496px) overflowed a 375px viewport with no shrink
   mechanism at all. */
@media (max-width: 700px) {
  .checkers-wrapper { padding: 8px; }
  .checkers-wrapper {
    /* 8 cells, no gap/padding on the grid itself (see .ck-grid) — just a
       safety margin for scrollbar/browser chrome. */
    --ck-cell: min(62px, calc((100vw - 16px) / 8));
  }
}

.ck-capture-banner {
  background: rgba(255, 167, 38, 0.15);
  border: 1px solid var(--warning);
  color: var(--warning);
  font-size: 13px;
  font-weight: 600;
  padding: 6px 14px;
  border-radius: 6px;
  text-align: center;
}

.ck-grid {
  display: grid;
  gap: 0;
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
  width: fit-content;
}

.ck-cell {
  width: var(--ck-cell);
  height: var(--ck-cell);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.ck-light { background: #d4a76a; }
.ck-dark  { background: #6b3a2a; }

/* ── pieces ──────────────────────────────────────────────────────────────── */

.ck-piece {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  transition: box-shadow 0.2s, transform 0.2s;
}

.ck-piece-red {
  background: radial-gradient(circle at 35% 35%, #e74c3c, #962d22);
  border: 2px solid #7a2018;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4), inset 0 1px 2px rgba(255, 255, 255, 0.15);
}

.ck-piece-black {
  background: radial-gradient(circle at 35% 35%, #4a4a4a, #1a1a1a);
  border: 2px solid #111;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4), inset 0 1px 2px rgba(255, 255, 255, 0.1);
}

.ck-crown {
  font-size: 20px;
  line-height: 1;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
  pointer-events: none;
}

/* ── selection & eligibility highlights ──────────────────────────────────── */

.ck-eligible {
  box-shadow: 0 0 0 3px rgba(79, 143, 224, 0.5), 0 2px 6px rgba(0, 0, 0, 0.4);
  cursor: pointer;
}

.ck-capture-eligible {
  box-shadow: 0 0 0 3px rgba(255, 167, 38, 0.7), 0 2px 6px rgba(0, 0, 0, 0.4);
  animation: ck-pulse 1.2s ease-in-out infinite;
  cursor: pointer;
}

.ck-selected {
  box-shadow: 0 0 0 4px var(--accent), 0 0 12px rgba(79, 143, 224, 0.6);
  transform: scale(1.08);
}

@keyframes ck-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(255, 167, 38, 0.7), 0 2px 6px rgba(0, 0, 0, 0.4); }
  50%      { box-shadow: 0 0 0 5px rgba(255, 167, 38, 0.9), 0 0 14px rgba(255, 167, 38, 0.4); }
}

/* ── destination markers ─────────────────────────────────────────────────── */

.ck-dest::after,
.ck-dest-capture::after {
  content: '';
  position: absolute;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 2;
}

.ck-dest {
  background: rgba(79, 143, 224, 0.15);
}

.ck-dest::after {
  background: rgba(79, 143, 224, 0.5);
}

.ck-dest-capture {
  background: rgba(255, 167, 38, 0.15);
}

.ck-dest-capture::after {
  background: rgba(255, 167, 38, 0.6);
}

/* ── move animation ──────────────────────────────────────────────────────── */

.ck-anim-moving {
  transition: transform 350ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
  z-index: 10;
}

/* ── capture fade ────────────────────────────────────────────────────────── */

.ck-anim-fading {
  animation: ck-fade-out 400ms ease-out forwards;
}

@keyframes ck-fade-out {
  0%   { transform: scale(1); opacity: 1; }
  30%  { transform: scale(1.15); opacity: 1; border-color: var(--danger); box-shadow: 0 0 12px var(--danger); }
  100% { transform: scale(0.5); opacity: 0; }
}

/* ── coronation animation ────────────────────────────────────────────────── */

.ck-anim-crowning {
  animation: ck-crown-pop 600ms ease-out;
}

.ck-crown-anim {
  animation: ck-crown-fade-in 300ms ease-out;
}

@keyframes ck-crown-pop {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.2); }
  100% { transform: scale(1); }
}

@keyframes ck-crown-fade-in {
  0%   { opacity: 0; transform: scale(0.5); }
  100% { opacity: 1; transform: scale(1); }
}

/* ── responsive: narrow viewports ────────────────────────────────────────── */

@media (max-width: 900px) {
  .game-sidebar { width: 240px; }
  :root {
    /* Recalculate for narrower sidebar */
    --board-size: min(calc(100vw - 272px), calc(100dvh - 86px), 960px);
  }
}

@media (max-width: 700px) {
  .game-layout { flex-direction: column; overflow-y: auto; }
  .game-sidebar { width: 100%; border-left: none; border-top: 1px solid var(--border); }
  :root {
    /* Sidebar is now stacked below — board fills viewport width */
    --board-size: min(calc(100vw - 32px), 480px);
  }

  /* Games without a fixed --board-size (Yahtzee, Kniffel-Quadro — content-
     driven height instead of a square board) otherwise collapse to near
     zero height here: .board-wrapper has overflow:auto, which resets a
     flex item's automatic minimum size to 0, so the flex-column layout
     above happily shrinks it to make room for the (often taller) stacked
     sidebar. A floor keeps the content reachable instead of invisible. */
  .board-wrapper { min-height: 360px; }

  /* Kniffel-Quadro "your turn" focus mode (mobile only): while it's your
     turn, the renderer toggles body.kq-mobile-focus and #kq-boards
     .kq-hide-total so the 4 real columns get the full screen instead of
     competing with the Gesamt table and the stacked Game-Log/Chat
     sections for space. Restored automatically once the turn passes on
     (see KniffelQuadroRenderer.paintMobileFocus). */
  body.kq-mobile-focus .log-section,
  body.kq-mobile-focus .chat-section {
    display: none;
  }
  body.kq-mobile-focus .board-wrapper {
    min-height: 520px;
  }
  .kq-boards.kq-hide-total .kq-total-board {
    display: none;
  }

  /* Kniffel-Quadro "not your turn" waiting mode (mobile only): the always-
     visible Players panel is redundant here (the waiting placeholder below
     and, once it's your turn, the board itself already say who's up), so
     it's hidden in both of this game's mobile modes to reclaim space. */
  body.kq-mobile-focus .players-section,
  body.kq-mobile-waiting .players-section {
    display: none;
  }

  /* While someone ELSE is playing, there's nothing to click — swap the
     board/dice/roll-button out for the waiting placeholder and let the
     Game Log + Chat (visible again since .kq-mobile-focus is off) take
     the screen instead of a frozen, unusable board. */
  body.kq-mobile-waiting #kq-boards,
  body.kq-mobile-waiting #kq-tray,
  body.kq-mobile-waiting .kq-roll-wrap {
    display: none;
  }
  body.kq-mobile-waiting .kq-waiting {
    display: flex;
  }

  /* Everything below must fit in ONE screen without scrolling — the
     defaults (360px board floor, 210px log, 120px chat) were sized for
     the desktop sidebar and leave a huge dead gap above Log/Chat on a
     phone. Shrink every piece of chrome specifically for waiting mode. */
  body.kq-mobile-waiting .board-wrapper {
    /* .board-wrapper is `flex: 1` (grow) with centered content — without
       overriding flex-grow, it still stretches to fill all leftover
       vertical space in the column layout even at min-height:0, leaving
       a large dead gap above Log/Chat with only the small waiting banner
       floating at its top. Shrink-to-content instead. */
    flex: 0 0 auto;
    min-height: 0;
  }
  body.kq-mobile-waiting .kq-wrapper {
    height: auto;
  }
  body.kq-mobile-waiting .action-section,
  body.kq-mobile-waiting .log-section,
  body.kq-mobile-waiting .chat-section {
    padding: 8px 12px;
  }
  body.kq-mobile-waiting .action-section h3,
  body.kq-mobile-waiting .log-section h3,
  body.kq-mobile-waiting .chat-section h3 {
    margin-bottom: 4px;
  }
  body.kq-mobile-waiting .game-log {
    height: 130px;
  }
  body.kq-mobile-waiting .chat-messages {
    height: 70px;
    margin-bottom: 4px;
  }
}

/* Kniffel-Quadro on tablets (Nutzervorgabe: Xiaomi Pad 5 and similar —
   wider than a phone but the 4 columns + Gesamt still don't fit next to
   the always-on sidebar). Fix: give the board the full row width, and
   — per explicit follow-up feedback — the renderer (see
   KniffelQuadroRenderer.updateSidebarEmbed) physically moves the real
   Players/Log/Chat sidebar into the Gesamt column, right below its
   table, narrowed to that column's width via `.kq-sidebar-embedded`
   below. More players making the row wider just means more horizontal
   scrolling to reach it — accepted trade-off (Nutzervorgabe).
   Unlike on phones, the 4 columns stay visible here at ALL times —
   including while another player is taking their turn (Nutzervorgabe:
   "die Spalten sollen auf dem Pad immer sichtbar sein") — there's
   enough width at this size to keep the board on screen instead of
   swapping it for the waiting placeholder. */

/* Keep the roll button reachable without scrolling: pin the dice tray
   and roll button to the bottom of the scrollable board area instead of
   letting them trail after 4 (tall) score sheets — the visible viewport
   in a mobile browser is already shorter than the screen itself (browser
   chrome/status bars), so this matters even more here than it would in
   a desktop window. */
@media (min-width: 701px) and (max-width: 1366px) {
  .kq-tray {
    position: sticky;
    bottom: 66px;
    z-index: 3;
  }
  .kq-roll-wrap {
    position: sticky;
    bottom: 0;
    z-index: 3;
    background: var(--bg);
    padding: 6px 0 2px;
  }
}

/* Applied by JS (not gated by the media query itself — its presence IS
   the gate, toggled only while the tablet breakpoint matches) when the
   sidebar has been reparented into `.kq-total-board`. Without a width
   clamp on the COLUMN, flexbox sizes `.kq-total-board` to its widest
   child — and the sidebar's own content (log lines, chat input) wants
   far more than the Gesamt table's ~140px, which would balloon the
   column outward instead of the sidebar shrinking inward (the actual
   Nutzervorgabe). Pin the column to a fixed narrow width and let the
   sidebar (now 100% of THAT) — and its log/chat text — wrap/scroll
   inside it instead. */
.kq-total-board.kq-total-embedded {
  width: 190px;
  flex: 0 0 190px;
}
.game-sidebar.kq-sidebar-embedded {
  width: 100%;
  border-left: none;
  border-top: 1px solid var(--border);
  overflow-x: hidden;
}

/* `.game-layout` (shared framework rule) clips overflow rather than
   scrolling it, and at typical tablet viewport heights the sidebar's
   default sizing (210px log + 120px chat + normal section padding)
   pushes the chat box just past the bottom edge with no way to reach it.
   Trim it down the same way the phone waiting-view already does, so the
   whole embedded column comfortably fits without depending on any
   scroll container actually being present. */
.kq-sidebar-embedded .players-section,
.kq-sidebar-embedded .action-section,
.kq-sidebar-embedded .log-section,
.kq-sidebar-embedded .chat-section {
  padding: 6px 10px;
}
.kq-sidebar-embedded .players-section h3,
.kq-sidebar-embedded .action-section h3,
.kq-sidebar-embedded .log-section h3,
.kq-sidebar-embedded .chat-section h3 {
  margin-bottom: 4px;
}
.kq-sidebar-embedded .game-log {
  height: 120px;
}
.kq-sidebar-embedded .chat-messages {
  height: 50px;
  margin-bottom: 4px;
}

/* Base state: hidden everywhere (including desktop) — only the mobile
   ".kq-mobile-waiting" rule above ever reveals it. */
.kq-waiting {
  display: none;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  text-align: center;
  padding: 10px;
}
