/* ------------------------------------------------------------------ */
/* Responsive breakpoints                                               */
/* ------------------------------------------------------------------ */
/* Mobile  : max-width 640px                                           */
/* Tablet  : 641px – 1024px                                            */

/* ------------------------------------------------------------------ */
/* Design tokens                                                       */
/* ------------------------------------------------------------------ */
:root {
  /* Brand */
  --color-primary: #6366f1;
  --color-primary-hover: #4f46e5;
  --color-primary-disabled: #a5a6f6;
  --color-primary-light: #f5f3ff;
  --color-primary-focus-ring: rgba(99,102,241,.15);

  /* Surfaces */
  --color-bg: #f5f5f4;
  --color-surface: #fff;
  --color-text-on-primary: #fff;

  /* Borders / fills */
  --color-border: #e5e7eb;
  --color-border-subtle: #f3f4f6;
  --color-border-input: #d1d5db;
  --color-bg-subtle: #f9fafb;

  /* Text */
  --color-text: #1a1a1a;
  --color-text-secondary: #374151;
  --color-text-muted: #6b7280;
  --color-text-faint: #9ca3af;

  /* Semantic */
  --color-success-bg: #dcfce7;
  --color-success-border: #86efac;
  --color-success-text: #166534;
  --color-success-strong-bg: #d1fae5;
  --color-success-strong-text: #059669;
  --color-danger: #dc2626;
  --color-danger-bg: #fee2e2;
  --color-danger-border: #fca5a5;
  --color-warning-bg: #fef3c7;
  --color-warning-border: #fde68a;
  --color-warning-text: #92400e;
  --color-info-bg: #dbeafe;
  --color-info-text: #1d4ed8;

  /* Radii */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-xl: 12px;
  --radius-pill: 99px;

  /* Shadows */
  --shadow-card: 0 1px 3px rgba(0,0,0,.06);
  --shadow-card-strong: 0 1px 4px rgba(0,0,0,.08);
}

/* ------------------------------------------------------------------ */
/* Base                                                                 */
/* ------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 14px;
  background: var(--color-bg);
  color: var(--color-text);
}

.hidden { display: none !important; }

/* Set synchronously by player.html's inline head script — hides the join
   form before first paint when a saved rejoin identity exists, so a
   reloading player never sees a flash of the name-entry screen. */
html.qb-resuming #view-join { display: none; }

/* ------------------------------------------------------------------ */
/* Player page                                                          */
/* ------------------------------------------------------------------ */
.player-wrap {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.player-card {
  background: var(--color-surface);
  border-radius: var(--radius-xl);
  padding: 32px 24px;
  width: 100%;
  max-width: 360px;
  box-shadow: var(--shadow-card-strong);
  text-align: center;
}

.player-card h1 { font-size: 20px; margin: 0 0 24px; }

.player-card input[type="text"]:not(.otp-box) {
  width: 100%;
  padding: 12px 14px;
  font-size: 16px;
  border: 1px solid var(--color-border-input);
  border-radius: var(--radius-md);
  outline: none;
  margin-bottom: 12px;
}
.player-card input[type="text"]:not(.otp-box):focus { border-color: var(--color-primary); }

.btn-primary {
  width: 100%;
  padding: 12px;
  background: var(--color-primary);
  color: var(--color-text-on-primary);
  border: none;
  border-radius: var(--radius-md);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.btn-primary:hover { background: var(--color-primary-hover); }
.btn-primary:disabled { background: var(--color-primary-disabled); cursor: not-allowed; }

.error-msg { color: var(--color-danger); font-size: 13px; margin-top: 8px; margin-bottom: 8px; }

.script-load-error {
  background: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  border-radius: var(--radius-md);
  color: var(--color-danger);
  font-size: 14px;
  font-weight: 600;
  margin: 12px;
  padding: 10px 12px;
}
.script-load-error p { margin: 0 0 10px; }
.script-load-error .btn-primary { width: auto; padding: 8px 16px; }

.status-msg { color: var(--color-text-muted); font-size: 15px; line-height: 1.5; }
.status-msg-success { color: var(--color-success-text); font-weight: 600; }

/* OTP boxes — input variant (create + player pages) */
.otp-label, .field-label {
  font-size: 12px;
  color: var(--color-text-muted);
  font-weight: 500;
  text-align: left;
  display: block;
  margin: 0 0 6px;
}
.field-label { margin-top: 4px; }

.otp-boxes {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-bottom: 16px;
}

.otp-box {
  width: 52px;
  height: 56px;
  font-size: 22px;
  font-weight: 700;
  text-align: center;
  border: 2px solid var(--color-border-input);
  border-radius: var(--radius-lg);
  outline: none;
  background: var(--color-surface);
  color: var(--color-text);
  caret-color: var(--color-primary);
  padding: 0;
}
.otp-box:focus { border-color: var(--color-primary); box-shadow: 0 0 0 3px var(--color-primary-focus-ring); }
.otp-box.prefilled { background: var(--color-bg-subtle); color: var(--color-text-muted); border-color: var(--color-border); }

/* OTP display boxes — host lobby (div, not input) */
.otp-display { margin-top: 12px; }
.otp-display-box {
  width: 52px;
  height: 56px;
  font-size: 22px;
  font-weight: 700;
  text-align: center;
  line-height: 56px;
  border: 2px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-bg-subtle);
  color: var(--color-text);
  user-select: all;
}

/* Or divider */
.or-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 20px 0;
  color: var(--color-text-faint);
  font-size: 13px;
}
.or-divider::before, .or-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--color-border);
}

