/* Arcade UI: chunky, high-contrast, readable at a glance. */

:root {
  --ink: #10131a;
  --paper: #f6f8fc;
  --accent: #ffd23f;
  --accent-2: #23c9d6;
  --green: #35d06a;
  --yellow: #ffd23f;
  --red: #ff4d4d;
  --panel: rgba(16, 19, 26, 0.88);
  --shadow: 0 10px 0 rgba(0, 0, 0, 0.28);
  --font: 'Trebuchet MS', 'Verdana', system-ui, sans-serif;
}

* { box-sizing: border-box; }

/* `hidden` must win over any layout display we set on these panels. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: #0d1016;
  font-family: var(--font);
  color: var(--paper);
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}

#game {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

#ui {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
#ui .layer { position: absolute; inset: 0; }
#ui button, #ui .clickable { pointer-events: auto; }

/* ============================================================ HUD ========= */

#scoreboard {
  position: absolute;
  top: 18px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 20px;
  background: var(--panel);
  border-radius: 14px;
  border: 3px solid rgba(255, 255, 255, 0.16);
  box-shadow: var(--shadow);
  letter-spacing: 0.06em;
}

#scoreboard .side {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 150px;
}
#scoreboard .side.right { justify-content: flex-end; }

#scoreboard .tag {
  font-size: 15px;
  font-weight: bold;
  opacity: 0.82;
  text-transform: uppercase;
  max-width: 130px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

#scoreboard .pts {
  font-size: 40px;
  font-weight: bold;
  line-height: 1;
  min-width: 46px;
  text-align: center;
  text-shadow: 0 3px 0 rgba(0, 0, 0, 0.5);
  transition: transform 90ms ease-out;
}
#scoreboard .pts.bump { transform: scale(1.35); color: var(--accent); }

#scoreboard .vs {
  font-size: 12px;
  opacity: 0.6;
  letter-spacing: 0.14em;
  min-width: 74px;
  text-align: center;
}

/* Little dot marking who is serving. */
#scoreboard .serve-dot {
  font-size: 16px;
  color: var(--accent);
  opacity: 0;
  transition: opacity 150ms;
}
#scoreboard .serve-dot.on { opacity: 1; }

/* Big centred rally callouts: OUT!, NET!, ACE!, KITCHEN! */
#callout {
  position: absolute;
  top: 30%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.6);
  font-size: 62px;
  font-weight: bold;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  text-shadow: 0 6px 0 rgba(0, 0, 0, 0.45), 0 0 30px rgba(255, 210, 63, 0.4);
  opacity: 0;
  white-space: nowrap;
}
#callout.show {
  animation: pop 1000ms cubic-bezier(0.16, 1.4, 0.4, 1) forwards;
}
@keyframes pop {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.5) rotate(-6deg); }
  18%  { opacity: 1; transform: translate(-50%, -50%) scale(1.12) rotate(2deg); }
  30%  { transform: translate(-50%, -50%) scale(1) rotate(0deg); }
  78%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -54%) scale(1.02); }
}

#serve-prompt {
  position: absolute;
  bottom: 96px;
  left: 50%;
  transform: translateX(-50%);
  padding: 9px 22px;
  border-radius: 12px;
  background: var(--panel);
  border: 2px solid rgba(255, 255, 255, 0.18);
  font-size: 14px;
  letter-spacing: 0.16em;
  animation: promptPulse 1.4s ease-in-out infinite;
}
#serve-prompt b { color: var(--accent); }
@keyframes promptPulse {
  0%, 100% { opacity: 0.75; transform: translateX(-50%) scale(1); }
  50%      { opacity: 1;    transform: translateX(-50%) scale(1.04); }
}

/* ------------------------------------------------------- serve meter ----- */

#serve-meter {
  position: absolute;
  bottom: 92px;
  left: 50%;
  transform: translateX(-50%);
  width: min(520px, 68vw);
  text-align: center;
}

/* The OPPONENT's serve meter. Moved to their end of the court and visibly
   demoted — smaller, dimmer, desaturated — so at a glance it is obviously
   something being done TO you rather than a prompt for you to act on. */
#serve-meter.theirs {
  bottom: auto;
  top: 86px;                 /* clear of the scoreboard at top: 18px */
  width: min(380px, 52vw);
  opacity: 0.72;
  filter: saturate(0.55);
}
#serve-meter.theirs .meter-track {
  height: 20px;
  border-width: 2px;
  border-color: rgba(255, 255, 255, 0.5);
}
#serve-meter.theirs .meter-hint {
  letter-spacing: 0.16em;
  opacity: 0.85;
}

.meter-track {
  position: relative;
  height: 30px;
  border-radius: 15px;
  overflow: hidden;
  border: 3px solid rgba(255, 255, 255, 0.85);
  box-shadow: var(--shadow), inset 0 -4px 0 rgba(0, 0, 0, 0.25);
  display: flex;
  background: #1b1f28;
}

/* Zone widths are set from JS so accuracy upgrades can widen the green band. */
.meter-track .zone { height: 100%; }
.meter-track .zone.red { background: #b93a3a; }
.meter-track .zone.yellow { background: #d9a72e; }
.meter-track .zone.green { background: var(--green); box-shadow: inset 0 0 14px rgba(255,255,255,0.35); }

.meter-track .needle {
  position: absolute;
  top: -2px;
  bottom: -2px;
  width: 6px;
  margin-left: -3px;
  background: var(--paper);
  border-radius: 3px;
  box-shadow: 0 0 10px rgba(255, 255, 255, 0.9);
}

.meter-hint {
  margin-top: 7px;
  font-size: 13px;
  letter-spacing: 0.16em;
  opacity: 0.8;
  text-shadow: 0 2px 4px #000;
}

/* ---------------------------------------------------------- shot bar ----- */

#shot-bar {
  position: absolute;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
}
#shot-bar .key {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border-radius: 10px;
  background: var(--panel);
  border: 2px solid rgba(255, 255, 255, 0.16);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
#shot-bar .key b {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  border-radius: 5px;
  background: var(--paper);
  color: var(--ink);
  font-size: 12px;
}
#shot-bar .key.locked { opacity: 0.35; }
#shot-bar .key.armed { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(255,210,63,0.35); }

/* --------------------------------------------------- instant replay ----- */

/* Live HUD steps aside while a replay is cut in. */
#hud.replay-mode #scoreboard,
#hud.replay-mode #shot-bar,
#hud.replay-mode #serve-prompt,
#hud.replay-mode #callout { display: none; }

#replay-banner {
  position: absolute;
  inset: 0;
  pointer-events: none;
  animation: replayIn 260ms ease-out;
}
/* Letterbox bars sell it as a replay cut rather than a camera glitch. */
#replay-banner::before,
#replay-banner::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  height: 8vh;
  background: #05070a;
}
#replay-banner::before { top: 0; }
#replay-banner::after { bottom: 0; }

#replay-banner .rec {
  position: absolute;
  top: calc(8vh + 18px);
  left: 32px;
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 14px;
  font-weight: bold;
  letter-spacing: 0.22em;
  text-shadow: 0 2px 6px #000;
}
#replay-banner .rec .dot {
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--red);
  box-shadow: 0 0 10px var(--red);
  animation: recBlink 1s steps(2, start) infinite;
}
@keyframes recBlink { 50% { opacity: 0.15; } }

#replay-banner .verdict {
  position: absolute;
  bottom: calc(8vh + 20px);
  left: 50%;
  transform: translateX(-50%);
  padding: 10px 26px;
  border-radius: 12px;
  background: rgba(10, 12, 16, 0.85);
  border: 2px solid var(--red);
  font-size: 20px;
  font-weight: bold;
  letter-spacing: 0.14em;
  white-space: nowrap;
}
#replay-banner .verdict b { color: var(--red); font-size: 26px; }

