:root {
  --bg: #11130f;
  --panel: #1d1d20;
  --panel-2: #27262b;
  --line: #3a383f;
  --ink: #e8ecf4;
  --muted: #a0a49e;
  --accent: #ffb648;
  --danger: #ff6b6b;
  --ok: #6fcf7f;
  --range: #ff8a4c;
}

* { box-sizing: border-box; }

/* The `hidden` attribute is only a UA-stylesheet `display: none`, so any rule
   here that sets a display (.overlay, .who) would silently outrank it and keep
   the element on screen. Make the attribute win everywhere. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  min-height: 100vh;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 20px;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}
.brand { font-weight: 700; letter-spacing: 0.3px; }
.brand .bomb { margin-right: 6px; }
.top-actions,
.who { display: flex; gap: 12px; align-items: center; color: var(--muted); font-size: 13px; }

h1 { font-size: 22px; margin: 0 0 6px; }
h2 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); margin: 20px 0 8px; }

.panel {
  max-width: 860px;
  margin: 40px auto;
  padding: 28px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.muted { color: var(--muted); font-size: 13px; }
.error { color: var(--danger); font-size: 13px; margin-top: 12px; }

label { display: block; margin: 14px 0; font-size: 13px; color: var(--muted); }
input,
textarea,
select {
  display: block;
  width: 100%;
  margin-top: 5px;
  padding: 9px 11px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 7px;
  color: var(--ink);
  font: inherit;
}
textarea {
  min-height: 130px;
  resize: vertical;
}
input:focus,
textarea:focus,
select:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

button {
  padding: 9px 15px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--panel-2);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
button:hover { border-color: var(--muted); }
button.primary { background: var(--accent); border-color: var(--accent); color: #1a1400; font-weight: 600; }
button.link { background: none; border: none; color: var(--muted); text-decoration: underline; padding: 0; }
.row { display: flex; gap: 10px; margin-top: 18px; }
.account-box {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
.account-box summary {
  color: var(--muted);
  cursor: pointer;
  font-size: 13px;
}

.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(8, 10, 12, 0.72);
}
.modal-panel {
  width: min(100%, 460px);
  margin: 0;
  padding: 22px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
}
.modal-head,
.admin-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.admin-panel {
  max-width: 980px;
}
.admin-auth {
  margin: 18px 0 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}
.feedback-list {
  display: grid;
  gap: 10px;
}
.feedback-item {
  padding: 12px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
}
.feedback-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  margin-bottom: 8px;
  color: var(--muted);
  font: 12px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
}
.feedback-message {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.lobby-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; }
.share { display: flex; gap: 8px; margin: 10px 0; }
.share input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
.share.small input { font-size: 11px; }
.rooms { list-style: none; padding: 0; margin: 0; }
.rooms li {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 7px;
  margin-bottom: 6px;
  font-size: 13px;
}
.rooms button { padding: 3px 10px; font-size: 12px; }

.game-wrap {
  display: flex;
  gap: 24px;
  padding: 24px;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: wrap;
}
.stage { position: relative; }
canvas {
  background: #0e1014;
  border: 1px solid var(--line);
  border-radius: 8px;
  display: block;
  /* The art is smooth cartoon rather than pixel art, so let the browser
     filter it when the board is scaled down to fit a narrow window. */
  image-rendering: auto;
  max-width: 100%;
}
.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(10, 12, 16, 0.72);
  border-radius: 8px;
  font-size: 26px;
  font-weight: 700;
  text-align: center;
  padding: 20px;
}
.player-hud {
  position: absolute;
  inset: 8px;
  pointer-events: none;
}

/* Connection readout. Top centre is the one part of the stage the four corner
   HUD cards leave alone. */