/* Ghost button */
.btn-ghost {
  width: 100%;
  padding: 12px;
  background: transparent;
  color: var(--color-primary);
  border: 1.5px solid var(--color-primary);
  border-radius: var(--radius-md);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.btn-ghost:hover { background: var(--color-primary-light); }

/* Buzz button — 3D circular buzzer */
/* Bespoke decorative effect — left as literal colors, not tokenized;
   a future rebrand will likely redesign this wholesale rather than
   recolor it via variables. */
#view-buzzer, #view-position {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.buzz-btn {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: radial-gradient(circle at 38% 32%, #ff6b6b 0%, #dc2626 45%, #7f1d1d 100%);
  color: #fff;
  border: none;
  border-bottom: 8px solid #450a0a;
  box-shadow:
    0 8px 0 #450a0a,
    0 12px 24px rgba(0,0,0,.45),
    inset 0 -4px 8px rgba(0,0,0,.3),
    inset 0 4px 12px rgba(255,255,255,.18);
  font-size: 26px;
  font-weight: 800;
  letter-spacing: .06em;
  cursor: pointer;
  transition: transform .08s ease, box-shadow .08s ease, border-bottom-width .08s ease;
  margin: 16px auto;
}
.buzz-btn:hover:not(:disabled) {
  background: radial-gradient(circle at 38% 32%, #ff8080 0%, #ef4444 45%, #991b1b 100%);
}
.buzz-btn:active:not(:disabled) {
  transform: translateY(6px);
  border-bottom-width: 2px;
  box-shadow:
    0 2px 0 #450a0a,
    0 4px 10px rgba(0,0,0,.35),
    inset 0 -2px 4px rgba(0,0,0,.3),
    inset 0 2px 8px rgba(255,255,255,.12);
}
.buzz-btn:disabled {
  background: radial-gradient(circle at 38% 32%, #d1d5db 0%, #9ca3af 45%, #6b7280 100%);
  border-bottom-color: #374151;
  box-shadow:
    0 8px 0 #374151,
    0 12px 24px rgba(0,0,0,.3),
    inset 0 -4px 8px rgba(0,0,0,.2);
  cursor: not-allowed;
  color: #e5e7eb;
}

.frozen-label {
  font-size: 13px;
  color: var(--color-text-muted);
  margin-top: 4px;
}

/* Buzzed / Others sections */
.queue-section {
  width: 100%;
  margin-top: 20px;
  border-top: 1px solid var(--color-border-subtle);
  padding-top: 14px;
}
.section-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: .06em;
  margin-bottom: 10px;
  text-align: left;
}
.roster-names {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.roster-chip {
  background: var(--color-border-subtle);
  color: var(--color-text-secondary);
  font-size: 13px;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  font-weight: 500;
}

.position-sub { color: var(--color-text-muted); font-size: 14px; }

.buzz-queue-list {
  list-style: none;
  padding: 0;
  margin: 0 0 16px;
  width: 100%;
  text-align: left;
}
.buzz-queue-list li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 18px;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-border-subtle);
  color: var(--color-text-secondary);
}
.buzz-queue-list li.buzz-me { font-weight: 700; font-size: 20px; color: var(--color-text); }

/* ------------------------------------------------------------------ */
/* Host page — shared                                                   */
/* ------------------------------------------------------------------ */
.host-wrap { min-height: 100vh; background: var(--color-bg); }

.host-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 24px;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}
.host-header h1 { font-size: 17px; font-weight: 700; margin: 0; }
.host-header .subtitle { font-size: 12px; color: var(--color-text-faint); margin: 2px 0 0; }