/* A ball that caught the line reads green — the opposite verdict, same drama. */
#replay-banner.in .verdict { border-color: var(--green); }
#replay-banner.in .verdict b { color: var(--green); }

@keyframes replayIn { from { opacity: 0; } to { opacity: 1; } }

/* ========================================================== SCREENS ====== */

#screen {
  display: flex;
  /* `safe` matters on short viewports: a panel taller than the screen would
     otherwise centre itself, overflow both ways, and put its own title above
     scrollTop 0 where nothing can reach it. Plain `center` is the fallback. */
  align-items: center;
  align-items: safe center;
  justify-content: center;
  background: radial-gradient(circle at 50% 35%, rgba(14, 26, 42, 0.68), rgba(8, 10, 14, 0.88));
  backdrop-filter: blur(3px);
  pointer-events: auto;
  overflow-y: auto;
  padding: 24px;
}

.panel {
  width: min(760px, 94vw);
  background: var(--panel);
  border: 4px solid rgba(255, 255, 255, 0.14);
  border-radius: 22px;
  box-shadow: 0 18px 0 rgba(0, 0, 0, 0.35);
  padding: 26px 30px 30px;
  text-align: center;
  animation: panelIn 260ms cubic-bezier(0.16, 1.3, 0.4, 1);
}
@keyframes panelIn {
  from { opacity: 0; transform: translateY(18px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

.panel h1 {
  margin: 0 0 4px;
  font-size: clamp(30px, 4.4vh, 46px);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-shadow: 0 5px 0 rgba(0, 0, 0, 0.45);
}
.panel h1.win  { color: var(--green); }
.panel h1.lose { color: var(--red); }
.panel h2 { margin: 22px 0 10px; font-size: 17px; letter-spacing: 0.14em; text-transform: uppercase; opacity: 0.72; }
.panel .sub { margin: 0 0 18px; opacity: 0.75; font-size: 15px; line-height: 1.5; }

.btn {
  font-family: var(--font);
  font-size: 18px;
  font-weight: bold;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 13px 26px;
  margin: 6px;
  border-radius: 12px;
  border: none;
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 5px 0 #9aa3b2;
  cursor: pointer;
  transition: transform 70ms, box-shadow 70ms, background 120ms;
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 7px 0 #9aa3b2; }
.btn:active { transform: translateY(3px); box-shadow: 0 2px 0 #9aa3b2; }
.btn.primary { background: var(--accent); box-shadow: 0 5px 0 #b8912a; }
.btn.primary:hover { box-shadow: 0 7px 0 #b8912a; }
.btn.primary:active { box-shadow: 0 2px 0 #b8912a; }
.btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; box-shadow: 0 5px 0 #9aa3b2; }

.row { display: flex; justify-content: center; flex-wrap: wrap; gap: 4px; }

/* ------------------------------------------------------ title screen ----- */

.title-logo {
  font-size: clamp(44px, 9vw, 92px);
  line-height: 0.94;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin: 0;
  color: var(--accent);
  text-shadow: 0 7px 0 #8a6a12, 0 12px 26px rgba(0, 0, 0, 0.6);
}
.title-logo .small { display: block; font-size: 0.34em; color: var(--paper); letter-spacing: 0.36em; text-shadow: 0 3px 0 rgba(0,0,0,0.5); }

.controls-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
  margin: 4px 0 6px;
  font-size: 13px;
  opacity: 0.85;
}
.controls-grid div { background: rgba(255,255,255,0.06); border-radius: 8px; padding: 8px; }
.controls-grid b { color: var(--accent); }

/* --------------------------------------------------------- campaign ----- */

/* The ladder scrolls inside the panel so the heading and the buttons below it
   are always reachable, however many opponents the roster grows to. */
.ladder {
  display: grid;
  gap: 6px;
  margin-bottom: 12px;
  text-align: left;
  max-height: min(46vh, 400px);
  overflow-y: auto;
  padding-right: 4px;
}
.ladder::-webkit-scrollbar { width: 8px; }
.ladder::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.18); border-radius: 4px; }

.opp-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-radius: 11px;
  background: rgba(255, 255, 255, 0.06);
  border: 2px solid transparent;
}
.opp-row.current { border-color: var(--accent); background: rgba(255, 210, 63, 0.12); }
.opp-row.beaten { opacity: 0.55; }
.opp-row.locked { opacity: 0.32; }
.opp-row .face {
  width: 32px; height: 32px; flex: 0 0 32px;
  border-radius: 9px;
  display: grid; place-items: center;
  font-size: 17px;
  background: #2a3140;
}
.opp-row .who { flex: 1; min-width: 0; }
.opp-row .who .name { font-weight: bold; font-size: 15px; letter-spacing: 0.04em; }
.opp-row .who .style {
  font-size: 11.5px; opacity: 0.7;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.opp-row .diff { font-size: 11px; letter-spacing: 0.1em; opacity: 0.8; text-align: right; }
.opp-row .diff .stars { color: var(--accent); font-size: 13px; letter-spacing: 1px; }

/* --------------------------------------------------------- upgrades ----- */

.sp-banner {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 20px;
  border-radius: 999px;
  background: rgba(255, 210, 63, 0.16);
  border: 2px solid var(--accent);
  font-size: 20px;
  font-weight: bold;
  margin-bottom: 12px;
}
.sp-banner .n { color: var(--accent); font-size: 26px; }

.stat-list { display: grid; gap: 10px; text-align: left; }

.stat-card {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.06);
  border: 2px solid rgba(255,255,255,0.05);
}
.stat-card.can-buy { border-color: rgba(53, 208, 106, 0.5); }
.stat-card .icon { font-size: 24px; text-align: center; }
.stat-card .name { font-weight: bold; letter-spacing: 0.08em; text-transform: uppercase; font-size: 14px; }
.stat-card .next { font-size: 12px; opacity: 0.72; margin-top: 3px; line-height: 1.35; }
.stat-card .next.maxed { color: var(--accent); opacity: 0.9; }

.pips { display: flex; gap: 3px; margin-top: 6px; }
.pips i {
  width: 15px; height: 9px; border-radius: 3px;
  background: rgba(255, 255, 255, 0.16);
}
.pips i.on { background: var(--accent); }
.pips i.gain { background: var(--green); animation: pipIn 300ms ease-out; }
@keyframes pipIn { from { transform: scale(0.3); } to { transform: none; } }

.buy-btn { min-width: 92px; font-size: 14px; padding: 10px 12px; margin: 0; }

/* --------------------------------------------------------- rewards ------ */

.reward-list { display: grid; gap: 5px; margin: 10px auto 16px; max-width: 380px; text-align: left; }
.reward-list .line {
  /* The gap matters: space-between alone lets a long value ("1 win streak")
     run straight into its own label. */
  display: flex; justify-content: space-between; gap: 12px;
  padding: 7px 14px; border-radius: 9px;
  background: rgba(255, 255, 255, 0.06);
  font-size: 14px;
  animation: slideIn 300ms ease-out backwards;
}
.reward-list .line.total { background: rgba(255, 210, 63, 0.16); font-weight: bold; }
.reward-list .line b { color: var(--accent); text-align: right; }
@keyframes slideIn { from { opacity: 0; transform: translateX(-14px); } to { opacity: 1; transform: none; } }

.hint { font-size: 12px; opacity: 0.55; margin-top: 14px; letter-spacing: 0.08em; }

/* ====================================================== CURRENCY / SHOP === */

:root { --cash: #57d98a; }

/* Dollar balance, pinned upper-right of every menu that can spend it. */
.balance-chip {
  position: fixed;
  top: 18px;
  right: 22px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 18px;
  border-radius: 999px;
  background: rgba(10, 14, 20, 0.9);
  border: 2px solid var(--cash);
  font-size: 20px;
  font-weight: bold;
  letter-spacing: 0.04em;
  color: var(--cash);
  box-shadow: 0 5px 0 rgba(0, 0, 0, 0.35);
  z-index: 5;
}
.balance-chip .coin {
  display: grid; place-items: center;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--cash);
  color: #0a1410;
  font-size: 15px;
}

.panel.wide { width: min(1040px, 96vw); }

.menu-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
  margin: 16px 0 4px;
}
.menu-grid .btn { margin: 0; width: 100%; }

/* ------------------------------------------------------------- tabs ------ */

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  justify-content: center;
  margin-bottom: 12px;
}
.tab {
  font-family: var(--font);
  font-size: 12px;
  font-weight: bold;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 8px 14px;
  border-radius: 9px;
  border: 2px solid transparent;
  background: rgba(255, 255, 255, 0.07);
  color: var(--paper);
  cursor: pointer;
}
.tab:hover { background: rgba(255, 255, 255, 0.14); }
.tab.on { background: var(--accent); color: var(--ink); }

/* The Gear/Stats switch at the top of Customize. Bigger than the slot tabs
   below it, so the two rows read as a hierarchy rather than as one long list. */
.main-tabs {
  margin-bottom: 16px;
  gap: 8px;
}
.main-tabs .tab {
  font-size: 13px;
  padding: 10px 22px;
}

/* Count badge on a slot tab: how many you own (Customize) or how many are
   still for sale (Shop). Makes an empty slot obvious before you click it. */
.tab-n {
  display: inline-block;
  min-width: 16px;
  margin-left: 6px;
  padding: 1px 5px;
  border-radius: 20px;
  background: rgba(0, 0, 0, 0.28);
  font-size: 10px;
  opacity: 0.85;
}
.tab.on .tab-n { background: rgba(0, 0, 0, 0.18); }

/* The "you own everything" state in the Shop. */
.big-hint {
  font-size: 14px;
  opacity: 0.75;
  line-height: 1.7;
  max-width: 46ch;
  margin: 28px auto;
  text-transform: none;
  letter-spacing: 0.02em;
}

/* The opponent's own words on their intro card — the first thing that tells
   you who they are, before a single stat bar. */
.boss-quote {
  margin: 10px 0 12px;
  padding-left: 12px;
  border-left: 3px solid var(--accent);
  font-size: 14px;
  line-height: 1.5;
  font-style: italic;
  color: var(--paper);
  opacity: 0.92;
  white-space: pre-line;
}

/* A ladder row you can actually click. Beaten rows stay dimmed but become
   obviously interactive, so the practice court reads as available. */
.opp-row.playable { cursor: pointer; transition: transform 90ms, background 140ms; }
.opp-row.playable:hover,
.opp-row.playable:focus-visible {
  transform: translateX(3px);
  background: rgba(255, 255, 255, 0.10);
  outline: none;
}
.opp-row.beaten.playable { opacity: 0.78; }
.opp-row.beaten.playable:hover { opacity: 1; }

/* ------------------------------------------------------ opponent talk ---- */
/* Deliberately on THEIR half of the screen and in their accent colour, so a
   line of dialogue never gets mistaken for a prompt aimed at the player. */
#speech {
  position: absolute;
  top: 132px;
  left: 50%;
  transform: translateX(-50%);
  max-width: min(440px, 62vw);
  padding: 10px 16px;
  border-radius: 14px;
  border: 2px solid var(--speech-accent, #ffffff);
  background: rgba(12, 16, 24, 0.88);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 180ms ease, transform 180ms ease;
}
#speech.show { opacity: 1; transform: translateX(-50%) translateY(4px); }
.speech-name {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--speech-accent, #ffffff);
  margin-bottom: 3px;
}
.speech-text {
  font-size: 14px;
  line-height: 1.45;
  color: var(--paper);
  white-space: pre-line;
}

/* ------------------------------------------------------ outfit sets ------ */
/* An outfit card is deliberately much larger than a cosmetic card: it sells a
   whole look, so the character wearing it has to be the biggest thing on it. */
.outfit-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: 14px;
  max-height: 52vh;
  overflow-y: auto;
  padding: 4px;
}
.outfit-card {
  display: grid;
  grid-template-columns: 132px 1fr;
  gap: 12px;
  align-items: center;
  text-align: left;
  padding: 12px;
  border-radius: 14px;
  border: 2px solid var(--rar, #b8c2cf);
  background: linear-gradient(140deg, rgba(255, 255, 255, 0.09), rgba(0, 0, 0, 0.24));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35), 0 6px 18px rgba(0, 0, 0, 0.3);
}
.outfit-card.locked { opacity: 0.6; }
.outfit-preview {
  width: 132px;
  height: 168px;
  border-radius: 10px;
  background: radial-gradient(circle at 50% 34%, rgba(255, 255, 255, 0.14), rgba(0, 0, 0, 0.3));
}
.outfit-name {
  font-size: 17px;
  font-weight: bold;
  letter-spacing: 0.04em;
  margin: 2px 0 4px;
}
.outfit-blurb {
  font-size: 11.5px;
  line-height: 1.5;
  opacity: 0.72;
  margin: 0 0 8px;
}
/* The four pieces, listed as chips so the set reads as a set. */
.outfit-pieces {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 10px;
}
.outfit-pieces span {
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 7px;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.1);
  opacity: 0.85;
}
.outfit-card .cos-buy s {
  opacity: 0.5;
  font-size: 11px;
  margin-left: 5px;
  font-weight: normal;
}
.owned-note { margin: 0 0 8px; text-transform: none; letter-spacing: 0.02em; }