.net-hud {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(12, 15, 20, 0.72);
  border: 1px solid var(--line);
  font: 600 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.03em;
  color: #cfd8e6;
  pointer-events: none;
  white-space: nowrap;
}
.net-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #6b7280;
}
.net-hud.good .net-dot { background: #6ee7a8; box-shadow: 0 0 6px rgba(110, 231, 168, 0.7); }
.net-hud.fair .net-dot { background: #ffd166; box-shadow: 0 0 6px rgba(255, 209, 102, 0.6); }
.net-hud.poor .net-dot { background: #ff6b6b; box-shadow: 0 0 6px rgba(255, 107, 107, 0.6); }
.net-hud.poor { color: #ffb4b4; }
.net-hud.lost { color: #ffb4b4; border-color: rgba(255, 107, 107, 0.55); }
.net-hud.lost .net-dot { background: #ff6b6b; animation: netBlink 0.8s steps(2, end) infinite; }
@keyframes netBlink { 50% { opacity: 0.2; } }

.stat-chip.ping { color: #9fb0c6; }
.stat-chip.ping.fair { color: #ffd166; }
.stat-chip.ping.poor { color: #ff8f8f; }
.hud-card {
  position: absolute;
  min-width: 142px;
  max-width: min(44%, 190px);
  padding: 7px 8px;
  background: rgba(13, 14, 16, 0.76);
  border: 1px solid rgba(232, 236, 244, 0.2);
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.24);
}
.hud-card.slot-0 { top: 0; left: 0; }
.hud-card.slot-1 { top: 0; right: 0; text-align: right; }
.hud-card.slot-2 { bottom: 0; left: 0; }
.hud-card.slot-3 { right: 0; bottom: 0; text-align: right; }
.hud-card.dead { opacity: 0.72; border-color: rgba(130, 226, 255, 0.45); }
.hud-name {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-weight: 700;
  font-size: 12px;
  line-height: 1.1;
}
.slot-1 .hud-name,
.slot-3 .hud-name { justify-content: flex-end; }
.hud-dot {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  flex: none;
}
.hud-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hud-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 7px;
  margin-top: 5px;
  color: var(--muted);
  font: 700 10px/1.2 ui-monospace, SFMono-Regular, Menlo, monospace;
}
.slot-1 .hud-stats,
.slot-3 .hud-stats { justify-content: flex-end; }
.hud-stats .hot { color: var(--range); }
.hud-stats .phase { color: #82e2ff; }
.hud-stats .weapon { color: var(--accent); }

.side {
  width: 300px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 18px;
}
/* Three links plus the room code do not fit across 300px, so the actions drop
   to their own line rather than pushing `leave` off the edge of the panel. */
.room-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: 10px; }
.head-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px 10px; margin-left: auto; }
.room-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 20px; letter-spacing: 2px; }

.loadout {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  margin: 12px 0 2px;
}
.stat {
  min-width: 0;
  padding: 7px 8px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 7px;
}
.stat .label {
  display: block;
  color: var(--muted);
  font-size: 10px;
  line-height: 1;
  text-transform: uppercase;
}
.stat .value {
  display: block;
  margin-top: 4px;
  color: var(--ink);
  font: 700 15px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
}

.scoreboard { list-style: none; padding: 0; margin: 0; }
.scoreboard li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.scoreboard .dot { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.scoreboard .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.scoreboard .stats {
  display: flex;
  gap: 5px;
  color: var(--muted);
  font-size: 11px;
  font-family: ui-monospace, Menlo, monospace;
  white-space: nowrap;
}
.scoreboard .stat-chip { color: var(--ink); }
.scoreboard .stat-chip.range { color: var(--range); }
.scoreboard .stat-chip.speed { color: var(--ok); }
.scoreboard .stat-chip.phase { color: #82e2ff; }
.scoreboard .stat-chip.weapon { color: var(--accent); }
.scoreboard .dead { opacity: 0.45; }
.scoreboard .bot { color: var(--muted); font-size: 11px; }
.bots { display: flex; gap: 8px; margin-top: 10px; }
.bots button { flex: 1; padding: 5px 8px; font-size: 12px; }

.modes-panel {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-bottom: 8px;
}
.mode-btn {
  padding: 7px 10px;
  font-size: 12px;
  border-radius: 7px;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--muted);
  cursor: pointer;
  transition: all 0.2s ease;
  text-align: center;
}
.mode-btn.active {
  background: var(--panel-2);
  color: var(--ink);
  border-color: var(--accent);
  box-shadow: 0 0 8px rgba(255, 182, 72, 0.18);
}
.mode-btn:hover {
  border-color: var(--muted);
}

.chat {
  height: 130px;
  overflow-y: auto;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 8px;
  font-size: 12.5px;
}
.chat div { margin-bottom: 3px; word-wrap: break-word; }
.chat .sys { color: var(--muted); font-style: italic; }
.chat .from { color: var(--accent); }
#chatForm { margin-top: 8px; }
.keys { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 12px; }

.touch-controls {
  display: none;
  width: min(100%, 600px);
  justify-content: space-between;
  align-items: end;
  gap: 20px;
}
.touch-controls button {
  width: 58px;
  height: 58px;
  padding: 0;
  border-radius: 8px;
  font-size: 24px;
  line-height: 1;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.touch-controls button.active {
  border-color: var(--accent);
  background: #3a3020;
}
.dpad {
  display: grid;
  grid-template-columns: repeat(3, 58px);
  grid-template-rows: repeat(3, 58px);
  gap: 6px;
}
.touch-up { grid-column: 2; grid-row: 1; }
.touch-left { grid-column: 1; grid-row: 2; }
.touch-down { grid-column: 2; grid-row: 3; }
.touch-right { grid-column: 3; grid-row: 2; }
.touch-bomb {
  flex: none;
  width: 74px !important;
  height: 74px !important;
  border-color: var(--range);
  background: #34231d;
}

/* Fullscreen. The class is set from JS on <body> so the same rules serve both
   the real Fullscreen API and the fill-the-window fallback when it is refused.
   The canvas keeps its fixed backing store (cols*TILE) and is only scaled by
   CSS, so nothing in the render loop has to know about any of this. */
body.fs #gameView {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--bg);
  overflow: auto;
}
body.fs .game-wrap {
  height: 100vh;
  padding: 16px;
  align-items: center;
  flex-wrap: nowrap;
}
body.fs canvas {
  /* `height`, not `max-height`: the canvas is 600x520 of backing store and a
     maximum can only ever shrink it, which is why the board just sat there at
     its natural size with half the screen empty. Width follows the aspect ratio,
     and the max-width — the screen less the side panel and the gaps around it —
     hands the height back when the board would otherwise run under the panel. */
  height: calc(100vh - 32px);
  width: auto;
  max-width: calc(100vw - 372px);
}
body.fs .side {
  max-height: calc(100vh - 32px);
  overflow-y: auto;
}

@media (max-width: 700px) {
  .lobby-grid { grid-template-columns: 1fr; }
  .game-wrap { padding: 12px; gap: 12px; }
  .side { width: 100%; }
  .loadout { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .player-hud { inset: 5px; }
  .hud-card { min-width: 118px; max-width: 48%; padding: 6px; }
  .hud-stats { gap: 3px 5px; font-size: 9px; }
  /* Too narrow to keep the board and the panel side by side: let them stack
     and scroll rather than squeezing the board into a sliver. */
  body.fs .game-wrap { height: auto; min-height: 100vh; flex-wrap: wrap; }
  body.fs canvas { height: auto; max-height: 70vh; max-width: 100%; }
  body.fs .side { max-height: none; }
}

@media (pointer: coarse), (max-width: 700px) {
  .touch-controls { display: flex; }
  .keys { display: none; }
}