.host-header-actions { display: flex; align-items: center; gap: 10px; }
.present-link {
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-primary);
  border: 1.5px solid var(--color-primary);
  border-radius: var(--radius-sm);
  text-decoration: none;
  white-space: nowrap;
}
.present-link:hover { background: var(--color-primary-light); }

.phase-badge {
  font-size: 12px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  display: flex;
  align-items: center;
  gap: 5px;
}
.phase-badge.lobby { background: var(--color-border-subtle); color: var(--color-text-muted); }
.phase-badge.live  { background: var(--color-success-strong-bg); color: var(--color-success-strong-text); }
.phase-badge.offline { background: var(--color-warning-bg); color: var(--color-warning-text); }

/* Set by host.js while the socket is mid-reconnect — blocks every board/
   sidebar/lobby control at once rather than instrumenting each handler,
   so no action can race the host:join handshake that re-establishes this
   connection's identity server-side (see host.js's disconnect listener). */
.host-wrap.reconnecting #view-lobby,
.host-wrap.reconnecting #view-live { pointer-events: none; opacity: .5; }

/* ------------------------------------------------------------------ */
/* Lobby view                                                           */
/* ------------------------------------------------------------------ */
.lobby-body { max-width: 600px; margin: 40px auto; padding: 0 24px; display: flex; flex-direction: column; gap: 16px; }

.card {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  padding: 20px;
  box-shadow: var(--shadow-card);
}

.card-label { font-size: 12px; color: var(--color-text-faint); margin: 0 0 10px; font-weight: 500; text-transform: uppercase; letter-spacing: .05em; }

.join-url-row { display: flex; gap: 8px; }
.join-url-input {
  flex: 1;
  padding: 10px 12px;
  background: var(--color-bg-subtle);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-family: monospace;
  color: var(--color-text-secondary);
  outline: none;
}
.btn-copy {
  padding: 10px 14px;
  background: var(--color-border-subtle);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
}
.btn-copy:hover { background: var(--color-border); }

.join-url-hint { font-size: 12px; color: var(--color-text-faint); margin: 6px 0 0; }

.players-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
.players-count {
  background: var(--color-info-bg);
  color: var(--color-info-text);
  font-size: 12px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
}

.players-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 16px;
}
.player-item { display: flex; align-items: center; gap: 6px; font-size: 14px; color: var(--color-text-secondary); justify-content: space-between; }
.player-item-name { display: flex; align-items: center; gap: 6px; }
.player-item-name::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--color-text-muted); flex-shrink: 0; }

.btn-remove-player {
  background: none;
  border: none;
  color: var(--color-text-faint);
  font-size: 13px;
  line-height: 1;
  padding: 2px 4px;
  cursor: pointer;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}
.btn-remove-player:hover { color: var(--color-danger); background: var(--color-border-subtle); }

.upload-hint {
  font-size: 12px;
  color: var(--color-text-muted);
  line-height: 1.5;
  margin-bottom: 10px;
}

.file-tree, .file-tree ul {
  list-style: none;
  margin: 0;
  padding-left: 0;
}
.file-tree {
  font-size: 12px;
  color: var(--color-text-muted);
  line-height: 1.8;
  margin-bottom: 10px;
}
.file-tree ul {
  padding-left: 18px;
  margin-left: 6px;
  border-left: 1px solid var(--color-border);
}
.file-tree > li { font-weight: 600; color: var(--color-text-secondary); }
.file-tree-more { font-style: italic; color: var(--color-text-faint); }

.bundle-rules {
  list-style: none;
  margin: 12px 0 14px;
  padding: 0;
}
.bundle-rules li {
  position: relative;
  padding-left: 14px;
  font-size: 12px;
  color: var(--color-text-muted);
  line-height: 1.6;
  margin-bottom: 6px;
}
.bundle-rules li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 7px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--color-text-muted);
}
.bundle-rules code, .file-tree code {
  background: var(--color-border-subtle);
  border: 1px solid var(--color-border);
  color: var(--color-text-secondary);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 11px;
}

#upload-btn { width: 100%; margin-bottom: 4px; }

.upload-alert { border-radius: var(--radius-md); padding: 10px 12px; margin: 8px 0; font-size: 12px; }
.upload-alert-error { background: var(--color-danger-bg); border: 1px solid var(--color-danger-border); }
.upload-alert-warning { background: var(--color-warning-bg); border: 1px solid var(--color-warning-border); }
.upload-alert-title { font-weight: 600; margin: 0 0 6px; }
.upload-alert-error .upload-alert-title { color: var(--color-danger); }
.upload-alert-warning .upload-alert-title { color: var(--color-warning-text); }
.upload-alert-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 200px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}
.upload-alert-list li { line-height: 1.6; color: var(--color-text-secondary); }
.upload-more-btn {
  background: none;
  border: none;
  padding: 0;
  margin-top: 4px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
  color: var(--color-warning-text);
}