/* Owned sets, offered as one click in Customize. */
.outfit-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
  margin-bottom: 10px;
}
.outfit-chip {
  font-family: var(--font);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 7px 12px;
  border-radius: 20px;
  border: 2px solid var(--rar, #b8c2cf);
  background: rgba(255, 255, 255, 0.07);
  color: var(--paper);
  cursor: pointer;
}
.outfit-chip:hover { background: rgba(255, 255, 255, 0.16); }
.outfit-chip.on { background: var(--accent); color: var(--ink); }

/* --------------------------------------------------- cosmetic cards ------ */

.cos-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(124px, 1fr));
  gap: 9px;
  max-height: min(52vh, 460px);
  overflow-y: auto;
  padding: 4px;
  margin-bottom: 12px;
}
.cos-grid::-webkit-scrollbar { width: 8px; }
.cos-grid::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.18); border-radius: 4px; }

.cos-card {
  --rar: #b8c2cf;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 8px 8px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.06);
  border: 2px solid rgba(255, 255, 255, 0.07);
  transition: transform 90ms, border-color 120ms;
}
.cos-card:hover { transform: translateY(-3px); border-color: var(--rar); }
.cos-card.equipped { border-color: var(--accent); background: rgba(255, 210, 63, 0.12); }
.cos-card.owned { border-color: rgba(255, 255, 255, 0.18); }
.cos-card.locked { opacity: 0.82; }

.cos-preview {
  width: 100%;
  height: 104px;
  display: block;
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(60, 110, 150, 0.35), rgba(30, 50, 70, 0.15));
}
.cos-preview.big { width: 150px; height: 180px; flex: 0 0 150px; }