.btn-start {
  width: 100%;
  padding: 16px;
  background: var(--color-primary);
  color: var(--color-text-on-primary);
  border: none;
  border-radius: var(--radius-md);
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.btn-start:hover { background: var(--color-primary-hover); }
.start-hint { text-align: center; font-size: 12px; color: var(--color-text-faint); margin-top: 6px; }

/* ------------------------------------------------------------------ */
/* Live view layout                                                     */
/* ------------------------------------------------------------------ */
.live-body {
  display: flex;
  gap: 16px;
  padding: 16px;
  align-items: flex-start;
}

.board-area { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 12px; position: relative; }

/* Board navigation */
.board-nav {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--color-surface);
  border-radius: var(--radius-md);
  padding: 10px 16px;
  box-shadow: var(--shadow-card);
}
.board-nav-label { font-weight: 600; font-size: 14px; flex: 1; text-align: center; }

.board-preview-hint {
  text-align: center;
  font-size: 12px;
  color: var(--color-text-muted);
  margin: 0;
}
.btn-nav {
  padding: 6px 14px;
  background: var(--color-border-subtle);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 13px;
  cursor: pointer;
  font-weight: 500;
}
.btn-nav:hover:not(:disabled) { background: var(--color-border); }
.btn-nav:disabled { opacity: .4; cursor: not-allowed; }

/* Board grid */
.board-grid-wrap {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  padding: 16px;
  box-shadow: var(--shadow-card);
  overflow-x: auto;
}

.board-grid {
  display: grid;
  gap: 8px;
  min-width: max-content;
}

.cell-header {
  padding: 8px 10px;
  text-align: center;
  font-weight: 600;
  font-size: 13px;
  color: var(--color-text-secondary);
  background: var(--color-bg-subtle);
  border-radius: var(--radius-sm);
}

.cell {
  padding: 12px 8px;
  text-align: center;
  border-radius: var(--radius-md);
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  border: 2px solid transparent;
  min-width: 90px;
  min-height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity .1s;
  line-height: 1.3;
}
.cell:hover { opacity: .85; }

.cell-unplayed {
  background: var(--color-surface);
  border-color: var(--color-border);
  color: var(--color-text-secondary);
  font-size: 16px;
  font-weight: 600;
}
.cell-unplayed:hover { border-color: var(--color-primary); }

.cell-awarded {
  background: var(--color-success-bg);
  border-color: var(--color-success-border);
  color: var(--color-success-text);
}

/* At least one genuine negative entry and no positive one — nobody got
   this. An all-zero cell stays .cell-awarded (0 is NA, not a miss). */
.cell-awarded-negative {
  background: var(--color-danger-bg);
  border-color: var(--color-danger-border);
  color: var(--color-danger);
}

.cell-passed {
  background: var(--color-border-subtle);
  border-color: var(--color-border);
  color: var(--color-text-faint);
  font-style: italic;
}

/* Board modal — covers only the board area (see .board-area's
   position: relative), shared by the pre-Start peek and the live reveal
   flow. The board is deliberately dimmed/inert behind it — there's no
   longer a border-highlight equivalent to .cell-scoring on the grid
   itself; the modal's own header is the "which tile" indicator. */
.board-modal-overlay {
  position: absolute;
  inset: 0;
  /* .board-area's own height is content-driven (a small board can be
     quite short) — floor it so the modal always has enough room for a
     typical reveal panel, regardless of how short the board grid is.
     A taller board-area (more categories/rows) still governs when it
     naturally exceeds this floor. 640px comfortably fits the
     question+image+answer+buttons content measured in practice
     (~510-530px) plus a few scoring rows; a large roster still falls
     back to .board-modal's own internal scroll, by design. */
  min-height: 640px;
  background: rgba(17, 17, 17, .55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 5;
  border-radius: var(--radius-lg);
}

.board-modal {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card-strong);
  padding: 24px;
  width: 100%;
  max-width: 640px;
  max-height: 100%;
  overflow-y: auto;
  position: relative;
}

.btn-modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 28px;
  height: 28px;
  border: none;
  background: var(--color-border-subtle);
  border-radius: var(--radius-pill);
  color: var(--color-text-muted);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.btn-modal-close:hover { background: var(--color-border); }