.cos-rarity {
  font-size: 9.5px;
  font-weight: bold;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--rar);
}
.cos-name {
  font-size: 12px;
  text-align: center;
  line-height: 1.2;
  min-height: 2.2em;
  display: flex;
  align-items: center;
}
.cos-buy {
  margin: 0;
  width: 100%;
  font-size: 12px;
  padding: 8px 6px;
  letter-spacing: 0.06em;
}
.cos-buy:disabled { opacity: 0.5; }

/* -------------------------------------------------------- customize ------ */

.customize-body {
  display: flex;
  gap: 18px;
  align-items: flex-start;
  text-align: left;
}
.customize-right { flex: 1; min-width: 0; }

.hero {
  flex: 0 0 190px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 12px;
  border-radius: 16px;
  background: linear-gradient(180deg, rgba(60, 110, 150, 0.32), rgba(20, 34, 48, 0.2));
  border: 2px solid rgba(255, 255, 255, 0.1);
}
.hero canvas { width: 165px; height: 235px; display: block; }
.hero-name {
  font-weight: bold;
  letter-spacing: 0.08em;
  font-size: 15px;
  text-transform: uppercase;
}

@media (max-width: 760px) {
  .customize-body { flex-direction: column; align-items: center; }
  .hero { flex: none; }
}

/* --------------------------------------------------------- rewards ------- */

.reward-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
  margin-bottom: 6px;
}
.reward-list .line b.cash { color: var(--cash); }
.reward-list .line.cash-total { background: rgba(87, 217, 138, 0.16); }
.wallet-row { gap: 10px; margin-bottom: 4px; }
.sp-banner.cash-banner { border-color: var(--cash); background: rgba(87, 217, 138, 0.14); }
.sp-banner.cash-banner .n { color: var(--cash); }

/* --------------------------------------------------------- settings ------ */

.setting-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  margin-bottom: 8px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.06);
  text-align: left;
}
.setting-row label {
  font-weight: bold;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 13px;
}
.setting-val { min-width: 34px; text-align: right; font-weight: bold; color: var(--accent); }

.text-input {
  font-family: var(--font);
  font-size: 15px;
  padding: 8px 12px;
  border-radius: 9px;
  border: 2px solid rgba(255, 255, 255, 0.2);
  background: rgba(0, 0, 0, 0.35);
  color: var(--paper);
  width: 190px;
  grid-column: 2 / span 2;
}
.text-input:focus { outline: none; border-color: var(--accent); }

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 190px;
  height: 8px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.18);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid #8a6a12;
  cursor: pointer;
}

.btn.toggle { margin: 0; min-width: 78px; font-size: 13px; padding: 9px 14px; }
.btn.toggle.on { background: var(--green); box-shadow: 0 5px 0 #227d43; }
.btn.danger { background: var(--red); color: #fff; box-shadow: 0 5px 0 #962020; }
.btn.danger:hover { box-shadow: 0 7px 0 #962020; }

/* ------------------------------------------------------------ modal ------ */

#modal {
  display: grid;
  place-items: center;
  background: rgba(4, 6, 10, 0.72);
  backdrop-filter: blur(4px);
  pointer-events: auto;
  z-index: 10;
  padding: 20px;
}
.modal-panel {
  width: min(520px, 94vw);
  background: #141922;
  border: 4px solid rgba(255, 255, 255, 0.16);
  border-radius: 20px;
  box-shadow: 0 18px 0 rgba(0, 0, 0, 0.4);
  padding: 24px 26px;
  text-align: center;
  animation: panelIn 200ms cubic-bezier(0.16, 1.3, 0.4, 1);
}
.modal-title {
  margin: 0 0 14px;
  font-size: 24px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 1;
}
.modal-item {
  display: flex;
  align-items: center;
  gap: 18px;
  justify-content: center;
  text-align: left;
  margin-bottom: 6px;
}
.modal-name { font-size: 21px; font-weight: bold; margin: 4px 0 6px; }
.modal-price { font-size: 26px; font-weight: bold; color: var(--cash); }

/* ========================================================== POLISH ======== */

/* Buttons lift on hover and settle on press — every menu control animates. */
.btn { position: relative; overflow: hidden; }
.btn::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(120deg, transparent 30%, rgba(255,255,255,0.45), transparent 70%);
  transform: translateX(-120%);
  transition: transform 420ms ease;
  pointer-events: none;
}
.btn:hover::after { transform: translateX(120%); }
.btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

.tab { transition: background 140ms, color 140ms, transform 90ms; }
.tab:hover { transform: translateY(-2px); }

.opp-row { transition: transform 110ms, border-color 140ms, background 140ms; }
.opp-row:not(.locked):hover { transform: translateX(4px); background: rgba(255,255,255,0.10); }

.stat-card { transition: transform 110ms, border-color 140ms; }
.stat-card.can-buy:hover { transform: translateY(-2px); }

/* Screens fade+lift in rather than snapping. */
#screen > .panel { animation: panelIn 260ms cubic-bezier(0.16, 1.3, 0.4, 1); }

/* ---------------------------------------------------------- toasts ------- */

#toasts {
  position: fixed;
  right: 20px;
  bottom: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-end;
  pointer-events: none;
  z-index: 40;
}

.toast {
  display: flex;
  align-items: center;
  gap: 13px;
  min-width: 290px;
  max-width: 380px;
  padding: 13px 18px 13px 14px;
  border-radius: 15px;
  background: linear-gradient(135deg, #1b2432, #131a24);
  border: 2px solid var(--accent);
  box-shadow: 0 10px 0 rgba(0,0,0,0.35), 0 0 26px rgba(255,210,63,0.28);
  transform: translateX(120%);
  opacity: 0;
  transition: transform 340ms cubic-bezier(0.16, 1.4, 0.4, 1), opacity 260ms;
}
.toast.in { transform: translateX(0); opacity: 1; }
.toast.out { transform: translateX(120%); opacity: 0; }

.toast-icon {
  flex: 0 0 46px;
  height: 46px;
  display: grid; place-items: center;
  font-size: 25px;
  border-radius: 12px;
  background: rgba(255, 210, 63, 0.16);
  border: 2px solid rgba(255, 210, 63, 0.4);
}
.toast-kind {
  font-size: 9.5px; font-weight: bold; letter-spacing: 0.2em;
  color: var(--accent); margin-bottom: 2px;
}
.toast-title { font-size: 16px; font-weight: bold; letter-spacing: 0.03em; }
.toast-desc { font-size: 11.5px; opacity: 0.72; line-height: 1.3; margin-top: 2px; }
.toast-reward { font-size: 12px; font-weight: bold; color: var(--cash); margin-top: 5px; }

/* ------------------------------------------------------- boss cards ------ */

#card {
  display: grid;
  place-items: center;
  background: rgba(4, 7, 12, 0.86);
  backdrop-filter: blur(5px);
  pointer-events: auto;
  z-index: 20;
  opacity: 0;
  transition: opacity 260ms ease;
}
#card.shown { opacity: 1; }
#card.leaving { opacity: 0; }