.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 16px;
}
.panel-title { font-size: 15px; font-weight: 700; }
.panel-default { font-size: 12px; color: var(--color-text-faint); }

.panel-player-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-border-subtle);
}
.panel-player-row:last-child { border-bottom: none; }

.panel-player-name { flex: 1; font-size: 14px; }

.score-input {
  width: 80px;
  padding: 7px 10px;
  border: 1px solid var(--color-border-input);
  border-radius: var(--radius-sm);
  font-size: 14px;
  text-align: right;
  outline: none;
}
.score-input:focus { border-color: var(--color-primary); }

.btn-quickfill {
  padding: 6px 10px;
  font-size: 12px;
  font-weight: 600;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  background: var(--color-bg-subtle);
  white-space: nowrap;
}
.btn-quickfill:hover { background: var(--color-border); }

.btn-close-question {
  width: 100%;
  margin-top: 16px;
  padding: 12px;
  background: var(--color-surface);
  color: var(--color-primary);
  border: 1.5px solid var(--color-primary);
  border-radius: var(--radius-md);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.btn-close-question:hover { background: var(--color-primary-light); }

.panel-hint { text-align: center; font-size: 12px; color: var(--color-text-faint); margin-top: 8px; }

.btn-cancel-reveal {
  width: 100%;
  margin-top: 10px;
  padding: 10px;
  background: var(--color-surface);
  color: var(--color-danger);
  border: 1.5px solid var(--color-danger);
  border-radius: var(--radius-md);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.btn-cancel-reveal:hover { background: var(--color-border-subtle); }

/* Pre-Start Q&A peek (reuses .board-modal/.panel-header/.panel-title) */
.peek-question { font-size: 16px; font-weight: 600; margin-bottom: 12px; line-height: 1.4; white-space: pre-line; }
.peek-media-row {
  display: flex;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.peek-media {
  /* flex: 1 1 0% + min-width: 0 is what actually lets multiple images
     share the row — a plain flex child won't shrink an <img> below its
     intrinsic size otherwise, so several images just wrap one-per-row
     instead of packing side by side. */
  flex: 1 1 0%;
  min-width: 0;
  max-width: 100%;
  max-height: 240px;
  object-fit: contain;
  border-radius: var(--radius-md);
}
.peek-answer { font-size: 14px; color: var(--color-text-secondary); padding-top: 12px; margin-bottom: 12px; border-top: 1px solid var(--color-border-subtle); white-space: pre-line; }

/* ------------------------------------------------------------------ */
/* Sidebar                                                              */
/* ------------------------------------------------------------------ */
.sidebar { width: 260px; flex-shrink: 0; display: flex; flex-direction: column; gap: 12px; }

/* Queue */
.queue-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 10px;
}
.queue-title { font-weight: 700; font-size: 14px; }
.queue-gap-label { font-size: 11px; color: var(--color-text-faint); }

.queue-list { list-style: none; margin: 0 0 12px; padding: 0; min-height: 24px; }
.queue-list li { display: flex; justify-content: space-between; align-items: baseline; font-size: 13px; padding: 4px 0; color: var(--color-text-secondary); }
.queue-name { color: var(--color-text-secondary); }

.buzz-delta { font-size: 12px; font-weight: 600; color: var(--color-text-muted); }
.buzz-delta.first { color: var(--color-success-strong-text); }
.queue-empty { color: var(--color-text-faint); font-size: 13px; font-style: italic; margin-bottom: 12px; }

.queue-locked-badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  margin-bottom: 10px;
}

.queue-actions { display: flex; gap: 8px; }
.btn-queue {
  flex: 1;
  padding: 8px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-subtle);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
}
.btn-queue:hover { background: var(--color-border); }

/* Totals */
.totals-title { font-weight: 700; font-size: 14px; margin-bottom: 10px; }
.totals-table { width: 100%; border-collapse: collapse; }
.totals-table th {
  font-size: 11px;
  color: var(--color-text-faint);
  font-weight: 500;
  text-align: right;
  padding: 0 0 6px;
}
.totals-table th:first-child { text-align: left; }
.totals-table td {
  font-size: 13px;
  padding: 5px 0;
  border-top: 1px solid var(--color-border-subtle);
}
.totals-table td:not(:first-child) { text-align: right; font-weight: 600; }
.totals-name { margin-right: 6px; }
.totals-sort-hint { font-size: 11px; color: var(--color-text-faint); margin-top: 6px; text-align: right; }

/* Add player */
.add-player-form { display: flex; gap: 6px; margin-top: 4px; }
.add-player-input {
  flex: 1;
  padding: 8px 10px;
  border: 1px solid var(--color-border-input);
  border-radius: var(--radius-sm);
  font-size: 13px;
  outline: none;
}
.add-player-input:focus { border-color: var(--color-primary); }
.add-player-input::placeholder { color: var(--color-text-faint); }
.btn-add-player {
  padding: 8px 12px;
  background: var(--color-border-subtle);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.btn-add-player:hover { background: var(--color-border); }

/* ------------------------------------------------------------------ */
/* Presentation view                                                    */
/* ------------------------------------------------------------------ */
.present-wrap {
  min-height: 100vh;
  background: var(--color-bg);
  padding: 16px;
  display: flex;
  flex-direction: column;
}

.present-header { text-align: center; margin-bottom: 16px; }
.present-board-label { font-size: clamp(16px, 2.2vh, 30px); font-weight: 700; color: var(--color-text); }

/* Presentation is always a dedicated full-screen display, so the stage and
   its sidebar scale to fill the viewport (vh/vw-based) instead of a small
   fixed cap — the host shouldn't need to zoom the browser to make this
   readable (zooming also zooms the control center, since browsers persist
   zoom per-origin, not per-tab). */
.present-layout {
  display: flex;
  gap: 16px;
  align-items: stretch;
  width: 96vw;
  height: 92vh;
  margin: 0 auto;
}

/* Outer stage cell: just centers the fixed-ratio box below within whatever
   space flexbox gives it. Sizing lives entirely on .present-stage-box —
   letting a flex item be simultaneously width:auto/height:auto *and*
   aspect-ratio-constrained does not reliably resolve across engines, so
   the ratio box is a plain (non-flex-item) child instead. */
.present-stage {
  flex: 1;
  min-width: 0;
  height: 100%;
  display: grid;
  place-items: center;
  overflow: hidden;
}

.present-stage-box {
  position: relative;
  width: 100%;
  height: auto;
  max-height: 100%;
  aspect-ratio: 16 / 9;
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 24px;
  display: flex;
  flex-direction: column;
  overflow: auto;
}

.present-board-slide { height: 100%; width: 100%; display: flex; align-items: center; justify-content: center; }
.present-board-slide .board-grid-wrap { box-shadow: none; padding: 0; background: transparent; width: 100%; }

.present-question-slide,
.present-answer-slide {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: left;
  gap: 16px;
}

.reviewing-badge {
  position: absolute;
  top: 12px;
  right: 12px;
  font-size: 11px;
  font-weight: 600;
  background: var(--color-warning-bg);
  color: var(--color-warning-text);
  padding: 4px 10px;
  border-radius: var(--radius-pill);
}

.present-question-text {
  /* Lower ceiling than a raw vh-scale would give — a short question
     reading at 64px dominated the whole stage regardless of how little
     text there was. fitSlideText (present.js) still shrinks further for
     anything long enough to overflow even at this smaller cap. */
  font-size: clamp(24px, 4vh, 44px);
  font-weight: 500;
  color: var(--color-text);
  max-width: 90%;
  white-space: pre-line;
}

.present-question-media {
  max-width: 80%;
  max-height: 40%;
  display: flex;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}
.present-media {
  /* Same flex-shrink fix as .peek-media — see its comment. */
  flex: 1 1 0%;
  min-width: 0;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: var(--radius-md);
}

.present-answer {
  font-size: clamp(22px, 4vh, 52px);
  font-weight: 500;
  color: var(--color-success-strong-text);
  max-width: 90%;
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  white-space: pre-line;
  transition: opacity .4s ease, max-height .4s ease;
}
.present-answer.answer-shown { opacity: 1; max-height: 60vh; }

/* Dedicated answer slide — the question and its media do not persist here
   (see present.js's renderAnswerSlide): shown full-stage whenever the
   answer carries its own image, or the answer wouldn't fit inline. */
.present-answer-slide-text {
  font-size: clamp(32px, 7vh, 88px);
  font-weight: 500;
  color: var(--color-success-strong-text);
  max-width: 90%;
  white-space: pre-line;
}

.present-answer-slide-media {
  max-width: 85%;
  max-height: 70%;
  display: flex;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Set by present.js's fitSlideText when content still doesn't fit even at
   the minimum font size (question or answer slide). Centered content that
   overflows a scrollable box has its start silently cut off — scrollTop
   can't go negative — so this switches to top-anchored, keeping the whole
   slide reachable by scrolling. */
.present-question-slide.overflowing,
.present-answer-slide.overflowing { justify-content: flex-start; }

.present-sidebar {
  width: clamp(220px, 18vw, 420px);
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow-y: auto;
}

@media (max-width: 900px) {
  .present-layout { flex-direction: column; height: auto; }
  .present-stage { width: 100%; height: auto; }
  .present-stage-box { max-height: none; }
  .present-sidebar { width: 100%; }
}

/* ------------------------------------------------------------------ */
/* Responsive — mobile + tablet (≤ 1024px)                             */
/* Stack sidebar above board; full-width cards                         */
/* ------------------------------------------------------------------ */
@media (max-width: 1024px) {
  /* Header */
  .host-header { padding: 10px 14px; }
  .host-header h1 { font-size: 14px; }

  /* Lobby */
  .lobby-body { margin: 16px auto; padding: 0 12px; gap: 12px; }

  /* Live view — stack vertically, sidebar above board */
  .live-body { flex-direction: column; padding: 10px; gap: 10px; }
  .sidebar { width: 100%; order: -1; }

  /* Add player — wrap button below input if it doesn't fit */
  .add-player-form { flex-wrap: wrap; }
  .btn-add-player { flex-shrink: 0; }

  /* Scoring panel — wrap player row to two lines */
  .panel-player-row { flex-wrap: wrap; gap: 6px; }
  .panel-player-name { width: 100%; }
  .score-input { width: 90px; }
}

/* ------------------------------------------------------------------ */
/* Responsive — tablet only (641px – 1024px)                           */
/* Cap stacked layout at 720px centered                                */
/* ------------------------------------------------------------------ */
@media (min-width: 641px) and (max-width: 1024px) {
  .live-body { max-width: 720px; margin: 0 auto; }
  .lobby-body { max-width: 720px; }
}

/* ------------------------------------------------------------------ */
/* Responsive — mobile only (≤ 640px)                                  */
/* ------------------------------------------------------------------ */
@media (max-width: 640px) {
  /* Board cells — smaller, still scrollable */
  .cell { min-width: 64px; min-height: 40px; font-size: 11px; padding: 8px 4px; }
  .cell-unplayed { font-size: 13px; }
}

/* ================================================================
   Summary view (/summary/<code>/<token>)
   ================================================================ */

.summary-wrap {
  min-height: 100vh;
  background: var(--color-bg);
  padding: 24px 16px;
  max-width: 900px;
  margin: 0 auto;
}
.summary-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}
.summary-body { display: flex; flex-direction: column; gap: 20px; }

/* Type scale — scoped to this page on purpose.
   .card-label, .subtitle and .totals-table are shared with the control center
   and presentation view, where they sit in a dense sidebar and are tuned to
   stay quiet. This page is wide, sparse and read at a distance, so it needs
   more contrast between a heading and the sentence explaining it. Overriding
   here rather than editing the shared rules keeps the other two pages exactly
   as they are. */
.summary-wrap h1 { margin: 0; font-size: 24px; font-weight: 700; letter-spacing: -.01em; }
/* .subtitle is defined only as `.host-header .subtitle`, so on this page it
   matched nothing and fell back to body's 14px near-black — louder than every
   section heading beneath it. */
.summary-wrap .subtitle { font-size: 13px; color: var(--color-text-muted); margin: 3px 0 0; }
.summary-wrap .card-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text-secondary);
  letter-spacing: .06em;
  margin: 0;
}
.summary-wrap .totals-table th {
  font-size: 12px;
  color: var(--color-text-muted);
  padding-bottom: 8px;
}
.summary-wrap .totals-table td { font-size: 14px; padding: 8px 0; }