.boss-card {
  position: relative;
  width: min(880px, 94vw);
  padding: 30px 34px 22px;
  border-radius: 24px;
  background: linear-gradient(150deg, var(--bossbg), #0b1119 70%);
  border: 4px solid var(--accent);
  box-shadow: 0 20px 0 rgba(0,0,0,0.4), 0 0 70px color-mix(in srgb, var(--accent) 35%, transparent);
  overflow: hidden;
  transform: scale(0.9) translateY(24px);
  opacity: 0;
  animation: bossIn 420ms cubic-bezier(0.16, 1.3, 0.4, 1) forwards;
}
@keyframes bossIn { to { transform: none; opacity: 1; } }

/* Slow sweep of the boss's own colour across the card. */
.boss-glow {
  position: absolute; inset: -40%;
  background: radial-gradient(circle at 25% 30%, color-mix(in srgb, var(--accent) 26%, transparent), transparent 55%);
  animation: bossGlow 7s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes bossGlow { to { transform: translate(12%, 8%) scale(1.15); } }

.boss-body { position: relative; display: flex; gap: 26px; align-items: center; }

.boss-portrait {
  position: relative;
  flex: 0 0 210px;
  border-radius: 18px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 22%, transparent), rgba(0,0,0,0.28));
  border: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  padding: 8px;
}
.boss-portrait canvas { width: 100%; height: 250px; display: block; }
.boss-portrait.beaten { filter: grayscale(0.45) brightness(0.85); }
.boss-badge {
  position: absolute; right: -12px; top: -12px;
  width: 46px; height: 46px;
  display: grid; place-items: center;
  font-size: 24px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 4px 0 rgba(0,0,0,0.35);
}

.boss-info { flex: 1; min-width: 0; text-align: left; }
.boss-vs {
  font-size: 11px; font-weight: bold; letter-spacing: 0.28em;
  color: var(--accent); opacity: 0.9;
}
.boss-vs.win { color: var(--green); }
.boss-name {
  margin: 4px 0 2px;
  font-size: clamp(30px, 4.6vw, 46px);
  line-height: 1;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-shadow: 0 5px 0 rgba(0,0,0,0.45);
}
.boss-nick {
  font-size: 17px; font-style: italic; color: var(--accent);
  margin-bottom: 8px;
}
.boss-blurb {
  font-size: 13.5px; line-height: 1.5; opacity: 0.82;
  margin: 0 0 14px; max-width: 46ch;
}

.boss-stats { display: grid; gap: 6px; margin-bottom: 12px; }
.boss-stat {
  display: grid;
  grid-template-columns: 118px 1fr 26px;
  align-items: center;
  gap: 10px;
  font-size: 11.5px;
  letter-spacing: 0.06em;
}
.boss-stat-name { text-transform: uppercase; opacity: 0.78; }
.boss-bar {
  height: 9px; border-radius: 5px;
  background: rgba(255,255,255,0.13);
  overflow: hidden;
}
.boss-bar i {
  display: block; height: 100%;
  background: var(--accent);
  border-radius: 5px;
  animation: barGrow 620ms cubic-bezier(0.16, 1, 0.4, 1) backwards;
}
@keyframes barGrow { from { width: 0 !important; } }
.boss-stat b { font-size: 13px; text-align: right; }

.boss-diff { display: flex; align-items: center; gap: 12px; font-size: 11px; letter-spacing: 0.2em; opacity: 0.85; }
.boss-diff b { color: var(--accent); font-size: 20px; letter-spacing: 3px; }
.boss-diff b i { opacity: 0.22; font-style: normal; }

.boss-rewards { display: flex; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.boss-reward {
  padding: 9px 16px; border-radius: 12px;
  background: rgba(255,255,255,0.08);
  border: 2px solid rgba(255,255,255,0.14);
  font-size: 10.5px; letter-spacing: 0.16em;
}
.boss-reward b { display: block; font-size: 22px; margin-top: 3px; color: var(--accent); letter-spacing: 0; }
.boss-reward.cash { border-color: var(--cash); }
.boss-reward.cash b { color: var(--cash); }

.boss-unlock {
  font-size: 12px; letter-spacing: 0.12em;
  padding: 8px 14px; border-radius: 10px;
  background: rgba(255,255,255,0.07);
  display: inline-block;
}
.boss-unlock b { color: var(--accent); }
.boss-unlock.champion { background: rgba(255,210,63,0.16); color: var(--accent); font-weight: bold; }

.boss-prompt {
  position: relative;
  margin-top: 20px;
  text-align: center;
  font-size: 12px;
  letter-spacing: 0.26em;
  opacity: 0.72;
  /* Its own keyframes: promptPulse assumes a translateX(-50%) centred element. */
  animation: bossPrompt 1.5s ease-in-out infinite;
}
@keyframes bossPrompt {
  0%, 100% { opacity: 0.6; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.03); }
}

/* ---------------------------------------------------- achievements ------- */

.ach-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 8px;
  max-height: min(44vh, 380px);
  overflow-y: auto;
  padding: 4px;
  text-align: left;
}
.ach-grid::-webkit-scrollbar { width: 8px; }
.ach-grid::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.18); border-radius: 4px; }

.ach-card {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px;
  border-radius: 12px;
  background: rgba(255,255,255,0.05);
  border: 2px solid rgba(255,255,255,0.06);
}
.ach-card.on { border-color: var(--accent); background: rgba(255,210,63,0.12); }
.ach-card .ico {
  flex: 0 0 38px; height: 38px;
  display: grid; place-items: center;
  font-size: 20px; border-radius: 10px;
  background: rgba(0,0,0,0.3);
}
.ach-card.off .ico { filter: grayscale(1); opacity: 0.4; }
.ach-card .t { font-size: 13.5px; font-weight: bold; letter-spacing: 0.03em; }
.ach-card .d { font-size: 11px; opacity: 0.68; line-height: 1.3; margin-top: 2px; }
.ach-card.off .t, .ach-card.off .d { opacity: 0.45; }

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 6px;
  text-align: left;
  margin-bottom: 6px;
}
.stat-line {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 8px 13px; border-radius: 9px;
  background: rgba(255,255,255,0.05);
  font-size: 12px;
}
.stat-line b { font-size: 15px; color: var(--accent); }

@media (max-width: 720px) {
  .boss-body { flex-direction: column; }
  .boss-portrait { flex: none; width: 190px; }
  .boss-info { text-align: center; }
  .boss-blurb { margin-inline: auto; }
  .boss-stat { grid-template-columns: 100px 1fr 24px; }
}

/* ------------------------------------------------------- power serve ----- */

/* The sliver is carved out of the green: hit it and the serve comes off hot. */
.meter-track .zone.power {
  background: linear-gradient(180deg, #ff5a4d, #d61f10);
  box-shadow: 0 0 12px rgba(255, 90, 77, 0.9), inset 0 0 6px rgba(255,255,255,0.5);
  animation: powerPulse 1.1s ease-in-out infinite;
}
@keyframes powerPulse { 50% { filter: brightness(1.4); } }

#serve-meter.has-power .meter-track { border-color: #ffd9a8; }

.meter-hint.power-hit {
  color: #ff6a4d;
  font-weight: bold;
  text-shadow: 0 0 12px rgba(255, 90, 77, 0.8);
  animation: pop 700ms cubic-bezier(0.16, 1.4, 0.4, 1);
}

/* ---------------------------------------------------- player slots ------- */

.slot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}

.slot-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 14px 12px 12px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.06);
  border: 2px solid rgba(255, 255, 255, 0.08);
  transition: transform 120ms, border-color 140ms;
}
.slot-card:hover { transform: translateY(-3px); }
.slot-card.active { border-color: var(--accent); background: rgba(255, 210, 63, 0.12); }
.slot-card.empty { justify-content: center; min-height: 250px; border-style: dashed; }

.slot-preview {
  width: 100%; height: 150px; display: block;
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(60,110,150,0.35), rgba(30,50,70,0.15));
}
.slot-plus { font-size: 46px; opacity: 0.35; line-height: 1; }
.slot-name { font-weight: bold; font-size: 16px; letter-spacing: 0.04em; }
.slot-name i { font-style: normal; font-size: 11px; color: var(--accent); opacity: 0.9; }
.slot-sub { font-size: 11.5px; opacity: 0.6; }

.slot-stats {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 10px;
  font-size: 11px; opacity: 0.78;
}
.slot-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 5px; width: 100%; }
.slot-btn { margin: 0; font-size: 12px; padding: 8px 12px; }
.slot-btn.small { font-size: 10.5px; padding: 6px 10px; }

.text-input.wide-input { width: 100%; max-width: 300px; grid-column: auto; margin: 4px auto 0; display: block; }

/* ------------------------------------------------------ title layout ----- */

.title-panel { width: min(430px, 94vw); padding-top: 16px; }

/* Options bar: everything secondary, out of the way at the top. */
.top-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 2px solid rgba(255, 255, 255, 0.09);
}
.top-bar-right { display: flex; gap: 6px; }

.chip-btn {
  font-family: var(--font);
  font-size: 14px;
  font-weight: bold;
  letter-spacing: 0.06em;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 13px;
  border-radius: 10px;
  border: 2px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.06);
  color: var(--paper);
  cursor: pointer;
  transition: background 130ms, border-color 130ms, transform 90ms;
}
.chip-btn:hover { background: rgba(255,255,255,0.14); border-color: var(--accent); transform: translateY(-1px); }
.chip-btn:active { transform: translateY(1px); }
.chip-btn span {
  max-width: 130px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font-size: 13px;
}

/* Primary actions: one column, stacked, nothing to scan sideways for. */
.menu-stack {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin: 18px 0 4px;
}
.menu-stack .btn { margin: 0; width: 100%; }
.btn.big { font-size: 20px; padding: 15px 24px; letter-spacing: 0.12em; }

.title-panel .title-logo { font-size: clamp(38px, 8vw, 62px); }

/* ================================================== DEVELOPER PANEL ====== */

#admin {
  display: grid;
  place-items: center;
  background: rgba(3, 5, 9, 0.9);
  backdrop-filter: blur(5px);
  pointer-events: auto;
  z-index: 60;
  padding: 18px;
  overflow-y: auto;
}
#admin button { pointer-events: auto; }

/* ------------------------------------------------------------- gate ------ */

.dev-gate {
  width: min(360px, 92vw);
  padding: 26px 24px 20px;
  border-radius: 20px;
  background: #10151d;
  border: 3px solid #2ec4b6;
  box-shadow: 0 16px 0 rgba(0,0,0,0.4), 0 0 50px rgba(46, 196, 182, 0.25);
  text-align: center;
  animation: panelIn 220ms cubic-bezier(0.16, 1.3, 0.4, 1);
}
.dev-lock { font-size: 34px; margin-bottom: 4px; }
.dev-gate h2 { margin: 0 0 2px; font-size: 21px; letter-spacing: 0.1em; text-transform: uppercase; }
.dev-gate .sub { margin-bottom: 14px; font-size: 13px; }