/* Heading and its note form one column; an action button is a sibling column,
   so the note can never flow underneath it. */
.summary-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 16px;
}
.summary-card-head-text { min-width: 0; }

/* Connection status, not quiz state — it previously borrowed .phase-badge,
   the control center's lobby/live chip, which read as a claim about the quiz
   on a page titled "Quiz Summary". */
.summary-live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--color-text-muted);
  white-space: nowrap;
}
.summary-live::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-success-strong-text);
}
.summary-live.offline { color: var(--color-warning-text); }
.summary-live.offline::before { background: var(--color-warning-text); }
.summary-empty {
  color: var(--color-text-muted);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 32px 20px;
  text-align: center;
  margin: 0;
}
.summary-empty-inline { color: var(--color-text-muted); font-size: 13px; margin: 10px 0 0; }
.summary-note {
  color: var(--color-text-muted);
  font-size: 13px;
  line-height: 1.55;
  margin: 6px 0 0;
  max-width: 64ch;
}

/* The shared .totals-table right-aligns every column but the first. That fits
   the buzz table as-is; standings lead with a rank column, so the name beside
   it has to be pulled back to the left. */
.summary-standings td:nth-child(2),
.summary-standings th:nth-child(2) { text-align: left; font-weight: 500; }
.summary-rank-col { width: 2.5em; text-align: left !important; color: var(--color-text-faint); font-weight: 600 !important; }
/* tbody, not tr:first-child — the latter also matches the header row, which
   painted the "#" column heading as though it were the winner. */