.dev-code { display: flex; justify-content: center; gap: 11px; margin-bottom: 8px; }
.dev-code i {
  width: 15px; height: 15px; border-radius: 50%;
  background: rgba(255,255,255,0.14);
  border: 2px solid rgba(255,255,255,0.22);
  transition: background 120ms, transform 120ms;
}
.dev-code i.on { background: #2ec4b6; border-color: #2ec4b6; transform: scale(1.15); }

.dev-error { min-height: 18px; font-size: 12px; color: var(--red); letter-spacing: 0.06em; }

.dev-keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 7px;
  margin: 8px 0 10px;
}
.dev-key {
  font-family: var(--font);
  font-size: 20px; font-weight: bold;
  padding: 13px 0;
  border-radius: 11px;
  border: 2px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.06);
  color: var(--paper);
  cursor: pointer;
  transition: background 110ms, transform 80ms;
}
.dev-key:hover { background: rgba(46,196,182,0.22); border-color: #2ec4b6; }
.dev-key:active { transform: translateY(2px); }
.dev-key.wide { font-size: 13px; letter-spacing: 0.08em; }

/* ------------------------------------------------------------ panel ------ */

.dev-panel {
  width: min(900px, 96vw);
  max-height: 94vh;
  overflow-y: auto;
  padding: 20px 22px;
  border-radius: 20px;
  background: #0f141c;
  border: 3px solid #2ec4b6;
  box-shadow: 0 16px 0 rgba(0,0,0,0.4);
  animation: panelIn 220ms cubic-bezier(0.16, 1.3, 0.4, 1);
}

.dev-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding-bottom: 12px; margin-bottom: 12px;
  border-bottom: 2px solid rgba(255,255,255,0.09);
}
.dev-tag { font-size: 10px; letter-spacing: 0.26em; color: #2ec4b6; font-weight: bold; }
.dev-head h2 { margin: 2px 0 0; font-size: 22px; letter-spacing: 0.04em; }
.dev-head h2 span { font-size: 13px; opacity: 0.55; font-weight: normal; }
.dev-head-actions { display: flex; gap: 6px; }

.dev-chip {
  font-family: var(--font); font-size: 12px; font-weight: bold; letter-spacing: 0.06em;
  padding: 8px 13px; border-radius: 9px;
  border: 2px solid rgba(255,255,255,0.14);
  background: rgba(255,255,255,0.06); color: var(--paper); cursor: pointer;
}
.dev-chip:hover { border-color: #2ec4b6; background: rgba(46,196,182,0.16); }
.dev-chip.on { background: #2ec4b6; color: #06231f; border-color: #2ec4b6; }
.dev-chip.close { color: var(--red); }

.dev-warn {
  padding: 8px 13px; margin-bottom: 10px; border-radius: 9px;
  background: rgba(255,77,77,0.14); border: 2px solid var(--red);
  font-size: 12px; letter-spacing: 0.08em; font-weight: bold;
}
.dev-note {
  padding: 8px 13px; margin-bottom: 10px; border-radius: 9px;
  background: rgba(46,196,182,0.14); border: 2px solid #2ec4b6;
  font-size: 12.5px;
}

.dev-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 18px; }
.dev-cols h3 {
  margin: 0 0 8px; font-size: 11px; letter-spacing: 0.2em;
  text-transform: uppercase; opacity: 0.6;
}
.dev-cols section > h3:not(:first-child) { margin-top: 16px; }

.dev-stats { display: grid; gap: 6px; }
.dev-stat {
  display: grid;
  grid-template-columns: 108px 30px 62px 30px 1fr;
  align-items: center; gap: 7px;
}
.dev-stat-name { font-size: 12px; letter-spacing: 0.04em; }
.dev-step {
  font-family: var(--font); font-size: 17px; font-weight: bold; line-height: 1;
  height: 30px; border-radius: 8px; cursor: pointer;
  border: 2px solid rgba(255,255,255,0.14);
  background: rgba(255,255,255,0.07); color: var(--paper);
}
.dev-step:hover { border-color: #2ec4b6; background: rgba(46,196,182,0.2); }

.dev-num {
  font-family: var(--font); font-size: 14px; text-align: center;
  padding: 6px 4px; border-radius: 8px;
  border: 2px solid rgba(255,255,255,0.16);
  background: rgba(0,0,0,0.35); color: var(--paper);
  width: 100%;
}
.dev-num:focus { outline: none; border-color: #2ec4b6; }
.dev-num.wide { width: 100%; margin-top: 4px; }

.dev-bar { height: 7px; border-radius: 4px; background: rgba(255,255,255,0.12); overflow: hidden; }
.dev-bar i { display: block; height: 100%; background: #2ec4b6; }

.dev-wallet { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.dev-wallet label { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; opacity: 0.72; }
.dev-apply { width: 100%; margin: 10px 0 0; }

.dev-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.dev-action {
  font-family: var(--font); font-size: 12px; text-align: left;
  display: flex; align-items: center; gap: 8px;
  padding: 9px 11px; border-radius: 9px; cursor: pointer;
  border: 2px solid rgba(255,255,255,0.1);
  background: rgba(255,255,255,0.05); color: var(--paper);
  transition: border-color 120ms, background 120ms, transform 80ms;
}
.dev-action:hover { border-color: #2ec4b6; background: rgba(46,196,182,0.14); transform: translateY(-1px); }
.dev-action-ico { font-size: 15px; }

.dev-jumps { display: flex; flex-wrap: wrap; gap: 5px; }
.dev-jump {
  font-family: var(--font); font-size: 11px;
  padding: 7px 10px; border-radius: 8px; cursor: pointer;
  border: 2px solid rgba(255,255,255,0.1);
  background: rgba(255,255,255,0.05); color: var(--paper);
}
.dev-jump:hover { border-color: var(--accent); background: rgba(255,210,63,0.14); }

.dev-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  margin-top: 16px; padding-top: 12px;
  border-top: 2px solid rgba(255,255,255,0.09);
  font-size: 11.5px; opacity: 0.75;
}
.dev-wipe { margin: 0; font-size: 12px; padding: 8px 14px; }

/* ==========================================================================
   MULTIPLAYER
   Everything online reuses .panel, .btn, .ladder and .reward-list; what is
   here is only the handful of things the campaign never needed — a versus
   screen, a rank ladder, a connection indicator and a countdown.
   ========================================================================== */

/* --- title-screen entry ---------------------------------------------------- */

.btn.online { position: relative; }
.btn.online .live-dot {
  display: inline-block; width: 9px; height: 9px; margin-left: 6px;
  border-radius: 50%; background: var(--green); vertical-align: middle;
  animation: livePulse 2.1s ease-in-out infinite;
}
@keyframes livePulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(53, 208, 106, 0.55); }
  50% { opacity: 0.75; box-shadow: 0 0 0 6px rgba(53, 208, 106, 0); }
}

/* --- connecting / searching ------------------------------------------------ */

.net-splash { padding: 22px 0 10px; }

.net-orb {
  width: 54px; height: 54px; margin: 0 auto 18px;
  border-radius: 50%;
  border: 5px solid rgba(255, 255, 255, 0.12);
  border-top-color: var(--accent-2);
  animation: netSpin 900ms linear infinite;
}
.net-orb.bad { border-top-color: var(--red); animation-play-state: paused; }
@keyframes netSpin { to { transform: rotate(360deg); } }

.searching-text {
  font-size: 19px; font-weight: bold; letter-spacing: 0.16em;
  margin: 0 0 6px; color: var(--accent);
}
.searching-text::after {
  content: ''; animation: dots 1.4s steps(4, end) infinite;
}
@keyframes dots { 0% { content: ''; } 25% { content: '.'; } 50% { content: '..'; } 75% { content: '...'; } }

/* --- forms ----------------------------------------------------------------- */

/* `minmax(0, 1fr)` and explicit column placement, both on purpose: a <select>
   is as wide as its longest option wants to be ("Peak Performance Pickleball
   Academy"), which grows the track past the panel and spills an extra implicit
   column that the next label then falls into. */
.form-grid {
  display: grid; grid-template-columns: 120px minmax(0, 1fr);
  gap: 12px 14px; align-items: center;
  text-align: left; margin: 6px 0 4px;
}
.form-grid > label {
  grid-column: 1;
  font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; opacity: 0.7;
}
.form-grid > :not(label) { grid-column: 2; min-width: 0; }
.form-grid .tabs { margin: 0; justify-content: flex-start; }

.text-input {
  font-family: var(--font); font-size: 15px; color: var(--paper);
  background: rgba(255, 255, 255, 0.07);
  border: 2px solid rgba(255, 255, 255, 0.16);
  border-radius: 10px; padding: 10px 12px; width: 100%;
}
.text-input:focus { outline: none; border-color: var(--accent); }
select.text-input { cursor: pointer; }
select.text-input option { background: #171b24; color: var(--paper); }

.mode-note {
  font-size: 12.5px; line-height: 1.5; opacity: 0.72;
  margin: 14px auto 4px; max-width: 460px;
}
.form-error { color: var(--red); font-size: 13px; margin: 10px 0 0; }

.code-entry {
  display: flex; align-items: center; justify-content: center;
  gap: 8px; margin: 24px 0 6px;
}
.code-entry .prefix {
  font-size: 22px; font-weight: bold; letter-spacing: 0.1em; opacity: 0.55;
}
.code-input {
  font-family: var(--font); font-size: 30px; font-weight: bold;
  letter-spacing: 0.24em; text-align: center; width: 168px;
  color: var(--accent); background: rgba(255, 255, 255, 0.07);
  border: 3px solid rgba(255, 255, 255, 0.18); border-radius: 12px; padding: 8px 0 8px 0.24em;
}
.code-input:focus { outline: none; border-color: var(--accent); }

/* --- browse ---------------------------------------------------------------- */

.lobby-row .diff { min-width: 92px; }
.empty-note { padding: 34px 10px; opacity: 0.7; }
.empty-note .big { font-size: 44px; margin-bottom: 10px; }
.empty-note p { margin: 4px 0; }

/* --- lobby ----------------------------------------------------------------- */

.versus {
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: center; gap: 10px; margin: 6px 0 14px;
}
.vs-mark {
  font-size: 26px; font-weight: bold; letter-spacing: 0.1em;
  color: var(--accent); text-shadow: 0 3px 0 rgba(0, 0, 0, 0.5);
}

.seat {
  background: rgba(255, 255, 255, 0.05);
  border: 3px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px; padding: 12px 8px 10px;
  transition: border-color 160ms, background 160ms;
}
.seat.ready { border-color: var(--green); background: rgba(53, 208, 106, 0.1); }
.seat.empty { opacity: 0.5; border-style: dashed; }
.seat-art { position: relative; height: 230px; display: grid; place-items: center; }
/* The CSS box must be fixed in BOTH axes. `characterPreview.render` sizes the
   canvas backing store from `clientWidth/clientHeight` and then writes the
   width/height attributes — with `height: auto` those writes feed back into
   layout, and the figure grows out of its seat and over the buttons below. */
.seat-canvas { display: block; width: 180px; height: 230px; max-width: 100%; }
.seat-name { font-weight: bold; font-size: 16px; letter-spacing: 0.04em; margin-top: 4px; }
.seat-sub { font-size: 11.5px; opacity: 0.72; margin-top: 3px; }

.ready-stamp {
  position: absolute; top: 12px; left: 50%;
  transform: translateX(-50%) rotate(-7deg);
  background: var(--green); color: var(--ink);
  font-weight: bold; font-size: 15px; letter-spacing: 0.14em;
  padding: 5px 14px; border-radius: 8px;
  box-shadow: 0 4px 0 rgba(0, 0, 0, 0.35);
  animation: stampIn 260ms cubic-bezier(0.2, 1.5, 0.4, 1);
}
@keyframes stampIn {
  0% { transform: translateX(-50%) rotate(-7deg) scale(2.2); opacity: 0; }
  100% { transform: translateX(-50%) rotate(-7deg) scale(1); opacity: 1; }
}

.waiting-dots { display: flex; gap: 8px; }
.waiting-dots i {
  width: 11px; height: 11px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  animation: waitBob 1.1s ease-in-out infinite;
}
.waiting-dots i:nth-child(2) { animation-delay: 0.14s; }
.waiting-dots i:nth-child(3) { animation-delay: 0.28s; }
@keyframes waitBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }

.starting-banner {
  background: var(--accent); color: var(--ink);
  font-weight: bold; font-size: 15px; letter-spacing: 0.18em;
  padding: 9px; border-radius: 10px; margin: 0 auto 12px; max-width: 320px;
  animation: livePulse 1.2s ease-in-out infinite;
}

.host-controls { max-width: 460px; margin: 8px auto 2px; }

.code-banner {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  background: rgba(35, 201, 214, 0.12);
  border: 2px dashed rgba(35, 201, 214, 0.5);
  border-radius: 12px; padding: 10px 14px; margin: 14px auto 4px; max-width: 400px;
}
.code-banner .label { font-size: 10.5px; letter-spacing: 0.16em; opacity: 0.7; }
.code-banner b {
  font-size: 22px; letter-spacing: 0.1em; color: var(--accent-2);
  user-select: text; -webkit-user-select: text;
}
.btn.tiny { margin: 0; padding: 7px 12px; font-size: 12px; box-shadow: 0 3px 0 #9aa3b2; }

/* --- ranks ----------------------------------------------------------------- */

/* Two-class selector on purpose: the narrow-viewport rule further down resizes
   .seat-canvas for lobby seats, and this figure must not follow it. */
.profile-figure { display: grid; place-items: center; margin-bottom: 14px; }
.profile-figure .seat-canvas { width: 150px; height: 192px; }

.rank-chip, .rank-hero {
  display: flex; align-items: center; gap: 14px;
  background: rgba(255, 255, 255, 0.05);
  border: 2px solid color-mix(in srgb, var(--rk, #888) 55%, transparent);
  border-radius: 14px; padding: 12px 16px; margin: 0 auto 18px;
  max-width: 420px; text-align: left;
}
.rank-chip .badge, .rank-hero .hero-badge {
  font-size: 30px; width: 50px; height: 50px; flex: none;
  display: grid; place-items: center; border-radius: 12px;
  background: color-mix(in srgb, var(--rk, #888) 22%, transparent);
}
.rank-hero .hero-badge { font-size: 40px; width: 66px; height: 66px; }
.rank-text, .hero-text { display: grid; gap: 2px; flex: 1; min-width: 0; }
.rank-text b, .hero-text b { font-size: 17px; letter-spacing: 0.06em; color: var(--rk, var(--paper)); }
.rank-text span, .hero-text span { font-size: 12.5px; opacity: 0.75; }

.rank-bar {
  height: 8px; border-radius: 4px; margin: 6px 0 3px;
  background: rgba(255, 255, 255, 0.12); overflow: hidden;
}
.rank-bar i {
  display: block; height: 100%; border-radius: 4px;
  background: var(--rk, var(--accent));
  transition: width 500ms cubic-bezier(0.2, 0.9, 0.3, 1);
}

.rank-ladder { display: grid; gap: 5px; align-content: start; }
.rank-row {
  display: grid; grid-template-columns: 34px 1fr auto;
  align-items: center; gap: 10px; text-align: left;
  background: rgba(255, 255, 255, 0.04);
  border: 2px solid transparent; border-radius: 10px; padding: 7px 12px;
  font-size: 13px;
}
.rank-row .badge { font-size: 18px; }
.rank-row .rank-name { color: var(--rk); font-weight: bold; letter-spacing: 0.05em; }
.rank-row .rank-min { font-size: 11px; opacity: 0.55; }
.rank-row.current { border-color: var(--rk); background: color-mix(in srgb, var(--rk) 14%, transparent); }
.rank-row.locked { opacity: 0.38; }

.mini-rank { color: var(--rk); font-weight: bold; }

.two-col {
  display: grid; grid-template-columns: 1fr 1fr; gap: 18px;
  align-items: start; text-align: left;
}
.two-col h2 { margin-top: 0; }

/* --- online results -------------------------------------------------------- */

.final-score {
  display: flex; align-items: center; justify-content: center; gap: 22px;
  margin: 10px 0 18px;
}
.final-score .who { display: grid; gap: 2px; min-width: 110px; }
.final-score .who span {
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; opacity: 0.7;
}
.final-score .who b { font-size: 52px; line-height: 1; color: var(--accent); }
.final-score .dash { font-size: 30px; opacity: 0.4; }

.rating-strip {
  display: flex; align-items: center; gap: 14px;
  background: rgba(255, 255, 255, 0.05);
  border: 2px solid color-mix(in srgb, var(--rk, #888) 55%, transparent);
  border-radius: 12px; padding: 10px 16px; margin: 0 auto 16px;
  max-width: 400px; text-align: left;
}
.rating-strip .badge { font-size: 28px; }
.rating-text { display: grid; gap: 2px; flex: 1; }
.rating-text b { font-size: 20px; }
.rating-text .delta { font-size: 15px; }
.rating-strip.up .delta { color: var(--green); }
.rating-strip.down .delta { color: var(--red); }

.hint.pulse { color: var(--accent); animation: livePulse 1.6s ease-in-out infinite; }

/* --- in-match chrome ------------------------------------------------------- */

#net-status {
  position: absolute; right: 12px; bottom: 12px;
  display: flex; align-items: center; gap: 6px;
  background: rgba(16, 19, 26, 0.6);
  border-radius: 20px; padding: 5px 11px;
  font-size: 11px; letter-spacing: 0.08em;
  opacity: 0.72; pointer-events: none;
}
#net-status .net-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--green);
}
#net-status .net-ping { opacity: 0.7; }
#net-status.q-good .net-dot { background: #9ede4f; }
#net-status.q-fair .net-dot { background: var(--yellow); }
#net-status.q-poor .net-dot { background: #ff8a4d; }
#net-status.q-reconnecting {
  opacity: 1; background: rgba(255, 77, 77, 0.25);
}
#net-status.q-reconnecting .net-dot {
  background: var(--red); animation: livePulse 900ms ease-in-out infinite;
}

#countdown {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 130px; font-weight: bold; letter-spacing: 0.04em;
  color: var(--accent); text-shadow: 0 8px 0 rgba(0, 0, 0, 0.45);
  pointer-events: none;
}
#countdown.pop { animation: countPop 420ms cubic-bezier(0.2, 1.4, 0.4, 1); }
@keyframes countPop {
  0% { transform: scale(2.1); opacity: 0; }
  40% { transform: scale(1); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

.grace-bar {
  height: 10px; border-radius: 5px; margin: 14px 0 8px;
  background: rgba(255, 255, 255, 0.12); overflow: hidden;
}
.grace-bar i {
  display: block; height: 100%; width: 100%;
  background: var(--red); border-radius: 5px;
  transition: width 240ms linear;
}

.q-excellent { color: var(--green); }
.q-good { color: #9ede4f; }
.q-fair { color: var(--yellow); }
.q-poor { color: #ff8a4d; }

@media (max-width: 720px) {
  .two-col { grid-template-columns: 1fr; }
  .versus { grid-template-columns: 1fr; }
  .vs-mark { margin: 4px 0; }
  /* The canvas has to shrink with its box. .seat-art is position:relative, so
     anything that overflows it paints ON TOP of the name and rank below. */
  .seat-art { height: 180px; }
  .seat-canvas { width: 141px; height: 180px; }
  .form-grid { grid-template-columns: 1fr; gap: 6px 0; }
  #countdown { font-size: 86px; }

  /* The balance chip is position:fixed, so on a phone-width screen a centred
     panel title runs underneath it. Shrink the chip and start titles below it. */
  .balance-chip { top: 10px; right: 12px; padding: 6px 13px; font-size: 15px; }
  .balance-chip .coin { width: 19px; height: 19px; font-size: 12px; }
  .panel h1 { margin-top: 22px; }
}