.summary-standings tbody tr:first-child .summary-rank-col { color: var(--color-primary); }
.summary-total { font-variant-numeric: tabular-nums; }

.summary-buzz { font-variant-numeric: tabular-nums; }
.summary-of { color: var(--color-text-faint); font-weight: 400; }
.summary-row-idle td { color: var(--color-text-faint); }

/* A wide table on a phone scrolls inside its own box rather than pushing the
   page sideways. */
.summary-table-scroll { overflow-x: auto; }

@media (max-width: 600px) {
  .summary-header { flex-direction: column; gap: 8px; }
  .summary-buzz { min-width: 460px; }
  /* Side by side, the button starves the note into a five-line column. Stack
     them; the toggle then sits directly above the chart it controls. */
  .summary-card-head { flex-direction: column; gap: 12px; }
  .chart-toggle { align-self: flex-start; }
}

/* Chart — hand-rolled SVG (no charting library; SPEC.md §11).
   Chrome/ink values are the data-viz reference instance's light column; the
   series hues live in summary.js, where the slot order is the CVD-safety
   mechanism and must stay fixed. */
/* .btn-nav is the repo's small secondary button (board prev/next). Here it sits
   beside a heading rather than in a control strip, so it loses the grey fill
   and takes it back on hover. */
.chart-toggle {
  flex: none;
  background: transparent;
  color: var(--color-text-secondary);
}
.chart-toggle:hover { background: var(--color-border-subtle); }
.chart-wrap { position: relative; }
.chart-svg { width: 100%; height: auto; display: block; overflow: visible; }

.chart-grid { stroke: #e1e0d9; stroke-width: 1; }
.chart-grid-zero { stroke: #c3c2b7; }
.chart-tick { fill: #898781; font-size: 11px; font-variant-numeric: tabular-nums; }
.chart-tick-y { text-anchor: end; dominant-baseline: middle; }
.chart-tick-x { text-anchor: middle; }
.chart-axis-title { fill: #898781; font-size: 11px; text-anchor: middle; }

.chart-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
/* A 2px surface ring keeps overlapping points readable where lines cross. */
.chart-dot { stroke: var(--color-surface); stroke-width: 2; }

.chart-end-label { fill: var(--color-text); font-size: 12px; dominant-baseline: middle; }
.chart-end-value { fill: var(--color-text-muted); font-variant-numeric: tabular-nums; }

.chart-crosshair { stroke: var(--color-text-faint); stroke-width: 1; stroke-dasharray: 3 3; }
.chart-hit { fill: transparent; }

.chart-legend {
  display: flex; flex-wrap: wrap; gap: 6px 16px;
  margin-top: 12px; font-size: 12px; color: var(--color-text-secondary);
}
#chart-table:not(.hidden) { margin-top: 16px; border-top: 1px solid var(--color-border-subtle); padding-top: 12px; }
.chart-legend-item { display: inline-flex; align-items: center; gap: 6px; }
.chart-legend-swatch { width: 10px; height: 10px; border-radius: 2px; flex: none; }
.chart-legend-dashed { opacity: .55; }

.chart-tooltip {
  position: absolute; top: 8px; z-index: 2; pointer-events: none;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card-strong);
  padding: 8px 10px; font-size: 12px; min-width: 150px;
}
.chart-tooltip-title { color: var(--color-text-muted); margin-bottom: 6px; font-size: 11px; }
.chart-tooltip-row { display: flex; align-items: center; gap: 6px; line-height: 1.7; }
.chart-tooltip-name { flex: 1; color: var(--color-text); }
.chart-tooltip-value { font-variant-numeric: tabular-nums; font-weight: 600; }

@media (max-width: 700px) {
  /* Scaling an 820-wide plot into a phone makes the tick labels unreadable.
     Scroll it instead, the same way wide tables and the board grid do. */
  .chart-wrap { overflow-x: auto; }
  .chart-svg { min-width: 620px; }
}

@media (max-width: 600px) {
  /* Touch has no hover; the table view is the way in on a phone. */
  .chart-tooltip { display: none; }
}
