﻿/* Self-hosted fonts. Served from our own origin rather than Google's CDN:
 * embedding fonts.googleapis.com sends every visitor's IP to Google, which a
 * German court found breached GDPR in 2022 — and this server runs in Frankfurt,
 * so most players are in the EU. Self-hosting also drops a render-blocking
 * request to a third party on first load.
 *
 * All four families are SIL Open Font License 1.1; see ASSETS.md and the
 * OFL.txt shipped alongside the woff2 files.
 * Latin subset only — the UI is English. */
@font-face {
  font-family: 'Cinzel';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/cinzel-500.woff2') format('woff2');
}
@font-face {
  font-family: 'Cinzel';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/cinzel-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Cinzel';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url('/assets/fonts/cinzel-900.woff2') format('woff2');
}
@font-face {
  font-family: 'Spectral';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/spectral-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Spectral';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/spectral-600.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-400.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-600.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/jetbrains-mono-400.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/jetbrains-mono-500.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/jetbrains-mono-700.woff2') format('woff2');
}

:root {
  /* --- HUD design system (Wizard Duel HUD handoff) --- */
  --font-display: Cinzel, Georgia, serif;
  --font-body: Spectral, Georgia, serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, monospace;
  --brass: #6d5527;          /* frame borders */
  --brass-lit: #c9a24a;      /* rules, headers */
  --gold-text: #e8cf95;
  --gold-bright: #d9b45e;    /* ultimate frame */
  --ult-text: #ffe0a8;
  --parchment: #efe3c8;
  --stone-hi: #3a3128;       /* frame gradient */
  --stone-lo: #1d1712;
  --ink: #14100d;
  --ink-deep: #120e0b;
  --frost-blue: #7fb6d8;     /* you */
  --blood: #c0392b;          /* foe */
  --hp-hi: #6fce5f;
  --hp-lo: #2f7d29;
  --ember: #f0a04b;          /* damage numbers in the log */

  /* --- main menu (Wizbots handoff) --- */
  --font-ui: 'JetBrains Mono', ui-monospace, monospace;
  --mn-gold: #e8c66a;
  --mn-cream: #efe7d8;

  --bg: #0e1020;
  --panel: #1a1d33;
  --fireball: #ff6b3d;
  --shield: #4db8ff;
  --dash: #7dff9e;
  --trap: #c98bff;
  --tesla: #b9e6ff;
  --tornado: #aebccf;
  --ice: #86e0ff;
  --oil: #9a7fbf;
  --ignite: #ff7a2a;
  --scatter: #ff9d4d;
  --boomerang: #5fd6e0;
  --nova: #9fe0ff;
  --frostbolt: #6db8f0;
  --fissure: #b98a52;
  --stoneskin: #8a6a42;
  --updraft: #cfeee0;
  --slipstream: #a5e8c9;
  --meteor: #ff5c2a;
  --blizzard: #7fc4ff;
  --quake: #a06c38;
  --hurricane: #9fb8ad;
  --firecannon: #ff4517;
  --swing: #e8d9a0;
  --text: #e8eaff;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: radial-gradient(circle at 50% 40%, #171a30 0%, #0a0b16 100%);
  color: #e8eaff;
  font-family: 'Segoe UI', system-ui, sans-serif;
  user-select: none;
}

canvas#game {
  display: block;
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  cursor: crosshair;
}

.hidden { display: none !important; }

/* ---------- Menu ---------- */
.overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(6, 8, 18, 0.82);
  backdrop-filter: blur(6px);
  z-index: 20;
}

.panel {
  background: linear-gradient(160deg, var(--stone-hi), var(--stone-lo) 55%, var(--ink));
  border: 1px solid var(--brass);
  border-radius: 14px;
  padding: 34px 40px;
  width: 380px;
  text-align: center;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(233, 207, 149, 0.08);
}

.panel h1 {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-size: 34px;
  letter-spacing: 0.06em;
  color: var(--gold-text);
}

.panel .tag {
  margin: 0 0 22px;
  font-family: var(--font-body);
  color: rgba(239, 227, 200, 0.6);
  font-size: 14px;
}

#nameInput {
  width: 100%;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid #363c6e;
  background: #0e1024;
  color: #fff;
  font-size: 16px;
  outline: none;
  margin-bottom: 12px;
}
#nameInput:focus { border-color: var(--shield); }

/* Still used by the between-round panel (Change loadout / Rematch now) —
   matches .ld-btn so the intermission and the draft read as one screen. */
.menu-btn {
  width: 100%;
  padding: 13px;
  border: none;
  border-radius: 8px;
  font-family: var(--font-display);
  color: var(--parchment);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: transform 0.08s ease, filter 0.15s ease, border-color 0.15s ease;
  margin-bottom: 10px;
}
.menu-btn:hover { filter: brightness(1.12); }
.menu-btn:active { transform: scale(0.98); }
.menu-btn.host {
  border: 1px solid var(--gold-bright);
  background: linear-gradient(180deg, #c9a24a 0%, #a07c31 55%, #7d5d22 100%);
  color: #201703;
  text-shadow: 0 1px 0 rgba(255, 232, 176, 0.35);
  box-shadow: inset 0 1px 0 rgba(255, 232, 176, 0.4);
}
.menu-btn.join {
  border: 1px solid var(--brass-lit);
  background: linear-gradient(180deg, rgba(58,49,40,0.9), var(--ink));
  margin-bottom: 0;
}
.menu-btn.test {
  background: linear-gradient(180deg, rgba(58,49,40,0.6), var(--ink));
  border: 1px solid var(--brass);
  color: rgba(239, 227, 200, 0.75);
  padding: 12px;
}
.menu-btn.test:hover { border-color: var(--brass-lit); color: var(--parchment); filter: none; }

#roomBadge {
  position: fixed;
  top: 14px;
  left: 14px;
  background: rgba(16, 18, 38, 0.78);
  border: 1px solid #2a2f58;
  border-radius: 10px;
  padding: 8px 14px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 1px;
  z-index: 10;
}
#roomBadge .lbl { color: #8b90c0; font-size: 10px; font-weight: 400; letter-spacing: 1px; display: block; text-transform: uppercase; }

.k {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 5px;
  font-size: 11px;
  font-weight: 700;
  background: #c2c8ee;   /* neutral chip so plain keys (Q/E) stay readable */
  color: #12142a;
}
.k.fireball { background: var(--fireball); }
.k.tesla { background: var(--tesla); }
.k.ice { background: var(--ice); }
.k.tornado { background: var(--tornado); }
.k.shield { background: var(--shield); }
.k.dash { background: var(--dash); }
.k.trap { background: var(--trap); }

/* ===================== MAIN MENU (Wizbots handoff) =====================
   A fixed 1920×1080 stage scaled to fit whatever viewport it lands in, so the
   composition never reflows — it just gets smaller. */
#menu {
  position: fixed;
  inset: 0;
  background: #07070a;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  z-index: 30;
  font-family: var(--font-ui);
  color: var(--mn-cream);
}
#menuStage {
  position: relative;
  flex: none;
  width: 1920px;
  height: 1080px;
  transform-origin: center center;
  overflow: hidden;
}
#menuBg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
#menuBg.missing { display: none; }        /* fall back to the painted backdrop */
/* backdrop used when no arena still is present */
#menuStage::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 90% at 72% 38%, rgba(232, 198, 106, 0.10), rgba(0, 0, 0, 0) 55%),
    linear-gradient(160deg, #16131b 0%, #0b0b10 45%, #07070a 100%);
}
.mn-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    rgba(6, 6, 10, 0.92) 0%, rgba(6, 6, 10, 0.82) 26%,
    rgba(6, 6, 10, 0.35) 48%, rgba(6, 6, 10, 0) 70%);
}
.mn-vignette {
  position: absolute;
  inset: 0;
  box-shadow: inset 0 0 260px 90px rgba(4, 4, 8, 0.85);
  pointer-events: none;
}

/* One flush column: the logo, the rule, the tagline and every button share
   the same left and right edge. Children size off the panel, not their own
   hardcoded widths, so the column stays aligned if it is ever retuned. */
.mn-panel {
  position: absolute;
  left: 92px;
  top: 132px;
  width: 478px;
  display: flex;
  flex-direction: column;
}
#menuLogo {
  width: 100%;
  height: auto;
  display: block;
  filter: drop-shadow(0 6px 22px rgba(0, 0, 0, 0.85));
}
#menuLogo.missing { display: none; }
/* typographic wordmark stands in until the logo art is dropped in */
#menuWordmark {
  display: none;
  font-size: 78px;
  font-weight: 700;
  letter-spacing: 0.14em;
  line-height: 1;
  color: var(--mn-cream);
  text-shadow: 0 6px 22px rgba(0, 0, 0, 0.85), 0 0 40px rgba(232, 198, 106, 0.25);
}
#menuWordmark.show { display: block; }
#menuWordmark::first-letter { color: var(--mn-gold); }

.mn-rule {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 30px;
  width: 100%;
  opacity: 0.55;
}
.mn-rule i {
  width: 9px;
  height: 9px;
  background: var(--mn-gold);
  transform: rotate(45deg);
  opacity: 0.8;
}
.mn-rule span { flex: 1; height: 1px; background: rgba(232, 198, 106, 0.5); }
.mn-tag {
  margin-top: 18px;
  width: 100%;
  font-size: 20px;
  letter-spacing: 0.42em;
  color: rgba(239, 231, 216, 0.68);
  text-align: center;
}

.mn-field { margin-top: 30px; width: 100%; display: block; }
.mn-field-lbl {
  display: block;
  font-size: 13px;
  letter-spacing: 0.28em;
  color: rgba(239, 231, 216, 0.4);
  margin-bottom: 8px;
}
#nameInput {
  width: 100%;
  height: 52px;
  padding: 0 20px;
  background: rgba(12, 12, 16, 0.72);
  border: 1px solid rgba(239, 231, 216, 0.12);
  color: var(--mn-cream);
  font-family: var(--font-ui);
  font-size: 22px;
  letter-spacing: 0.14em;
  outline: none;
  transition: border-color 0.12s linear;
}
#nameInput::placeholder { color: rgba(239, 231, 216, 0.22); }
#nameInput:focus { border-color: rgba(232, 198, 106, 0.6); }

/* ---- menu buttons, from the "Main Menu" handoff -------------------------
   The same two shapes as every screen the menu leads to: a rectangle notched
   top-left and bottom-right, and a square turned 45 degrees. The markup was
   already the handoff's shape — dot, label, hint, and NAME REQUIRED swapped in
   when PLAY is gated — so this is styling only.

   Two layers without a wrapper element: the button IS the 1px gilt edge and
   ::before is its face. The edge is a gradient, which an inset border cannot
   be, and the gradient going gold is most of what the hover state is.

   The handoff's key art and wordmark PNG are not imported — the logo already
   in the game stays.                                                        */

.mn-items {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 26px;
  width: 100%;
}
.mn-item {
  position: relative;
  height: 56px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 20px;
  border: 0;
  border-radius: 0;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.045));
  clip-path: polygon(14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%, 0 14px);
  color: rgba(245, 236, 221, 0.85);
  font-family: var(--font-ui);
  text-align: left;
  cursor: pointer;
  transition: background 0.16s ease, box-shadow 0.16s ease;
}
.mn-item::before {
  content: '';
  position: absolute; inset: 1px;
  background: rgba(16, 13, 18, 0.9);
  clip-path: polygon(13px 0, 100% 0, 100% calc(100% - 13px), calc(100% - 13px) 100%, 0 100%, 0 13px);
}
/* the face is drawn by ::before, so the contents have to sit above it */
.mn-dot, .mn-label, .mn-hint { position: relative; z-index: 1; }

.mn-dot {
  width: 9px; height: 9px; flex: none;
  border-radius: 0;
  transform: rotate(45deg);
  background: rgba(217, 177, 96, 0.6);
  transition: background 0.16s ease, box-shadow 0.16s ease;
}
.mn-label {
  font: 700 17px var(--font-ui);
  letter-spacing: 0.22em;
  white-space: nowrap;
}
.mn-hint {
  margin-left: auto;
  font: 400 9.5px var(--font-ui);
  letter-spacing: 0.18em;
  color: rgba(255, 255, 255, 0.34);
  white-space: nowrap;
}

/* Selected — the keyboard cursor and the hover state are the same thing here,
   so this is what the handoff draws as its hovered button. */
.mn-item.sel {
  background: linear-gradient(160deg, #d9b160, rgba(217, 177, 96, 0.3));
  box-shadow: 0 0 40px -12px rgba(217, 177, 96, 0.65);
}
.mn-item.sel::before {
  background: linear-gradient(100deg, rgba(217, 177, 96, 0.2), rgba(217, 177, 96, 0.03)), rgba(16, 13, 18, 0.94);
}
.mn-item.sel .mn-dot { background: #f0d08a; box-shadow: 0 0 12px rgba(217, 177, 96, 0.9); }
.mn-item.sel .mn-label { color: #f5ecdd; text-shadow: 0 0 20px rgba(217, 177, 96, 0.5); }
.mn-item.sel .mn-hint { color: rgba(240, 208, 138, 0.85); font-weight: 500; }
/* the light that runs along the top edge of the one you are on */
.mn-item.sel::after {
  content: '';
  position: absolute; top: 1px; left: 1px;
  width: 22%; height: 2px;
  background: linear-gradient(90deg, transparent, #d9b160, transparent);
  animation: lobSweep 3.4s linear infinite;
  z-index: 1;
}
/* Gated until the wizard has a name — still focusable so it can explain why.
   Dimmed by stating each colour rather than by dropping the whole button's
   opacity: NAME REQUIRED is the one thing here that has to stay readable.

   AFTER the selected block, not before it. .mn-item.locked and .mn-item.sel
   are both two classes deep, so between them it is source order that decides —
   and with locked first, hovering a gated PLAY lit it gold, glow and all, and
   turned NAME REQUIRED the same gold as a live hint. */
.mn-item.locked {
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0.03));
  box-shadow: none;
  cursor: not-allowed;
}
.mn-item.locked::before { background: rgba(14, 11, 16, 0.8); }
.mn-item.locked .mn-dot { background: rgba(255, 255, 255, 0.16); box-shadow: none; }
.mn-item.locked .mn-label { color: rgba(255, 255, 255, 0.28); text-shadow: none; }
.mn-item.locked .mn-hint { color: rgba(224, 132, 116, 0.6); }
/* no light runs along a button you cannot press */
.mn-item.locked::after { display: none; }

/* hovered while gated: enough of an edge to show the cursor is on it, in the
   colour of the reason rather than the colour of a live button */
.mn-item.locked.sel { background: linear-gradient(160deg, rgba(224, 132, 116, 0.5), rgba(224, 132, 116, 0.12)); }
.mn-item.locked.sel .mn-dot { background: rgba(224, 132, 116, 0.7); box-shadow: none; }
.mn-item.locked.sel .mn-hint { color: rgba(224, 132, 116, 0.85); }

.mn-joinrow { display: flex; gap: 10px; }
.mn-joinrow.hidden { display: none; }
/* difficulty picker revealed under PRACTICE, same shape as the join row */
.mn-practicerow { display: flex; flex-direction: column; gap: 8px; padding: 2px 0 4px; }
.mn-practicerow.hidden { display: none; }
.mn-practicerow .mn-seg-note { text-align: center; }
#codeInput {
  flex: 1;
  height: 60px;
  padding: 0 20px;
  background: rgba(12, 12, 16, 0.72);
  border: 1px solid rgba(232, 198, 106, 0.4);
  color: var(--mn-gold);
  font-family: var(--font-ui);
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 0.5em;
  text-transform: uppercase;
  outline: none;
}
#codeInput::placeholder { font-size: 17px; letter-spacing: 0.24em; color: rgba(239, 231, 216, 0.22); font-weight: 400; }
#codeInput:focus { border-color: var(--mn-gold); }
.mn-go {
  flex: none;
  padding: 0 22px;
  background: rgba(232, 198, 106, 0.14);
  border: 1px solid var(--mn-gold);
  color: var(--mn-gold);
  font-family: var(--font-ui);
  font-size: 16px;
  letter-spacing: 0.16em;
  cursor: pointer;
}
.mn-go:hover { background: rgba(232, 198, 106, 0.26); }

.mn-error {
  margin-top: 18px;
  width: 100%;
  font-size: 16px;
  letter-spacing: 0.1em;
  color: #e0604f;
}

.mn-foot {
  position: absolute;
  bottom: 30px;
  font-size: 15px;
  letter-spacing: 0.2em;
  color: rgba(239, 231, 216, 0.38);
}
.mn-foot-l { left: 40px; }
.mn-foot-r { right: 40px; display: flex; gap: 26px; }

/* ---- menu dialogs (settings / credits) ---- */
.mn-modal {
  position: absolute;
  inset: 0;
  background: rgba(4, 4, 8, 0.78);
  backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: wzFade 0.14s linear;
  z-index: 5;
}
.mn-modal.hidden { display: none; }
@keyframes wzFade { from { opacity: 0; } to { opacity: 1; } }
.mn-dialog {
  width: 1180px;
  height: 800px;
  background: rgba(11, 11, 15, 0.97);
  border: 1px solid rgba(232, 198, 106, 0.3);
  box-shadow: 0 40px 120px rgba(0, 0, 0, 0.8);
  display: flex;
  flex-direction: column;
}
.mn-dialog.narrow { width: 760px; height: auto; padding: 44px 44px 36px; text-align: center; }
/* Settings sits outside the menu stage so ESC can open it mid-match. Nothing
   scales it out there, so it sizes to the viewport instead of to 1920x1080. */
#settingsModal { position: fixed; z-index: 450; }
#settingsModal .mn-dialog { width: min(1180px, 94vw); height: min(800px, 90vh); }
.mn-dlg-head {
  display: flex;
  align-items: center;
  padding: 30px 36px;
  border-bottom: 1px solid rgba(239, 231, 216, 0.1);
}
.mn-diamond { width: 11px; height: 11px; background: var(--mn-gold); transform: rotate(45deg); margin-right: 18px; }
.mn-dlg-title { font-size: 26px; font-weight: 700; letter-spacing: 0.26em; }
.mn-dlg-title.center { letter-spacing: 0.22em; }
.mn-x {
  margin-left: auto;
  width: 46px;
  height: 46px;
  border: 1px solid rgba(239, 231, 216, 0.18);
  background: none;
  color: rgba(239, 231, 216, 0.7);
  font-family: var(--font-ui);
  font-size: 20px;
  cursor: pointer;
}
.mn-x:hover { border-color: rgba(232, 198, 106, 0.6); color: var(--mn-gold); }
.mn-dlg-body { display: flex; flex: 1; min-height: 0; }
.mn-tabs {
  width: 280px;
  border-right: 1px solid rgba(239, 231, 216, 0.1);
  padding: 24px 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.mn-tab {
  padding: 20px 30px;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: 19px;
  letter-spacing: 0.18em;
  text-align: left;
  background: none;
  border: none;
  border-left: 3px solid transparent;
  color: rgba(239, 231, 216, 0.55);
}
.mn-tab.on { background: rgba(232, 198, 106, 0.1); color: var(--mn-gold); border-left-color: var(--mn-gold); }
.mn-rows { flex: 1; padding: 30px 40px; overflow-y: auto; display: flex; flex-direction: column; gap: 26px; }
.mn-row {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-bottom: 22px;
  border-bottom: 1px solid rgba(239, 231, 216, 0.07);
}
.mn-row-head { display: flex; align-items: baseline; gap: 14px; }
.mn-row-label { font-size: 20px; letter-spacing: 0.1em; }
.mn-row-value { margin-left: auto; font-size: 18px; letter-spacing: 0.12em; color: var(--mn-gold); }
/* loading screen — sits over the menu until the art it needs has arrived,
   because a menu with no background reads as broken rather than as loading */
#loader {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at 50% 45%, #171a30 0%, #07080f 100%);
  transition: opacity 0.45s ease;
}
#loader.done { opacity: 0; pointer-events: none; }
#loader.gone { display: none; }
.ld-inner { width: min(420px, 74vw); text-align: center; }
.ld-title {
  font-family: var(--font-display, 'Cinzel', serif);
  font-size: 34px;
  letter-spacing: 0.34em;
  color: var(--mn-gold, #e8c66a);
  margin-bottom: 26px;
  text-indent: 0.34em;          /* letter-spacing pads the right; re-centre */
}
.ld-bar {
  height: 6px;
  background: rgba(239, 231, 216, 0.12);
  border-radius: 3px;
  overflow: hidden;
}
.ld-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #c9a24a, #e8c66a);
  transition: width 0.25s ease;
}
.ld-text {
  margin-top: 16px;
  font-size: 13px;
  letter-spacing: 0.16em;
  color: rgba(239, 231, 216, 0.5);
}

/* leaderboard table */
.mn-leaders { max-height: 46vh; overflow-y: auto; padding: 4px 2px; }
.mn-lb-row {
  display: grid;
  grid-template-columns: 44px 1fr 62px 62px 54px;
  align-items: center;
  gap: 8px;
  padding: 9px 10px;
  font-size: 15px;
  border-bottom: 1px solid rgba(239, 231, 216, 0.07);
}
.mn-lb-row.head {
  font-size: 12px;
  letter-spacing: 0.14em;
  color: rgba(239, 231, 216, 0.45);
  border-bottom: 1px solid rgba(232, 198, 106, 0.3);
}
.mn-lb-row.me { background: rgba(232, 198, 106, 0.1); }
.mn-lb-rank { color: var(--mn-gold); font-weight: 700; }
.mn-lb-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mn-lb-num { text-align: right; font-variant-numeric: tabular-nums; }
.mn-lb-streak { text-align: right; color: rgba(239, 231, 216, 0.55); }
.mn-leaders-empty {
  padding: 30px 10px;
  text-align: center;
  color: rgba(239, 231, 216, 0.5);
  line-height: 1.6;
}
.mn-leaders::-webkit-scrollbar { width: 8px; }
.mn-leaders::-webkit-scrollbar-thumb { background: rgba(201, 162, 74, 0.4); border-radius: 4px; }

/* segmented picker for choice rows — reuses .mn-tab, but the sidebar version is
   a tall left-aligned strip, so the box/centring is overridden here */
.mn-seg { display: flex; gap: 10px; margin-top: 4px; }
.mn-seg .mn-tab {
  flex: 1;
  padding: 12px 8px;
  text-align: center;
  font-size: 15px;
  letter-spacing: 0.12em;
  border: 1px solid rgba(232, 198, 106, 0.25);
  background: rgba(0, 0, 0, 0.2);
}
.mn-seg .mn-tab.on {
  border-color: var(--mn-gold);
  background: rgba(232, 198, 106, 0.14);
}
.mn-seg-note { font-size: 14px; letter-spacing: 0.03em; color: rgba(239, 231, 216, 0.5); }
.mn-slider { height: 34px; display: flex; align-items: center; cursor: pointer; margin-top: 4px; }
.mn-track { position: relative; width: 100%; height: 6px; background: rgba(239, 231, 216, 0.12); }
.mn-fill { position: absolute; left: 0; top: 0; bottom: 0; background: var(--mn-gold); }
.mn-knob { position: absolute; top: 50%; width: 14px; height: 22px; margin: -11px 0 0 -7px; background: var(--mn-cream); }
.mn-toggle {
  margin-top: 6px;
  width: 92px;
  height: 38px;
  position: relative;
  cursor: pointer;
  border: 1px solid rgba(239, 231, 216, 0.2);
  background: rgba(239, 231, 216, 0.05);
  padding: 0;
}
.mn-toggle .mn-tknob {
  position: absolute;
  top: 4px;
  left: 4px;
  width: 38px;
  height: 28px;
  background: rgba(239, 231, 216, 0.35);
  transition: left 0.12s linear;
}
.mn-toggle.on { border-color: var(--mn-gold); background: rgba(232, 198, 106, 0.16); }
.mn-toggle.on .mn-tknob { left: 50px; background: var(--mn-gold); }
.mn-keys { display: flex; flex-direction: column; gap: 12px; }
.mn-keyrow { display: flex; align-items: center; gap: 10px; font-size: 16px; letter-spacing: 0.08em; color: rgba(239, 231, 216, 0.66); }
.mn-keyrow .k { background: rgba(232, 198, 106, 0.85); color: #14100d; font-family: var(--font-ui); }
.mn-dlg-foot {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 24px 36px;
  border-top: 1px solid rgba(239, 231, 216, 0.1);
}
.mn-saved { font-size: 15px; letter-spacing: 0.14em; color: rgba(239, 231, 216, 0.38); }
.mn-btn {
  padding: 14px 34px;
  border: 1px solid rgba(239, 231, 216, 0.2);
  background: none;
  color: rgba(239, 231, 216, 0.75);
  font-family: var(--font-ui);
  font-size: 18px;
  letter-spacing: 0.18em;
  cursor: pointer;
}
.mn-btn:hover { border-color: rgba(232, 198, 106, 0.6); color: var(--mn-gold); }
.mn-btn.primary { border-color: var(--mn-gold); background: rgba(232, 198, 106, 0.14); color: var(--mn-gold); }
.mn-btn.primary:hover { background: rgba(232, 198, 106, 0.26); }
.mn-btn.wide { width: 100%; padding: 18px 0; font-size: 19px; }
.mn-dlg-foot .mn-btn:nth-of-type(1) { margin-left: auto; }
.mn-credits { margin-top: 22px; text-align: left; }
.mn-credits p { margin: 0 0 16px; font-size: 17px; line-height: 1.7; color: rgba(239, 231, 216, 0.62); letter-spacing: 0.04em; }
.mn-credits b { color: var(--mn-cream); letter-spacing: 0.14em; }
.mn-credits a { color: var(--mn-gold); text-decoration: none; }
.mn-credits a:hover { color: #ffe6a1; text-decoration: underline; }
.mn-cred-k {
  display: inline-block;
  min-width: 96px;
  font-size: 13px;
  letter-spacing: 0.2em;
  color: rgba(239, 231, 216, 0.35);
}
.mn-dlg-actions { margin-top: 26px; }

/* ================= HUD: PORTRAIT · WARD · ABILITIES ======================
   From the "HUD Ability Bar" handoff. The rack was the last surface still
   built from carved stone and brass plates while every screen around it had
   moved to notched rectangles and diamonds — you left the draft, the fight
   began, and the furniture changed.

   The element colours stay. They are the one thing on this bar that is
   information rather than decoration: they live on the icon diamond's edge,
   where the old stone tile carried them.                                    */

#playerBar {
  position: fixed;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  z-index: 10;
  display: flex;
  align-items: flex-end;
  gap: 16px;
}
#pbStack {
  display: flex;
  flex-direction: column;
  align-items: stretch;   /* the ward bar spans the rack's width */
  gap: 12px;
}

/* ---- portrait: notched on all four corners ---- */
#portrait {
  position: relative;
  flex: none;
  padding: 2px;
  background: linear-gradient(160deg, rgba(217, 177, 96, 0.85), rgba(217, 177, 96, 0.18) 40%,
                              rgba(217, 177, 96, 0.1) 62%, rgba(217, 177, 96, 0.7));
  clip-path: polygon(14px 0, calc(100% - 14px) 0, 100% 14px, 100% calc(100% - 14px),
                     calc(100% - 14px) 100%, 14px 100%, 0 calc(100% - 14px), 0 14px);
  box-shadow: 0 0 40px -14px rgba(217, 177, 96, 0.55);
}
.pt-in {
  width: 132px;
  background: linear-gradient(180deg, #181118, #0d0a0e);
  clip-path: polygon(13px 0, calc(100% - 13px) 0, 100% 13px, 100% calc(100% - 13px),
                     calc(100% - 13px) 100%, 13px 100%, 0 calc(100% - 13px), 0 13px);
}
.pt-head { padding: 9px 8px 7px; text-align: center; border-bottom: 1px solid rgba(217, 177, 96, 0.22); }
.pt-class {
  font: 700 10px var(--font-display);
  letter-spacing: 0.14em;
  color: #f0d08a;
  white-space: nowrap;
}
.pt-art {
  position: relative;
  height: 104px;
  overflow: hidden;
  display: grid; place-items: center;
  background:
    radial-gradient(70% 60% at 50% 45%, rgba(217, 177, 96, 0.15), transparent 72%),
    repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.016) 0 8px, transparent 8px 16px);
}
.pt-ring {
  position: absolute; left: 50%; top: 14px;
  width: 76px; height: 76px; margin-left: -38px;
  border: 1px solid rgba(217, 177, 96, 0.24);
  border-radius: 50%;
  pointer-events: none;
}
.pt-art img {
  position: relative; z-index: 1;
  max-width: 76%; max-height: 88%;
  width: auto; height: auto;
  object-fit: contain;
  image-rendering: pixelated;
}
.pt-corner { position: absolute; width: 15px; height: 15px; pointer-events: none; z-index: 2; }
.pt-corner.tl { top: 6px; left: 6px; border-top: 1px solid rgba(217, 177, 96, 0.6); border-left: 1px solid rgba(217, 177, 96, 0.6); }
.pt-corner.tr { top: 6px; right: 6px; border-top: 1px solid rgba(217, 177, 96, 0.6); border-right: 1px solid rgba(217, 177, 96, 0.6); }
.pt-foot {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 8px 8px 9px;
  border-top: 1px solid rgba(217, 177, 96, 0.22);
}
.pt-dia { width: 6px; height: 6px; flex: none; border: 1px solid rgba(217, 177, 96, 0.6); transform: rotate(45deg); }
.pt-lv { font: 700 11px var(--font-ui); letter-spacing: 0.18em; color: #f5ecdd; white-space: nowrap; }

/* ---- the ward ---- */
#healthBar {
  position: relative;
  padding: 1px;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: linear-gradient(160deg, rgba(217, 177, 96, 0.6), rgba(217, 177, 96, 0.14));
  clip-path: polygon(11px 0, 100% 0, 100% calc(100% - 11px), calc(100% - 11px) 100%, 0 100%, 0 11px);
}
.hp-in {
  position: relative;
  height: 26px;
  overflow: hidden;
  background: #0f0c11;
  clip-path: polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
}
/* The ward you have left, in gold. It was a 32%-alpha wash under a hatch that
   ran the full width of the track, so the two halves of the bar looked the
   same and the only real readout was the number. The gold is strong enough to
   see now, the hatch belongs to the EMPTY part alone, and a lit edge marks
   exactly where the ward ends.

   Kept translucent rather than solid: the caption sits on top of it and has to
   stay readable whether the fill is behind it or not. At this weight the
   filled ground is about #6e5c3a, which carries the cream text at ~6:1. */
#healthFill {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 100%;
  z-index: 1;
  border-radius: 0;
  /* OPAQUE, the same colour the translucent version blended to over the
     track (~#6e5c3a). Translucent, the empty-track hatch showed through the
     filled part too — crisply on a 1080p screen, blurred away at 150% on a
     4K — so host and guest saw two different bars. */
  background: linear-gradient(180deg, #7b6742, #5f4d30);
  border-right: 2px solid #f0d08a;
  box-shadow: 0 0 12px rgba(217, 177, 96, 0.45);
  transition: width 0.18s ease;
}
/* at full ward there is no boundary to mark, and the edge would sit on the frame */
#healthBar.full #healthFill { border-right-color: transparent; box-shadow: none; }
/* Under a quarter it stops being a gold bar and becomes a warning. This is the
   one place the palette is allowed to break — you have to be able to read it
   without looking at it. */
#healthBar.low #healthFill {
  background: linear-gradient(180deg, rgba(224, 96, 79, 0.7), rgba(140, 36, 25, 0.45));
  border-right-color: #ff9a8a;
  box-shadow: 0 0 14px rgba(224, 96, 79, 0.45);
}
/* the empty track's texture — under the fill, so it reads as what is GONE */
.hp-hatch {
  position: absolute; inset: 0; pointer-events: none;
  z-index: 0;
  background: repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.05) 0 7px, transparent 7px 14px);
}
.hp-sweep {
  position: absolute; top: 0; left: 0; z-index: 2;
  width: 22%; height: 2px;
  background: linear-gradient(90deg, transparent, #d9b160, transparent);
  animation: lobSweep 3.4s linear infinite;
}
.hp-row {
  position: relative; z-index: 3; height: 100%;
  display: flex; align-items: center; justify-content: center; gap: 10px;
}
.hp-lbl { font: 400 8.5px var(--font-ui); letter-spacing: 0.22em; color: rgba(245, 236, 221, 0.6); }
.hp-dia { width: 5px; height: 5px; flex: none; border: 1px solid rgba(217, 177, 96, 0.7); transform: rotate(45deg); }
#healthText {
  position: static;
  display: block;
  font: 700 12px var(--font-ui);
  letter-spacing: 0.14em;
  color: #f5ecdd;
  /* the caption crosses the boundary as the ward drops, so it needs to hold
     against both the gold and the empty track behind it */
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
}
.hp-lbl { text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85); }

/* ---- the ability rack ---- */
#spellbar { display: flex; gap: 9px; align-items: stretch; justify-content: center; }

.spell {
  position: relative;
  flex: none;
  width: auto; height: auto;
  padding: 1px;
  border: 0;
  border-radius: 0;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.05));
  clip-path: polygon(12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%, 0 12px);
  box-shadow: none;
  cursor: pointer;
  transition: background 0.16s ease, box-shadow 0.16s ease;
}
.spell:hover { background: linear-gradient(160deg, #d9b160, rgba(217, 177, 96, 0.3)); }
.sp-in {
  position: relative;
  width: 96px;
  background: #100d12;
  clip-path: polygon(11px 0, 100% 0, 100% calc(100% - 11px), calc(100% - 11px) 100%, 0 100%, 0 11px);
  padding: 7px 8px 9px;
}
.sp-top { display: flex; align-items: center; justify-content: space-between; gap: 6px; min-height: 15px; }

/* the keycap */
.spell .hotkey {
  position: static;
  padding: 2px 6px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 0;
  background: none;
  clip-path: polygon(4px 0, 100% 0, 100% calc(100% - 4px), calc(100% - 4px) 100%, 0 100%, 0 4px);
  font: 500 8.5px var(--font-ui);
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.55);
  white-space: nowrap;
}
/* rank in the opposite corner, as a number */
.spell .rank {
  position: static;
  font: 700 11px var(--font-ui);
  color: rgba(240, 208, 138, 0.85);
  letter-spacing: 0;
  text-shadow: none;
}

/* the icon frame is a diamond, so whatever is in it is turned back */
.sp-orb {
  position: relative;
  width: 38px; height: 38px;
  margin: 10px auto 0;
  border: 1px solid rgba(255, 255, 255, 0.26);
  transform: rotate(45deg);
  display: flex; align-items: center; justify-content: center;
}
.sp-orb > * { transform: rotate(-45deg); }
.spell .icon { font-size: 17px; line-height: 1; }
.spell .icon-img { width: 22px; height: 22px; object-fit: contain; image-rendering: pixelated; filter: none; }

.sp-rule { display: block; margin: 12px auto 0; width: 60%; height: 1px; background: rgba(255, 255, 255, 0.09); }
.sp-name {
  margin-top: 8px;
  text-align: center;
  font: 700 10.5px var(--font-ui);
  letter-spacing: 0.06em;
  color: rgba(245, 236, 221, 0.95);
  /* One line, never wider than its cell. A name that does not fit is clipped
     rather than allowed to push the rack apart — the cells are a fixed width
     and a two-line caption would make one of them taller than the rest. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.spell .label { text-transform: uppercase; }
/* What it costs to open the slot. Inline, in front of the name, is where the
   handoff puts it — and where it fits the example it draws, SCTR. With the
   real names it does not: twelve of this game's twenty labels overran a 96px
   cell that way, up to 101px for "1 PT · STAFF SWING", and an ellipsis across
   half the bar is worse than either. It goes in the corner the rank number
   leaves empty on a locked slot, and the name keeps its own line intact.

   The sealed ultimate is the exception. Its corner is taken by ULT and its
   name is on the draft screen, so RND 4 stays as the caption. */
.spell .lock-cap { color: rgba(255, 255, 255, 0.55); }
.spell .lock-cap:empty { display: none; }
.spell .lock-cap:not(:empty)::after { content: ' \00B7 '; }
.spell.locked:not(.sealed) .lock-cap:not(:empty) {
  position: absolute;
  top: 7px; right: 8px;
  font: 600 9px/15px var(--font-ui);
  letter-spacing: 0.08em;
}
.spell.locked:not(.sealed) .lock-cap:not(:empty)::after { content: ''; }

/* the rule that separates baseline kit · drafted abilities · ultimate */
.spell.section-start, .spell.ult-start { margin-left: 13px; }
.spell.section-start::before, .spell.ult-start::before {
  content: '';
  position: absolute;
  left: -9px; top: 0; bottom: 0;
  width: 1px;
  background: linear-gradient(180deg, transparent, rgba(217, 177, 96, 0.35), transparent);
}

/* ---- states ------------------------------------------------------------- */

/* off cooldown and castable: gold edge, lit diamond */
.spell.ready {
  background: linear-gradient(160deg, #d9b160, rgba(217, 177, 96, 0.28));
  box-shadow: 0 0 30px -10px rgba(217, 177, 96, 0.6);
}
.spell.ready .sp-in { background: linear-gradient(180deg, rgba(217, 177, 96, 0.14), rgba(217, 177, 96, 0.02)), #100d12; }
.spell.ready .hotkey {
  border: 0;
  background: linear-gradient(160deg, #f0d08a, #d9b160);
  color: #120f0a;
  font-weight: 700;
}
.spell.ready .sp-orb { background: rgba(217, 177, 96, 0.12); box-shadow: 0 0 20px -6px rgba(217, 177, 96, 0.6); }
.spell.ready .sp-rule { background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.45), transparent); }
.spell.ready .sp-name { color: #f5ecdd; }

/* the ultimate is wider and gold-tinted whatever its state */
.spell.tier-ultimate { width: auto; height: auto; background: linear-gradient(160deg, rgba(217, 177, 96, 0.7), rgba(217, 177, 96, 0.18)); }
.spell.tier-ultimate .sp-in { width: 112px; background: linear-gradient(180deg, rgba(217, 177, 96, 0.08), rgba(255, 255, 255, 0.006)), #100d12; }
.spell.tier-ultimate .hotkey { border-color: rgba(217, 177, 96, 0.5); color: #f0d08a; font-weight: 700; }
.spell.tier-ultimate .sp-orb { border-color: rgba(217, 177, 96, 0.45); background: rgba(217, 177, 96, 0.07); }
.spell.tier-ultimate .sp-rule { background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.35), transparent); }
.spell.tier-ultimate .sp-name { color: #f0d08a; }
.spell.tier-ultimate .icon { font-size: 19px; }
.spell.tier-ultimate .icon-img { width: 24px; height: 24px; }
/* A ready ultimate takes the SOLID GOLD keycap from .ready and then the GOLD
   TEXT from .tier-ultimate. Both are three classes deep, so source order
   decided it and the letter vanished into its own background — the F on a lit
   Fire Cannon was an empty gold block.

   Four classes, so it beats both, and it only has to restate the one property
   the collision destroyed. */
.spell.ready.tier-ultimate .hotkey { color: #120f0a; }

/* locked: nothing spent on it, and the frame around the icon says so */
.spell.locked {
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.03));
  box-shadow: none;
  cursor: not-allowed;
}
.spell.locked:hover { background: linear-gradient(160deg, rgba(217, 177, 96, 0.5), rgba(217, 177, 96, 0.14)); }
.spell.locked .sp-in {
  background: repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.02) 0 8px, transparent 8px 16px), #0d0a0f;
}
.spell.locked .hotkey { border-color: rgba(255, 255, 255, 0.2); background: none; color: rgba(255, 255, 255, 0.5); font-weight: 500; }
.spell.locked .sp-orb {
  border: 1px dashed rgba(255, 255, 255, 0.18) !important;
  background: none;
  box-shadow: none;
}
.spell.locked .icon, .spell.locked .icon-img { opacity: 0.3; filter: grayscale(1); }
.spell.locked .sp-rule { background: rgba(255, 255, 255, 0.06); }
/* the price plus the name is the longest caption on the bar — 1 PT · SCATTER
   overran a 96px cell by 7px at the tracking the live cells use */
.spell.locked .sp-name { font-weight: 600; font-size: 10px; letter-spacing: 0.04em; color: rgba(255, 255, 255, 0.55); }

/* sealed: a locked ULTIMATE, which is waiting on the round rather than a point */
.spell.locked.sealed { background: linear-gradient(160deg, rgba(217, 177, 96, 0.35), rgba(255, 255, 255, 0.04)); }
.spell.locked.sealed .sp-in {
  background: repeating-linear-gradient(115deg, rgba(217, 177, 96, 0.03) 0 8px, transparent 8px 16px), #0d0a0f;
}
.spell.locked.sealed .hotkey { border-color: rgba(217, 177, 96, 0.35); color: rgba(240, 208, 138, 0.7); }
.spell.locked.sealed .sp-orb {
  border: 1px solid rgba(217, 177, 96, 0.35) !important;
  background: rgba(217, 177, 96, 0.05);
}
.spell.locked.sealed .icon, .spell.locked.sealed .icon-img { opacity: 0.55; filter: none; }
.spell.locked.sealed .sp-rule { background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.28), transparent); }
.spell.locked.sealed .sp-name { color: rgba(240, 208, 138, 0.9); }
/* the corner carries the round it opens; the caption is its name, like every
   other cell on the bar */
.spell.locked.sealed .rank { font: 600 8.5px var(--font-ui); letter-spacing: 0.14em; color: rgba(240, 208, 138, 0.9); }

/* the element colours, on the icon frame where the stone tile used to carry
   them — the one thing on this bar that is information, not decoration */
.spell.fireball  .sp-orb { border-color: var(--fireball); }
.spell.oil       .sp-orb { border-color: var(--oil); }
.spell.ignite    .sp-orb { border-color: var(--ignite); }
.spell.tesla     .sp-orb { border-color: var(--tesla); }
.spell.ice       .sp-orb { border-color: var(--ice); }
.spell.tornado   .sp-orb { border-color: var(--tornado); }
.spell.shield    .sp-orb { border-color: var(--shield); }
.spell.dash      .sp-orb { border-color: var(--dash); }
.spell.trap      .sp-orb { border-color: var(--trap); }
.spell.scatter   .sp-orb { border-color: var(--scatter); }
.spell.boomerang .sp-orb { border-color: var(--boomerang); }
.spell.nova      .sp-orb { border-color: var(--nova); }
.spell.frostbolt .sp-orb { border-color: var(--frostbolt); }
.spell.fissure   .sp-orb { border-color: var(--fissure); }
.spell.stoneskin .sp-orb { border-color: var(--stoneskin); }
.spell.updraft   .sp-orb { border-color: var(--updraft); }
.spell.slipstream .sp-orb { border-color: var(--slipstream); }
.spell.meteor    .sp-orb { border-color: var(--meteor); }
.spell.blizzard  .sp-orb { border-color: var(--blizzard); }
.spell.quake     .sp-orb { border-color: var(--quake); }
.spell.hurricane .sp-orb { border-color: var(--hurricane); }
.spell.firecannon .sp-orb { border-color: var(--firecannon); }
.spell.swing     .sp-orb { border-color: var(--swing); }

/* ---- cooldown: a clock sweep over the whole cell, seconds on top ---- */
.spell .cd-fill {
  position: absolute;
  inset: 0;
  border-radius: 0;
  background: conic-gradient(rgba(8, 6, 10, 0.82) 0 var(--sweep, 0deg),
                             rgba(8, 6, 10, 0) var(--sweep, 0deg) 360deg);
  pointer-events: none;
}
.spell .cd-text {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 700 22px var(--font-ui);
  color: #f5ecdd;
  text-shadow: 0 2px 6px #000;
  pointer-events: none;
}
/* banked uses for a charge ability, pinned to the icon it belongs to */
.spell .charges {
  position: absolute;
  right: -7px; bottom: -7px;
  min-width: 15px; height: 15px;
  display: grid; place-items: center;
  background: #100d12;
  box-shadow: inset 0 0 0 1px rgba(217, 177, 96, 0.55);
  clip-path: polygon(4px 0, 100% 0, 100% calc(100% - 4px), calc(100% - 4px) 100%, 0 100%, 0 4px);
  font: 700 9px var(--font-ui);
  color: #f0d08a;
  text-shadow: none;
  z-index: 3;
}
.spell .charges:empty { display: none; }

/* "can't cast — locked" shake */
.spell.denied { animation: spellDeny 0.32s ease; }
@keyframes spellDeny {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}

#respawn {
  position: fixed;
  top: 46%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 26px;
  font-weight: 700;
  color: #ff6b6b;
  text-shadow: 0 2px 12px rgba(0,0,0,0.6);
  z-index: 10;
}

.status {
  position: fixed;
  bottom: 8px;
  left: 10px;
  font-size: 12px;
  color: #6b70a0;
  z-index: 10;
}

/* ---------- Chat ----------
   Chat outranks the HUD *and* the round overlays (z 20). The between-round
   panel is exactly when people talk, and at z 11 the feed and the input both
   sat behind it — you could open chat during an intermission and type blind.
   Only the menu and the countdown (z 30) still cover it. */
#chatFeed {
  position: fixed;
  bottom: 70px;
  left: 12px;
  z-index: 25;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: min(380px, 46vw);
  pointer-events: none;
}
.chat-row {
  background: rgba(10, 12, 26, 0.6);
  border-radius: 8px;
  padding: 3px 9px;
  width: fit-content;
  max-width: 100%;
  font-size: 13px;
  color: #e2e5ff;
  line-height: 1.3;
  word-break: break-word;
  transition: opacity 0.9s ease;
}
.chat-row.fade { opacity: 0; }
/* Expired rows stay in the DOM as history but take up no space during play. */
.chat-row.stale { display: none; }
/* While the chat input is open the feed becomes a scrollable log and the whole
   backlog comes back. pointer-events is re-enabled so it can be scrolled —
   the feed is otherwise click-through so it never eats aiming clicks. */
#chatFeed.log {
  max-height: 42vh;
  overflow-y: auto;
  pointer-events: auto;
  background: rgba(8, 6, 4, 0.72);
  border: 1px solid var(--brass);
  border-radius: 10px;
  padding: 8px;
}
#chatFeed.log .chat-row.stale { display: block; }
#chatFeed.log .chat-row { opacity: 1; }        /* cancel any in-flight fade */
#chatFeed.log::-webkit-scrollbar { width: 8px; }
#chatFeed.log::-webkit-scrollbar-thumb {
  background: rgba(201, 162, 74, 0.4);
  border-radius: 4px;
}
.chat-name { font-weight: 700; }
#chatInput {
  position: fixed;
  bottom: 34px;
  left: 12px;
  width: min(360px, 46vw);
  z-index: 26;   /* one above the feed, same reasoning */
  padding: 8px 12px;
  border-radius: 8px;
  border: 2px solid var(--brass-lit);
  background: rgba(8, 6, 4, 0.92);
  color: var(--parchment);
  font-family: var(--font-body);
  font-size: 14px;
  outline: none;
}
#chatInput::placeholder { color: rgba(239, 227, 200, 0.4); }

/* ---------- Pre-round countdown ---------- */
#countdown {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex; flex-direction: column;   /* the number, then the round-one hint under it */
  align-items: center;
  justify-content: center;
  background: rgba(6, 8, 16, 0.4);   /* dim the arena to 40% */
  pointer-events: none;
}
#countdown.fight { background: transparent; } /* FIGHT flashes over the game */
#countNum {
  font-family: 'Segoe UI', system-ui, sans-serif;
  font-weight: 900;
  font-size: 190px;
  line-height: 1;
  color: #ffd24d;
  text-shadow: 0 0 30px rgba(255, 180, 40, 0.85), 0 6px 14px rgba(0, 0, 0, 0.6);
}
#countdown.fight #countNum {
  font-size: 130px;
  letter-spacing: 8px;
  color: #fff2b0;
  text-shadow: 0 0 34px rgba(255, 160, 30, 0.95), 0 6px 16px #000;
}
#countNum.pop { animation: countPop 0.5s cubic-bezier(0.2, 1.4, 0.5, 1); }
/* round one only, under the number: why two of your three abilities are dark */
#countHint {
  margin-top: 18px;
  padding: 8px 16px;
  font: 700 12px var(--font-ui); letter-spacing: 0.2em;
  color: #f0d08a;
  background: rgba(12, 10, 14, 0.85);
  border: 1px solid rgba(217, 177, 96, 0.45);
  clip-path: polygon(9px 0, 100% 0, 100% calc(100% - 9px), calc(100% - 9px) 100%, 0 100%, 0 9px);
  text-align: center;
  max-width: 80vw;
}
#countHint.hidden { display: none; }
@keyframes countPop {
  0%   { transform: scale(0.35); opacity: 0; }
  45%  { transform: scale(1.18); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* ---------- Round banner ---------- */
/* Top banner. Two forms: a message plaque (waiting / drafting) and the score
   plaque that hangs off the top edge of the screen during a round. */
#roundBanner {
  position: fixed;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  text-align: center;
}
#roundBanner.msg {
  top: 14px;
  background: linear-gradient(#332b23, #1b1611);
  border: 1px solid var(--brass);
  border-radius: 8px;
  padding: 8px 18px;
  font: 600 14px/1.35 var(--font-body);
  color: var(--parchment);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
}
#roundBanner .sub { font: 400 11px var(--font-body); color: rgba(239, 227, 200, 0.6); }
#roundBanner b { color: var(--gold-text); }

.rb-plaque {
  display: flex;
  align-items: stretch;
  margin-top: 12px;        /* breathing room from the screen edge */
  background: linear-gradient(#332b23, #1b1611);
  border: 1px solid var(--brass);
  border-radius: 0 0 8px 8px;   /* flat top, rounded base — reads as a hung sign */
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
}
.rb-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 8px 20px 9px;
  gap: 2px;
}
.rb-score { font: 900 26px/1 var(--font-display); }
.rb-score.me { color: var(--frost-blue); }
.rb-score.foe { color: var(--blood); }
.rb-tag { font: 600 8px var(--font-mono); letter-spacing: 0.18em; color: rgba(239, 227, 200, 0.45); }
.rb-rounds { font: 600 17px/1 var(--font-mono); color: var(--parchment); letter-spacing: 0.04em; }
.rb-tag.gold { color: rgba(201, 162, 74, 0.7); }
.rb-div {
  width: 1px;
  background: linear-gradient(rgba(201, 162, 74, 0), rgba(201, 162, 74, 0.55), rgba(201, 162, 74, 0));
}

/* ---------- Intermission / upgrades ---------- */
.intermission-panel { width: 540px; }
.intermission-panel h2 {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 28px;
  letter-spacing: 0.05em;
  color: var(--gold-text);
}
/* win/lose stay green/red — outcome must not be a shade of the same gold */
.intermission-panel h2.win { color: var(--hp-hi); }
.intermission-panel h2.lose { color: #e0604f; }

.points-line {
  margin: 14px 0 6px;
  font-family: var(--font-mono);
  font-size: 15px;
  letter-spacing: 0.08em;
  color: var(--gold-bright);
  font-weight: 700;
}

/* The pre-handoff upgrade cards used to be styled here — flat brass tiles,
   142px wide, rounded. Every rule was superseded by the ROUND RESULT block
   below, and the three that were not (a locked card dimmed to 0.92, a tinted
   pill behind the badge row, a gold .u-cat) only leaked through. Deleted
   rather than overridden: that is the same trap the loadout cards fell into. */

.next-round {
  margin-top: 16px;
  font-family: var(--font-body);
  font-size: 14px;
  color: rgba(239, 227, 200, 0.6);
}
.next-round b { color: var(--gold-text); font-size: 18px; transition: color 0.15s linear; }
/* final seconds: the number goes red and beats once a second, so it reads as
   "commit now" rather than as a passive readout you can keep ignoring */
.next-round.urgent { color: rgba(224, 96, 79, 0.75); }
.next-round.urgent b {
  color: #ff5a3c;
  font-size: 22px;
  text-shadow: 0 0 12px rgba(255, 90, 60, 0.55);
  animation: nextRoundPulse 1s steps(1, end) infinite;
  display: inline-block;
}
@keyframes nextRoundPulse {
  0%   { transform: scale(1.18); }
  50%  { transform: scale(1); }
  100% { transform: scale(1); }
}

/* ---------- Loadout draft ----------
   The backdrop the panel sits on. The panel itself is in the LOADOUT block at
   the end of this file; this is the room around it. */
#loadout.overlay {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 24px;
  overflow: auto;
  background: radial-gradient(80% 60% at 50% 0%, #191118 0%, #0b090c 55%, #08070a 100%);
}
#loadout.overlay::before {
  content: '';
  position: absolute; inset: 0;
  opacity: 0.5;
  background-image:
    repeating-linear-gradient(52deg, rgba(233,207,149,0.020) 0 2px, transparent 2px 9px),
    repeating-linear-gradient(-38deg, rgba(201,162,74,0.014) 0 1px, transparent 1px 14px);
}

.ld-panel {
  position: absolute;
  left: 200px; top: 56px;
  width: 1280px;
  border: 1px solid var(--brass);
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(58,49,40,0.97) 0%, rgba(20,16,13,0.98) 100%);
  box-shadow: 0 40px 90px rgba(0,0,0,0.65), inset 0 1px 0 rgba(233,207,149,0.08);
  font-family: var(--font-body);
}

.ld-head { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 30px 0 24px; }
.ld-title {
  display: flex; align-items: center; gap: 16px;
  font-family: var(--font-display);
  font-size: 38px; font-weight: 700; letter-spacing: 0.14em;
  color: var(--gold-text); line-height: 1;
}
.ld-diamond {
  position: relative; width: 26px; height: 26px; flex: none;
}
/* The diamond sits left of the word, so centring the row would push LOADOUT
   itself off centre. Mirror the diamond's footprint on the right so the word
   lands on the panel's centre line — same alignment the subtitle uses. */
.ld-title::after {
  content: '';
  width: 26px;
  flex: none;
}
.ld-diamond::before {
  content: ''; position: absolute; inset: 4px;
  border: 2px solid var(--brass-lit); transform: rotate(45deg);
}
.ld-diamond::after {
  content: ''; position: absolute; inset: 10px;
  background: var(--gold-text); transform: rotate(45deg);
}
.ld-sub { font-size: 14px; color: rgba(239, 227, 200, 0.6); }

.ld-body {
  display: grid;
  grid-template-columns: 300px 1fr 328px;
  gap: 30px;
  padding: 0 32px 26px;
  align-items: start;
}
.ld-col { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

.ld-cat {
  font-family: var(--font-display);
  font-size: 14px; font-weight: 700; letter-spacing: 0.2em;
  color: var(--brass-lit);
  text-align: center;
}
.ld-cat-c { padding-bottom: 2px; }
/* this heading is the player's own name, so it can be any 16 chars they like —
   clip rather than let it wrap and shove the preview down */
.ld-whoami {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ld-cat-row { display: flex; align-items: center; justify-content: space-between; margin-top: 12px; }
.ld-cat-spacer, .ld-count { width: 132px; }
.ld-count {
  text-align: right;
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 400; letter-spacing: 0.08em;
  color: rgba(239, 227, 200, 0.45);
}
.ld-note {
  font-family: var(--font-mono);
  font-size: 9px; letter-spacing: 0.1em;
  color: rgba(239, 227, 200, 0.45);
  text-transform: none;
}
/* the ultimate reads gold everywhere else in the game (the R slot, the HUD
   divider) — match it so the section is recognisable at a glance */
/* stacked so the heading itself centres in the column rather than being
   pushed off-centre by the note sitting beside it */
.ld-cat.gold {
  color: #ffc040;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.ld-cat.gold .ld-note { color: rgba(255, 192, 64, 0.6); }
.ld-hint {
  text-align: center; font-size: 13px; padding-top: 8px;
  color: rgba(239, 227, 200, 0.5);
}

/* --- left column: wizard preview --- */
.ld-preview {
  position: relative;
  height: 424px;
  border: 1px solid var(--brass);
  border-radius: 10px;
  overflow: hidden;
  background: var(--ink-deep);
  display: flex; align-items: center; justify-content: center;
}
.ld-preview::before {
  content: ''; position: absolute; inset: 0;
  background-image: repeating-linear-gradient(45deg, rgba(233,207,149,0.028) 0 2px, transparent 2px 10px);
}
.ld-glow {
  position: absolute; left: 50%; top: 44%;
  width: 260px; height: 260px; margin: -130px 0 0 -130px;
  border-radius: 50%;
  filter: blur(6px);
  transition: background 0.2s linear;
}
.ld-sigil {
  position: absolute; left: 50%; top: 44%;
  width: 208px; height: 208px; margin: -104px 0 0 -104px;
  border-radius: 50%;
  animation: ld-pulse 4.5s ease-in-out infinite;
  transition: border-color 0.2s linear, box-shadow 0.2s linear;
}
@keyframes ld-pulse {
  0%, 100% { opacity: 0.55; transform: scale(1); }
  50%      { opacity: 0.95; transform: scale(1.04); }
}
.ld-wizard {
  position: relative;
  height: 232px; width: auto;
  margin-bottom: 54px;
  /* true pixel art scaled up — keep the blocks hard, like the canvas does */
  image-rendering: pixelated;
  filter: drop-shadow(0 12px 26px rgba(0,0,0,0.7));
}
.ld-preview-meta {
  position: absolute; left: 0; right: 0; bottom: 16px;
  text-align: center; padding: 0 14px;
}
.ld-preview-name {
  font-family: var(--font-display);
  font-size: 20px; font-weight: 700; letter-spacing: 0.1em;
  color: var(--parchment);
}
.ld-preview-line {
  font-size: 11.5px; line-height: 1.45; margin-top: 3px;
  color: rgba(239, 227, 200, 0.68);
}
.ld-preview-line.dim { color: rgba(239, 227, 200, 0.44); }

/* --- cards --- */
.ld-grid { display: grid; gap: 12px; }
.ld-grid-2 { grid-template-columns: repeat(2, 1fr); }
.ld-grid-3 { grid-template-columns: repeat(3, 1fr); }
.ld-grid-4 { grid-template-columns: repeat(4, 1fr); }

.ld-card {
  position: relative;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  border: 1px solid var(--brass);
  background: linear-gradient(180deg, rgba(58,49,40,0.85) 0%, rgba(20,16,13,0.95) 100%);
  box-shadow: inset 0 1px 0 rgba(233,207,149,0.05);
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
  text-align: center;
}
.ld-card:hover { border-color: var(--brass-lit); }
/* the card is a fixed box now, so text clamps rather than pushing it taller */
.ld-card .ld-ds {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* selection still uses the ELEMENT colour — that is information, not decoration,
   and it is the one place the palette should not be brass */
.ld-card.on {
  border-color: var(--ld-c, var(--gold-bright));
  background: linear-gradient(180deg, rgba(201,162,74,0.12) 0%, rgba(20,16,13,0.95) 70%);
  box-shadow: 0 0 0 1px rgba(201,162,74,0.3), 0 0 26px rgba(201,162,74,0.2),
              inset 0 1px 0 rgba(233,207,149,0.07);
}
.ld-card.disabled { opacity: 0.42; cursor: not-allowed; }
.ld-card.disabled:hover { border-color: var(--brass); }
.ld-card-in {
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  padding: 16px 12px 15px;
}
.ld-orb {
  position: relative;
  width: 46px; height: 46px; flex: none;
  border-radius: 50%;
  display: grid; place-items: center;
}
.ld-orb img { width: 30px; height: 30px; object-fit: contain; }
.ld-orb-icon { font-size: 24px; line-height: 1; }
.ld-name {
  font-family: var(--font-display);
  font-size: 16px; font-weight: 700; letter-spacing: 0.04em;
  color: var(--parchment);
}
.ld-desc {
  font-size: 12px; line-height: 1.45; text-wrap: pretty;
  color: rgba(239, 227, 200, 0.58);
}
.ld-tag {
  font-family: var(--font-mono);
  font-size: 9px; letter-spacing: 0.12em;
  color: rgba(239, 227, 200, 0.42);
}
/* pick order — 1 is what your starting skill point unlocks */
.ld-order {
  position: absolute; top: 7px; left: 8px;
  width: 19px; height: 19px;
  border-radius: 50%;
  background: var(--ink-deep);
  border: 1px solid var(--brass-lit);
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 600; line-height: 17px;
  color: var(--gold-text);
}
/* the round-1 marker stays green: it is a status, and must not read as
   another shade of gold on a gold panel */
.ld-card.first .ld-order { background: #64d98a; border-color: #64d98a; color: #07240f; }
.ld-lock {
  position: absolute; bottom: 9px; right: 10px;
  padding: 2px 6px;
  border: 1px solid var(--brass); border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 8px; letter-spacing: 0.1em;
  color: rgba(239, 227, 200, 0.5);
}
.ld-card.ability .ld-card-in { min-height: 152px; }
.ld-card.compact .ld-card-in { padding: 14px 8px 13px; gap: 7px; }
.ld-card.compact .ld-name { font-size: 14px; }
.ld-card.static { cursor: default; }
.ld-card.static:hover { border-color: var(--brass); }

/* --- right column: key binds --- */
.ld-slots {
  border: 1px solid var(--brass);
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(58,49,40,0.55) 0%, rgba(20,16,13,0.75) 100%);
  padding: 14px 12px;
  display: flex; flex-direction: column; gap: 12px;
}
.ld-slotrow { display: flex; gap: 10px; justify-content: center; }
.ld-slot {
  position: relative;
  width: 84px; height: 84px;
  border-radius: 8px;
  background: var(--ink-deep);
  border: 1px dashed var(--brass);
  display: flex; align-items: center; justify-content: center;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.ld-slot.filled { border-style: solid; border-color: var(--brass-lit); }
.ld-slot.ult.filled { border-color: var(--gold-bright); box-shadow: 0 0 18px -6px var(--gold-bright); }
.ld-slot.start.filled { border-color: #64d98a; box-shadow: 0 0 18px -6px #64d98a; }
.ld-slot-key {
  position: absolute; top: 5px; left: 8px;
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 600; color: var(--brass-lit);
}
.ld-slot-icon { font-size: 30px; line-height: 1; }
.ld-slot-icon img { height: 40px; width: auto; display: block; }
.ld-slot-badge {
  position: absolute; bottom: -8px; left: 50%; transform: translateX(-50%);
  padding: 2px 7px; border-radius: 7px;
  background: #64d98a; color: #07240f;
  font-family: var(--font-mono);
  font-size: 8px; font-weight: 700; letter-spacing: 0.6px;
  white-space: nowrap;
}
.ld-slot-label {
  position: absolute; bottom: 5px; left: 0; right: 0;
  font-size: 9px; color: rgba(239, 227, 200, 0.5);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 4px;
}

/* --- footer --- */
.ld-rule {
  height: 1px; margin: 0 32px;
  background: linear-gradient(90deg, transparent, rgba(201,162,74,0.32) 20%, rgba(201,162,74,0.32) 80%, transparent);
}
/* Three buttons, one row. This was `1fr 1fr` for LEAVE's two predecessors, so
   adding a third wrapped CONFIRM onto a second line and pushed it off the
   bottom of a stage that is a fixed 1680x960. The two secondary actions size to
   their text; CONFIRM takes everything left, because it is the one you came
   here to press. */
.ld-foot {
  display: grid;
  grid-template-columns: auto auto minmax(300px, 1fr);
  gap: 18px;
  padding: 22px 120px 28px;
}
.ld-foot .ld-btn:not(.primary) { padding: 0 34px; font-size: 16px; }
.ld-btn {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  height: 54px;
  border: 1px solid var(--brass);
  border-radius: 8px;
  background: linear-gradient(180deg, rgba(58,49,40,0.8), var(--ink));
  font-family: var(--font-display);
  font-size: 17px; font-weight: 700; letter-spacing: 0.16em;
  color: rgba(239, 227, 200, 0.78);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, filter 0.15s;
}
.ld-btn:hover { border-color: var(--brass-lit); color: var(--parchment); }
.ld-btn.primary {
  border: 1px solid var(--gold-bright);
  background: linear-gradient(180deg, #c9a24a 0%, #a07c31 55%, #7d5d22 100%);
  color: #201703;
  text-shadow: 0 1px 0 rgba(255, 232, 176, 0.35);
  box-shadow: 0 10px 30px rgba(160, 124, 49, 0.3), inset 0 1px 0 rgba(255, 232, 176, 0.4);
}
.ld-btn.primary:hover { filter: brightness(1.08); }
.ld-btn:disabled { opacity: 0.45; cursor: not-allowed; filter: none; }
.ld-btn.primary:disabled:hover { filter: none; }

/* ---------- Match victory screen ---------- */
/* The pre-handoff victory stage used to live here — two sprites side by
   side, the winner scaled up 1.42x with a crown pinned above it. The "Match
   Victory" handoff replaced all of it, and leaving these rules behind was
   actively breaking the new one: .victor-wiz.winner still animated a
   scale(1.42) translateY(-16px) onto the whole left column, which dragged the
   victor's name up into the MATCH LOST title, and the crown was positioned
   -40px off that same displaced element.

   Deleted rather than overridden. That is now the fifth time a superseded
   block has kept fighting its replacement in this redesign.

   The crown survives, because it was hard-won — it spent a while as mojibake —
   but it lives inside the victor's frame now, where it cannot escape into the
   header. See .mv-side.winner .mv-frame-in::after below. */

  to   { transform: translateY(0) scale(1); opacity: 1; }
}

.rivalry {
  margin: 10px 0 2px;
  padding: 10px 12px;
  background: rgba(233, 207, 149, 0.05);
  border: 1px solid var(--brass);
  border-radius: 8px;
  font-family: var(--font-body);
  font-size: 13px;
  color: rgba(239, 227, 200, 0.7);
  line-height: 1.55;
}
.rivalry .vs {
  font-family: var(--font-display);
  font-weight: 800; color: var(--parchment); font-size: 15px;
}
.rivalry .streak { color: var(--gold-bright); font-weight: 700; }

#rematchBtn { margin-top: 12px; margin-bottom: 0; }
#rematchBtn.waiting {
  filter: grayscale(0.4) brightness(0.8);
  cursor: default;
}

/* --- scrollable ability / ultimate racks ---------------------------------
   The draft panel used to grow with whatever the class happened to hold:
   Earth has three ultimates where every other class has two, so its extra row
   changed the panel height, which changed the stage scale, which made the whole
   screen jump when you clicked between classes.

   The racks are now fixed boxes that scroll instead. The panel is the same
   height for every class, so nothing moves, and an arrow appears only when
   there is genuinely something past the edge. */
.ld-rack { position: relative; }
.ld-rack > .ld-grid {
  overflow: auto;
  scrollbar-width: none;              /* the arrow is the affordance */
  scroll-behavior: smooth;
}
.ld-rack > .ld-grid::-webkit-scrollbar { display: none; }

/* ultimates: one row, scrolling sideways.
   The row is a FIXED height. Card text used to set it, so Meteor Shower's
   longer name and description made Earth's row taller than everyone else's and
   pushed KEY BINDS down the column. Shorter copy helped; pinning the height is
   what actually guarantees nothing below it ever moves again. */
.ld-rack-x > .ld-grid {
  height: 168px;
  grid-auto-rows: 168px;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - 12px) / 2);   /* exactly two visible */
  grid-template-columns: none;
  overflow-y: hidden;
  padding-bottom: 2px;
}
/* abilities: two rows, scrolling down */
.ld-rack-y > .ld-grid {
  height: 356px;              /* fixed, for the same reason */
  grid-auto-rows: 172px;                  /* two rows of cards plus the gap */
  overflow-x: hidden;
  padding-right: 2px;
}

.ld-more {
  position: absolute;
  display: none;                      /* only shown when there IS more */
  align-items: center;
  justify-content: center;
  width: 30px; height: 30px;
  color: var(--brass-lit);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;            /* it is a control, not just a hint */
  border-radius: 50%;
  animation: ldNudge 1.6s ease-in-out infinite;
}
.ld-rack.can-next > .ld-more.next { display: flex; }
.ld-rack.can-prev > .ld-more.prev { display: flex; }
.ld-more:hover { opacity: 1; background: rgba(232, 198, 106, 0.14); animation: none; }
.ld-rack-x > .ld-more { top: 50%; margin-top: -15px; }
.ld-rack-x > .ld-more.next { right: -26px; }
.ld-rack-x > .ld-more.prev { left: -26px; }
.ld-rack-y > .ld-more { left: 50%; margin-left: -15px; }
.ld-rack-y > .ld-more.next { bottom: -26px; }
.ld-rack-y > .ld-more.prev { top: -26px; }
@keyframes ldNudge {
  0%, 100% { opacity: 0.45; transform: translate(0, 0); }
  50%      { opacity: 1; }
}
.ld-rack-x.can-next > .ld-grid { mask-image: linear-gradient(to right, #000 86%, transparent 100%); }
.ld-rack-y.can-next > .ld-grid { mask-image: linear-gradient(to bottom, #000 88%, transparent 100%); }
/* both edges fading at once, when you are stopped in the middle */
.ld-rack-x.can-next.can-prev > .ld-grid { mask-image: linear-gradient(to right, transparent 0%, #000 14%, #000 86%, transparent 100%); }
.ld-rack-y.can-next.can-prev > .ld-grid { mask-image: linear-gradient(to bottom, transparent 0%, #000 12%, #000 88%, transparent 100%); }
.ld-rack-x.can-prev:not(.can-next) > .ld-grid { mask-image: linear-gradient(to right, transparent 0%, #000 14%); }
.ld-rack-y.can-prev:not(.can-next) > .ld-grid { mask-image: linear-gradient(to bottom, transparent 0%, #000 12%); }

/* ---- public room browser ---- */
/* Deliberately a LIST OF BUTTONS rather than rows with a button in them: the
   whole row is the target, because "join this room" is the only thing anyone
   opens this dialog to do. */
.mn-rooms { max-height: 44vh; overflow-y: auto; padding: 4px 2px; }
.mn-room {
  display: grid;
  grid-template-columns: 34px 1fr auto auto;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  margin-bottom: 8px;
  background: rgba(239, 231, 216, 0.04);
  border: 1px solid rgba(232, 198, 106, 0.18);
  border-radius: 6px;
  color: var(--mn-cream);
  font: inherit;
  font-size: 15px;
  text-align: left;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.mn-room:hover, .mn-room:focus-visible {
  background: rgba(232, 198, 106, 0.12);
  border-color: var(--mn-gold);
  outline: none;
}
.mn-room-go {
  display: grid;
  place-items: center;
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 1px solid var(--mn-gold);
  color: var(--mn-gold);
  font-size: 11px;
}
.mn-room-host { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; }
.mn-room-arena { color: rgba(239, 231, 216, 0.5); font-size: 13px; }
.mn-room-count {
  color: var(--mn-gold);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  letter-spacing: 0.08em;
}
.mn-rooms-empty {
  padding: 26px 10px;
  text-align: center;
  color: rgba(239, 231, 216, 0.5);
  line-height: 1.7;
}
.mn-rooms-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 6px;
  padding-top: 12px;
  border-top: 1px solid rgba(232, 198, 106, 0.22);
}
.mn-rooms-note { color: rgba(239, 231, 216, 0.45); font-size: 13px; }
.mn-rooms::-webkit-scrollbar { width: 8px; }
.mn-rooms::-webkit-scrollbar-thumb { background: rgba(201, 162, 74, 0.4); border-radius: 4px; }

/* A room already in a duel: still listed (an empty browser reads as a dead
   game) but deliberately not a button, so it cannot be clicked at. */
.mn-room.busy {
  cursor: default;
  opacity: 0.62;
  border-color: rgba(239, 231, 216, 0.12);
  background: rgba(239, 231, 216, 0.02);
}
.mn-room.busy .mn-room-go { border-color: rgba(239, 231, 216, 0.3); color: rgba(239, 231, 216, 0.45); }
.mn-room.busy .mn-room-count { color: rgba(239, 231, 216, 0.45); }
.mn-rooms-online {
  color: var(--mn-gold);
  font-size: 13px;
  letter-spacing: 0.12em;
  white-space: nowrap;
}
.mn-rooms-foot { flex-wrap: wrap; }

/* CREATE sits beside JOIN in the private-room row. Quieter than JOIN, because
   most people arriving here have a code from a friend; creating is the other
   half of the same idea, not the headline. */
.mn-go.ghost {
  background: transparent;
  border-color: rgba(232, 198, 106, 0.45);
  color: rgba(239, 231, 216, 0.75);
}
.mn-go.ghost:hover { background: rgba(232, 198, 106, 0.12); color: var(--mn-gold); }

/* LEAVE MATCH. Red enough to read as "this ends the game", quiet enough that
   it is not the first thing your eye lands on in a settings panel. */
.mn-btn.danger {
  border-color: rgba(224, 96, 79, 0.55);
  color: #e0604f;
}
.mn-btn.danger:hover { background: rgba(224, 96, 79, 0.16); border-color: #e0604f; }
.mn-btn.danger.hidden { display: none; }

/* ================= LOBBY =================================================
   From the "Lobby Redesign" handoff, in the language the loadout and result
   screens now share: a gilded frame with notched corners, and every mark on it
   either a clipped rectangle or a square turned 45 degrees.

   This shell — frame, crest header, two columns, footer — is also the
   leaderboard's. It always was: that screen was built on .lob / .lob-main /
   .lob-side and borrows whatever they are. Restyling one and not the other was
   never an option.

   The handoff's palette is already ours to within a rounding error, so this
   uses the tokens rather than introducing a second gold. Its Google Fonts link
   is deliberately NOT carried over: both families are self-hosted here, and
   re-adding the CDN would undo the GDPR fix.                                */

.lob-frame {
  width: min(1100px, 94vw);
  max-height: 92vh;
  overflow-y: auto;
  padding: 2px;
  background: linear-gradient(150deg,
    rgba(217, 177, 96, 0.85),
    rgba(217, 177, 96, 0.16) 32%,
    rgba(217, 177, 96, 0.08) 68%,
    rgba(217, 177, 96, 0.7));
  clip-path: polygon(26px 0, calc(100% - 26px) 0, 100% 26px, 100% calc(100% - 26px),
                     calc(100% - 26px) 100%, 26px 100%, 0 calc(100% - 26px), 0 26px);
  box-shadow: 0 40px 110px -35px #000;
}
.lob {
  position: relative;
  background: #0c0a0e;
  text-align: left;
  clip-path: polygon(25px 0, calc(100% - 25px) 0, 100% 25px, 100% calc(100% - 25px),
                     calc(100% - 25px) 100%, 25px 100%, 0 calc(100% - 25px), 0 25px);
}

/* ---- crest header ---- */
.lob-crest-head {
  position: relative;
  overflow: hidden;
  padding: 28px 34px 22px;
  border-bottom: 1px solid rgba(217, 177, 96, 0.2);
  background: radial-gradient(120% 130% at 50% -30%, rgba(217, 177, 96, 0.12), transparent 62%);
}
.lob-crest { display: flex; align-items: center; justify-content: center; gap: 16px; }
.lob-crest-rule { flex: 1; height: 1px; background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.5)); }
.lob-crest-rule.flip { background: linear-gradient(270deg, transparent, rgba(217, 177, 96, 0.5)); }
.lob-crest-title {
  font: 700 24px var(--font-display); letter-spacing: 0.28em;
  color: #f5ecdd; text-shadow: 0 0 28px rgba(217, 177, 96, 0.4);
  white-space: nowrap;
}
.lob-meta {
  margin-top: 12px;
  display: flex; align-items: center; justify-content: center;
  gap: 14px; row-gap: 6px; flex-wrap: wrap;
}
.lob-meta-live {
  display: flex; align-items: center; gap: 8px;
  font: 400 10.5px var(--font-ui); letter-spacing: 0.14em;
  color: rgba(217, 177, 96, 0.8); white-space: nowrap;
}
.lob-meta-txt {
  font: 400 10.5px var(--font-ui); letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.34); white-space: nowrap;
}
.lob-meta-div { width: 1px; height: 12px; background: rgba(255, 255, 255, 0.14); flex: none; }

/* the diamond, at its three sizes */
.lob-dia {
  width: 11px; height: 11px; flex: none;
  border: 1px solid #d9b160;
  transform: rotate(45deg);
  box-shadow: 0 0 14px rgba(217, 177, 96, 0.6);
}
.lob-dia.sm { width: 9px; height: 9px; border-color: rgba(217, 177, 96, 0.6); box-shadow: none; }
.lob-bullet {
  width: 7px; height: 7px; flex: none;
  border: 1px solid rgba(217, 177, 96, 0.7);
  transform: rotate(45deg);
}
.lob-dot {
  width: 6px; height: 6px; flex: none;
  background: #d9b160;
  transform: rotate(45deg);
  box-shadow: 0 0 9px #d9b160;
  animation: lobDot 2.4s ease-in-out infinite;
}
.lob-meta-live .lob-dot { width: 5px; height: 5px; box-shadow: 0 0 8px #d9b160; }
@keyframes lobDot {
  0%, 100% { opacity: 0.35; transform: rotate(45deg) scale(1); }
  50%      { opacity: 0.9;  transform: rotate(45deg) scale(1.35); }
}

/* ---- the two columns ---- */
.lob-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(230px, 300px);
  align-items: stretch;
}
.lob-main { position: relative; padding: 26px 26px 28px; }
.lob-side {
  padding: 26px 22px;
  border-left: 1px solid rgba(217, 177, 96, 0.14);
  background: linear-gradient(180deg, rgba(217, 177, 96, 0.06), transparent 42%);
  display: flex; flex-direction: column; gap: 20px;
}

/* ---- section headers ---- */
.lob-eyebrow { display: flex; align-items: center; gap: 9px; margin-bottom: 13px; }
.lob-eyebrow > span {
  font: 400 9.5px var(--font-ui); letter-spacing: 0.2em;
  color: rgba(255, 255, 255, 0.34); white-space: nowrap;
}
.lob-hair { flex: 1; height: 1px; background: linear-gradient(90deg, rgba(217, 177, 96, 0.3), transparent); }
.lob-div { display: flex; align-items: center; gap: 9px; }
.lob-div i { flex: 1; height: 1px; background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.3)); }
.lob-div i:last-child { background: linear-gradient(270deg, transparent, rgba(217, 177, 96, 0.3)); }
.lob-div .lob-dia { width: 8px; height: 8px; border-color: rgba(217, 177, 96, 0.55); }

/* ---- the empty state: two seats, one of them yours ---- */
.lob-hero {
  padding: 1px;
  background: linear-gradient(160deg, rgba(217, 177, 96, 0.7), rgba(217, 177, 96, 0.15));
  clip-path: polygon(16px 0, calc(100% - 16px) 0, 100% 16px, 100% calc(100% - 16px),
                     calc(100% - 16px) 100%, 16px 100%, 0 calc(100% - 16px), 0 16px);
  box-shadow: 0 0 44px -16px rgba(217, 177, 96, 0.45);
}
.lob-hero-in {
  position: relative;
  overflow: hidden;
  background: linear-gradient(180deg, rgba(217, 177, 96, 0.07), rgba(255, 255, 255, 0.006)), #0f0c11;
  clip-path: polygon(15px 0, calc(100% - 15px) 0, 100% 15px, 100% calc(100% - 15px),
                     calc(100% - 15px) 100%, 15px 100%, 0 calc(100% - 15px), 0 15px);
  padding: 34px 26px 28px;
}
.lob-hero.hidden, .lob-list.hidden, .lob-openrow.hidden, .lob-ghosts.hidden { display: none; }
.lob-corner { position: absolute; width: 22px; height: 22px; pointer-events: none; }
.lob-corner.tl { top: 10px; left: 10px; border-top: 1px solid rgba(217, 177, 96, 0.5); border-left: 1px solid rgba(217, 177, 96, 0.5); }
.lob-corner.br { bottom: 10px; right: 10px; border-bottom: 1px solid rgba(217, 177, 96, 0.5); border-right: 1px solid rgba(217, 177, 96, 0.5); }

.lob-seats {
  display: flex; align-items: center; justify-content: center;
  gap: 40px; row-gap: 24px; flex-wrap: wrap;
}
.lob-seat { display: flex; flex-direction: column; align-items: center; gap: 6px; }
/* The box is fixed so the two seats stay level: the diamonds are rotated, and
   a rotated square's bounding box is 1.41x its side. */
.lob-av-box { width: 106px; height: 106px; display: grid; place-items: center; }
.lob-av {
  width: 74px; height: 74px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 0;
  transform: rotate(45deg);
}
/* whatever sits in a diamond has to be turned back out of it */
.lob-av > span { display: block; transform: rotate(-45deg); }
.lob-av.you {
  border: 1px solid rgba(217, 177, 96, 0.6);
  background: rgba(217, 177, 96, 0.1);
  box-shadow: 0 0 36px -8px rgba(217, 177, 96, 0.55);
  font: 700 24px var(--font-display); color: #f0d08a;
}
.lob-av.empty {
  border: 1px dashed rgba(255, 255, 255, 0.22);
  animation: lobFlick 4.5s ease-in-out infinite;
  font: 700 22px var(--font-ui); color: rgba(255, 255, 255, 0.24);
}
.lob-seat-lbl { font: 500 10px var(--font-ui); letter-spacing: 0.16em; color: var(--mn-cream); }
.lob-seat-lbl.dim { font-weight: 400; color: rgba(255, 255, 255, 0.32); }

.lob-vs { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.lob-vs-txt { font: 600 13px var(--font-display); letter-spacing: 0.24em; color: rgba(217, 177, 96, 0.7); }

.lob-hero-rule {
  display: block; margin: 24px auto 0;
  width: 58%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.35), transparent);
}
.lob-copy {
  margin: 20px auto 0; max-width: 420px;
  font: 400 13px/1.75 var(--font-ui); color: rgba(255, 255, 255, 0.55);
  text-align: center; text-wrap: pretty;
}
.lob-note {
  margin-top: 14px; text-align: center;
  font: 400 10px var(--font-ui); letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.28);
}
.lob-note + .lob-note { margin-top: 6px; }   /* the Duel Pass line sits with the first, not apart from it */
.lob-note b { color: rgba(240, 208, 138, 0.7); font-weight: 600; }

/* ---- the primary call to action ---- */
.lob-cta-wrap { display: flex; justify-content: center; margin-top: 22px; }
.lob-cta {
  height: 46px;
  display: flex; align-items: center; gap: 12px;
  padding: 0 32px;
  border: 0; border-radius: 0;
  background: linear-gradient(160deg, #f0d08a, #d9b160 55%, #c39c4c);
  clip-path: polygon(14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%, 0 14px);
  box-shadow: 0 0 34px -8px rgba(217, 177, 96, 0.6);
  color: #120f0a;
  font: 700 12px var(--font-ui); letter-spacing: 0.2em;
  white-space: nowrap; cursor: pointer;
  transition: background 0.16s ease;
}
.lob-cta:hover { background: linear-gradient(160deg, #f7dda0, #e6be6e 55%, #d0a856); }
.lob-cta.slim { height: 40px; font-size: 11px; padding: 0 26px; }

/* ---- the populated state ---- */
.lob-list { display: flex; flex-direction: column; gap: 7px; }
.lob-row {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: 14px;
  padding: 13px 16px;
  border: 0; border-radius: 0;
  background: #100d12;
  clip-path: polygon(12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%, 0 12px);
  box-shadow: inset 0 0 0 1px rgba(217, 177, 96, 0.35);
  cursor: pointer;
  text-align: left;
  transition: box-shadow 0.16s ease, background 0.16s ease;
  /* A joinable room is a <button> and a full one is a <div>. Buttons do not
     inherit colour — they fall back to the UA's ButtonText, which is black —
     so without this the host's name was unreadable on exactly the rows you are
     meant to click, and fine on the ones you are not. */
  color: rgba(245, 236, 221, 0.85);
  font-family: var(--font-ui);
}
.lob-row:hover { box-shadow: inset 0 0 0 1px #d9b160; background: rgba(217, 177, 96, 0.07); }
.lob-row.busy {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
  cursor: default;
  opacity: 0.72;
}
.lob-row.busy:hover { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12); background: #100d12; }
.lob-row-seat {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center;
  border: 1px solid rgba(217, 177, 96, 0.5);
  background: rgba(217, 177, 96, 0.1);
  transform: rotate(45deg);
  font: 700 11px var(--font-ui); color: #f0d08a;
}
.lob-row-seat > * { transform: rotate(-45deg); }
.lob-row.busy .lob-row-seat { border-color: rgba(255, 255, 255, 0.14); background: none; color: rgba(255, 255, 255, 0.3); }
/* the other player's name is the thing you are reading this row for */
.lob-row-host {
  font: 500 14px var(--font-ui);
  color: #f0d08a;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lob-row.busy .lob-row-host { color: rgba(255, 255, 255, 0.5); }
.lob-row-arena { font: 400 10.5px var(--font-ui); letter-spacing: 0.1em; color: rgba(255, 255, 255, 0.32); }
.lob-row-tag { font: 700 10px var(--font-ui); letter-spacing: 0.18em; color: var(--gold-bright); }
.lob-row.busy .lob-row-tag { color: rgba(255, 255, 255, 0.3); font-weight: 400; }
.lob-openrow { display: flex; justify-content: center; margin-top: 12px; }

/* placeholder rows: the shape of what would be there, at rest */
.lob-ghosts { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; }
.lob-ghosts i {
  height: 44px;
  background: repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.02) 0 9px, transparent 9px 18px);
  clip-path: polygon(11px 0, 100% 0, 100% calc(100% - 11px), calc(100% - 11px) 100%, 0 100%, 0 11px);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);
}
.lob-ghosts i:last-child {
  background: repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.012) 0 9px, transparent 9px 18px);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.035);
}

/* ---- realm status ---- */
.lob-card {
  padding: 1px;
  background: linear-gradient(160deg, rgba(217, 177, 96, 0.6), rgba(217, 177, 96, 0.14));
  clip-path: polygon(14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%, 0 14px);
}
.lob-card-in {
  background: linear-gradient(180deg, rgba(217, 177, 96, 0.08), rgba(255, 255, 255, 0.006)), #100d12;
  clip-path: polygon(13px 0, 100% 0, 100% calc(100% - 13px), calc(100% - 13px) 100%, 0 100%, 0 13px);
  padding: 16px 15px 15px;
}
.lob-online { display: flex; align-items: center; gap: 10px; font: 500 13px var(--font-ui); color: #f1e8d8; }
.lob-tally { display: flex; gap: 13px; margin-top: 10px; font: 400 10.5px var(--font-ui); color: rgba(255, 255, 255, 0.34); white-space: nowrap; }
.lob-pipe { color: rgba(255, 255, 255, 0.14); }

/* ---- the private code ---- */
.lob-code { position: relative; display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.lob-code input {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  opacity: 0;
  border: 0; padding: 0;
  font: inherit; letter-spacing: 2.2em;
  cursor: pointer;
  z-index: 2;
}
.lob-cell {
  aspect-ratio: 1;
  display: grid; place-items: center;
  background: #0f0c11;
  clip-path: polygon(9px 0, 100% 0, 100% calc(100% - 9px), calc(100% - 9px) 100%, 0 100%, 0 9px);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
  font: 700 15px var(--font-ui); color: #d9b160;
  text-transform: uppercase;
}
.lob-cell.filled, .lob-cell.active {
  background: linear-gradient(180deg, rgba(217, 177, 96, 0.12), rgba(217, 177, 96, 0.02)), #100d12;
  box-shadow: inset 0 0 0 1px rgba(217, 177, 96, 0.5);
}
.lob-cell.active::after { content: '|'; animation: lobFlick 1.6s steps(2, end) infinite; }

/* ---- buttons: one notched layer, an inset border tracing it ---- */
.lob-join, .lob-btn.outline {
  height: 38px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 18px;
  border: 0; border-radius: 0;
  background: #100d12;
  clip-path: polygon(11px 0, 100% 0, 100% calc(100% - 11px), calc(100% - 11px) 100%, 0 100%, 0 11px);
  box-shadow: inset 0 0 0 1px rgba(217, 177, 96, 0.5);
  font: 600 11px var(--font-ui); letter-spacing: 0.18em;
  color: #d9b160; white-space: nowrap; cursor: pointer;
  transition: box-shadow 0.16s ease, background 0.16s ease;
}
.lob-join { width: 100%; margin-top: 11px; }
.lob-join:hover, .lob-btn.outline:hover { background: rgba(217, 177, 96, 0.1); box-shadow: inset 0 0 0 1px #d9b160; }
/* Creating a private duel is not in the handoff, but without it hosting one has
   no entry point at all — the code field would have nothing to open. */
.lob-mklink {
  display: block; width: 100%;
  margin-top: 9px; padding: 4px 0;
  border: 0; background: none;
  font: 400 10.5px var(--font-ui);
  color: rgba(255, 255, 255, 0.32);
  cursor: pointer;
  transition: color 0.14s;
}
.lob-mklink:hover { color: var(--gold-bright); }
.lob-blurb { margin: 0; font: 400 11px/1.75 var(--font-ui); color: rgba(255, 255, 255, 0.32); text-wrap: pretty; }

/* ---- footer ---- */
.lob-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; row-gap: 14px; flex-wrap: wrap;
  padding: 18px 34px 20px;
  border-top: 1px solid rgba(217, 177, 96, 0.2);
  background: linear-gradient(180deg, transparent, rgba(217, 177, 96, 0.05));
}
.lob-foot-l { display: flex; align-items: center; gap: 11px; }
.lob-foot-hint { font: 400 11.5px var(--font-ui); letter-spacing: 0.1em; color: rgba(255, 255, 255, 0.45); }
.lob-foot-r { display: flex; align-items: center; gap: 10px; }
.lob-btn { font-family: var(--font-ui); border: 0; border-radius: 0; cursor: pointer; white-space: nowrap; }
.lob-btn.ghost {
  height: 40px; padding: 0 18px;
  background: none;
  font: 500 11px var(--font-ui); letter-spacing: 0.18em;
  color: rgba(255, 255, 255, 0.42);
  transition: color 0.16s ease;
}
.lob-btn.ghost:hover { color: #d9b160; }

@media (max-width: 780px) {
  .lob-cols { grid-template-columns: 1fr; }
  .lob-side { border-left: 0; border-top: 1px solid rgba(217, 177, 96, 0.14); }
}

@keyframes lobFlick { 0%, 100% { opacity: 0.85 } 45% { opacity: 0.55 } 70% { opacity: 1 } }
@keyframes lobPulse { 0%, 100% { opacity: 0.35; transform: scale(1) } 50% { opacity: 0.9; transform: scale(1.35) } }
/* translateX percentages are of the ELEMENT, not its parent — and this bar is
   22% of the panel. The handoff's 300% therefore carried it to 88% and stopped
   it dead just short of the right edge, which is exactly where it looked wrong.
   To clear the edge the bar's left side has to reach 100% of the panel:
   100 / 22 = 4.545 of its own width. Change --sweep-w and this number moves
   with it. */
.lob-sweep {
  position: absolute; top: 0; left: 0;
  width: var(--sweep-w, 22%); height: 2px;
  background: linear-gradient(90deg, transparent, #d9b160, transparent);
  animation: lobSweep 3.4s linear infinite;
}
.lob-hero-in, .lob-crest-head { --sweep-w: 22%; }
@keyframes lobSweep {
  0%   { transform: translateX(-100%) }
  100% { transform: translateX(455%) }
}

/* ---- leaderboard ---------------------------------------------------------
   Shares the lobby shell (.lob / .lob-main / .lob-side); only the table and
   the standing panel are its own. The handoff's RATING column is not here:
   this game has no Elo, and inventing a number would make the board look
   authoritative about something it does not measure. The last column is WINS,
   which is what actually decides rank.                                     */

.lb-crest {
  width: 58px; height: 58px; margin: 0 auto;
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed rgba(217, 177, 96, 0.4);
  font: 600 20px var(--font-display);
  color: rgba(217, 177, 96, 0.5);
  animation: lobFlick 4.5s ease-in-out infinite;
}

.lb-table.hidden, .lob-hero.hidden, .lb-you.hidden { display: none; }
.lb-head, .lb-row, .lb-you {
  display: grid;
  grid-template-columns: 44px 1fr 74px 62px 58px;
  gap: 10px;
  align-items: center;
}
.lb-head {
  padding: 0 12px 9px;
  font: 400 9px var(--font-ui);
  letter-spacing: 0.18em;
  color: rgba(255, 255, 255, 0.28);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.lb-head .r, .lb-num { text-align: right; }

.lb-rows { display: flex; flex-direction: column; max-height: 46vh; overflow-y: auto; }
.lb-rows::-webkit-scrollbar { width: 8px; }
.lb-rows::-webkit-scrollbar-thumb { background: rgba(201, 162, 74, 0.4); border-radius: 4px; }

.lb-row {
  padding: 13px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  transition: background 0.12s;
}
.lb-row:last-child { border-bottom: 0; }
.lb-row:hover { background: rgba(255, 255, 255, 0.035); }
/* first place is lit; second and third are warm; the rest are plain, so the
   podium reads at a glance without three different badges */
.lb-row.p1 { background: linear-gradient(90deg, rgba(217,177,96,0.1), rgba(217,177,96,0.01)); }
.lb-row.p1:hover { background: rgba(217, 177, 96, 0.14); }
.lb-rank { font: 700 13px var(--font-display); color: rgba(255, 255, 255, 0.4); }
.lb-row.p1 .lb-rank { font-size: 14px; color: #f0d08a; }
.lb-row.p2 .lb-rank { color: rgba(217, 177, 96, 0.8); }
.lb-row.p3 .lb-rank { color: rgba(217, 177, 96, 0.65); }

.lb-wiz { display: flex; align-items: center; gap: 10px; min-width: 0; }
.lb-av {
  flex: none;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border: 1px solid rgba(255, 255, 255, 0.12);
  font: 700 11px var(--font-display);
  color: rgba(255, 255, 255, 0.45);
}
.lb-row.p1 .lb-av, .lb-row.p2 .lb-av, .lb-row.p3 .lb-av { border-color: rgba(255, 255, 255, 0.16); color: rgba(255,255,255,0.6); }
.lb-row.p1 .lb-av { border-color: rgba(217, 177, 96, 0.55); background: rgba(217, 177, 96, 0.12); color: #f0d08a; }
.lb-name {
  font: 400 13px var(--font-ui);
  color: rgba(255, 255, 255, 0.75);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lb-row.p1 .lb-name, .lb-row.p2 .lb-name, .lb-row.p3 .lb-name { font-weight: 500; color: #e8e2d6; }
.lb-row.p1 .lb-name { color: #f5ecdd; }
.lb-tag {
  flex: none;
  font: 400 8.5px var(--font-ui); letter-spacing: 0.14em;
  padding: 2px 5px;
  border: 1px solid rgba(217, 177, 96, 0.4);
  color: var(--gold-bright);
}
.lb-streak { flex: none; font: 400 8.5px var(--font-ui); letter-spacing: 0.14em; color: rgba(255, 255, 255, 0.35); }
.lb-num { font: 400 12px var(--font-ui); color: rgba(255, 255, 255, 0.4); }
.lb-row.p1 .lb-num, .lb-row.p2 .lb-num, .lb-row.p3 .lb-num { color: rgba(255, 255, 255, 0.5); }
.lb-wins { text-align: right; font: 500 13px var(--font-ui); color: rgba(255, 255, 255, 0.75); }
.lb-row.p1 .lb-wins { font-weight: 700; color: #f0d08a; }

/* your own row, pinned under the board when you are not in it */
.lb-you {
  margin-top: 14px;
  padding: 13px 12px;
  border: 1px solid rgba(217, 177, 96, 0.35);
  background: rgba(217, 177, 96, 0.05);
}
.lb-you .lb-rank { color: var(--gold-bright); font-family: var(--font-ui); font-weight: 500; }
.lb-you .lb-av { border-color: rgba(217, 177, 96, 0.5); background: rgba(217, 177, 96, 0.1); color: #f0d08a; }
.lb-you .lb-name { font-weight: 500; color: #f5ecdd; }
.lb-you .lb-num { color: rgba(255, 255, 255, 0.5); }
.lb-you .lb-wins { font-weight: 700; color: #f0d08a; }
.lb-row.me { background: rgba(217, 177, 96, 0.07); }

/* ---- sidebar standing ---- */
.lb-standing { display: flex; align-items: baseline; gap: 8px; }
.lb-rank-big { font: 600 30px var(--font-display); color: #f0d08a; }
.lb-of { font: 400 10.5px var(--font-ui); color: rgba(255, 255, 255, 0.35); }
.lb-bar { margin-top: 12px; height: 4px; background: rgba(255, 255, 255, 0.07); }
.lb-bar i {
  display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, rgba(217, 177, 96, 0.5), var(--gold-bright));
  transition: width 0.4s ease;
}
.lb-next {
  margin-top: 7px;
  font: 400 9.5px var(--font-ui); letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.28);
}
.lb-last { display: flex; gap: 6px; }
.lb-last span {
  flex: 1; aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.12);
  font: 700 12px var(--font-ui);
  color: rgba(255, 255, 255, 0.3);
}
.lb-last span.w { border-color: rgba(217, 177, 96, 0.5); background: rgba(217, 177, 96, 0.12); color: #f0d08a; }
.lb-last span.none { border-style: dashed; border-color: rgba(255, 255, 255, 0.08); color: rgba(255, 255, 255, 0.15); }

/* The rank slot holds a big numeral when you have a rank, and a word when you
   do not. A 30px 'UNRANKED' would blow the sidebar apart, so the word gets its
   own size — same slot, same colour, still obviously the answer to the
   heading above it. */
.lb-rank-big.word {
  font: 500 13px var(--font-ui);
  letter-spacing: 0.16em;
  color: rgba(217, 177, 96, 0.75);
}


/* ================= ROUND RESULT ==========================================
   From the "Defeat" handoff, in the same language as the Loadout: a gilded
   frame with notched corners, and every mark on it either a clipped rectangle
   or a square turned 45 degrees.

   Held at 16:9. The panel used to grow with the display — min(96vw, 1700px,
   max(1180px, 72vw)) — which on a wide monitor stretched it to nearly 3:1 and
   left one row of cards floating in a letterbox. A fixed ratio keeps the
   proportions it was drawn at, and the card grid takes whatever height is
   left over.

   The accent turns red on a defeat and green on a win: the sweep, the eyebrow
   bullet, the frame's top edge. That is carried by .vic.win / .vic.lose, not
   by the title alone.                                                        */

.vic-frame {
  /* Height first, width derived — the other way round, a max-height clamp
     would break the ratio instead of shrinking the panel. */
  height: min(92vh, calc(min(1240px, 94vw) * 9 / 16));
  aspect-ratio: 16 / 9;
  width: auto;
  padding: 2px;
  background: linear-gradient(150deg,
    rgba(217, 177, 96, 0.7),
    rgba(217, 177, 96, 0.16) 34%,
    rgba(217, 177, 96, 0.08) 66%,
    rgba(217, 177, 96, 0.6));
  clip-path: polygon(26px 0, calc(100% - 26px) 0, 100% 26px, 100% calc(100% - 26px),
                     calc(100% - 26px) 100%, 26px 100%, 0 calc(100% - 26px), 0 26px);
  box-shadow: 0 40px 110px -35px #000;
}
.vic {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #0c0a0e;
  text-align: left;
  clip-path: polygon(25px 0, calc(100% - 25px) 0, 100% 25px, 100% calc(100% - 25px),
                     calc(100% - 25px) 100%, 25px 100%, 0 calc(100% - 25px), 0 25px);
}
/* one variable carries the result through the whole header */
/* A win is the house gold, not a second accent colour — the handoff draws
   YOU WIN THE MATCH in cream over a gold glow, and reserves a colour of its
   own for the defeat. */
.vic { --tone: 217, 177, 96; --tone-txt: #f0d08a; }
.vic.lose { --tone: 196, 84, 68; --tone-txt: #e08474; }

/* ---- header ---- */
.vic-head {
  position: relative;
  flex: none;
  overflow: hidden;
  padding: 28px 34px 24px;
  border-bottom: 1px solid rgba(217, 177, 96, 0.18);
  background: radial-gradient(120% 130% at 50% -30%, rgba(var(--tone), 0.16), transparent 62%);
}
.vic-sweep {
  position: absolute; top: 0; left: 0;
  width: 22%; height: 2px;
  background: linear-gradient(90deg, transparent, rgba(var(--tone), 0.9), transparent);
  animation: lobSweep 3.4s linear infinite;
}
.vic-head-in {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 26px; row-gap: 16px; flex-wrap: wrap;
}
.vic-eyerow { display: flex; align-items: center; gap: 9px; margin-bottom: 10px; }
.vic-bullet {
  width: 7px; height: 7px; flex: none;
  border: 1px solid rgba(var(--tone), 0.75);
  transform: rotate(45deg);
}
.vic-eyebrow {
  font: 400 9.5px var(--font-ui); letter-spacing: 0.24em;
  color: rgba(var(--tone), 0.8); white-space: nowrap;
}
.vic-title {
  margin: 0;
  font: 700 40px var(--font-display); letter-spacing: 0.2em;
  color: #f5ecdd;
  text-shadow: 0 0 34px rgba(var(--tone), 0.45);
  animation: vicFlick 5s ease-in-out infinite;
}
.vic.lose .vic-title { color: var(--tone-txt); }
@keyframes vicFlick { 0%, 100% { opacity: 0.85; } 45% { opacity: 0.55; } 70% { opacity: 1; } }

.vic-subrow { display: flex; align-items: center; gap: 12px; margin-top: 13px; flex-wrap: wrap; }
.vic-sub { margin: 0; font: 400 12.5px var(--font-ui); color: rgba(255, 255, 255, 0.5); white-space: nowrap; }
.vic-sub b { color: #e8e2d6; font-weight: 400; }
.vic-subdiv { width: 1px; height: 13px; background: rgba(255, 255, 255, 0.16); flex: none; }
/* clutch and streak are the same badge — a fact about the duel, stated once */
.vic-badge {
  font: 500 11px var(--font-ui); letter-spacing: 0.14em;
  padding: 3px 8px;
  border: 1px solid rgba(var(--tone), 0.45);
  background: rgba(var(--tone), 0.09);
  color: var(--tone-txt);
  white-space: nowrap;
}
.vic-subdiv.hidden, .vic-badge.hidden { display: none; }

.vic-tallies { display: flex; align-items: stretch; gap: 20px; text-align: right; }
.vic-tallies.hidden { display: none; }
.vic-tally-lbl {
  font: 400 9px var(--font-ui); letter-spacing: 0.2em;
  color: rgba(255, 255, 255, 0.28); margin-bottom: 8px; white-space: nowrap;
}
.vic-tally-nums { display: flex; align-items: baseline; gap: 9px; justify-content: flex-end; }
.vic-tally-mine { font: 600 26px var(--font-display); color: var(--tone-txt); }
.vic-tally-sep { font: 400 13px var(--font-ui); color: rgba(255, 255, 255, 0.25); }
.vic-tally-theirs { font: 600 26px var(--font-display); color: rgba(255, 255, 255, 0.55); }
.vic-tally-dia {
  align-self: center; flex: none;
  width: 8px; height: 8px;
  border: 1px solid rgba(217, 177, 96, 0.5);
  transform: rotate(45deg);
}

/* ---- body: everything left over after the header and footer ---- */
.vic-body {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  padding: 24px 34px 28px;
}
.vic-points {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 16px;
  flex: none; flex-wrap: wrap; row-gap: 8px;
}
.vic-points.hidden { display: none; }
.vic-dot {
  width: 6px; height: 6px; flex: none;
  background: #d9b160;
  transform: rotate(45deg);
  box-shadow: 0 0 9px #d9b160;
  animation: vicPulse 2.4s ease-in-out infinite;
}
@keyframes vicPulse {
  0%, 100% { opacity: 0.35; transform: rotate(45deg) scale(1); }
  50%      { opacity: 0.9;  transform: rotate(45deg) scale(1.35); }
}
.vic-point-txt { font: 600 12px var(--font-ui); letter-spacing: 0.18em; color: #f0d08a; white-space: nowrap; }
.vic-point-hint { font: 400 11.5px var(--font-ui); color: rgba(255, 255, 255, 0.42); white-space: nowrap; }
.vic-hair { flex: 1; min-width: 40px; height: 1px; background: linear-gradient(90deg, rgba(217, 177, 96, 0.3), transparent); }
.vic-count-lbl { font: 400 9.5px var(--font-ui); letter-spacing: 0.18em; color: rgba(255, 255, 255, 0.28); white-space: nowrap; }

/* One row of six at this width. Centred in the leftover height rather than
   stretched into it — a card pulled to 370px is mostly gap. */
#upgradeCards {
  flex: 1; min-height: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 10px;
  align-content: center;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* ---- the cards ---- */
.upgrade {
  width: auto;
  display: flex;
  padding: 1px;
  border: 0;
  border-radius: 0;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.045));
  clip-path: polygon(13px 0, 100% 0, 100% calc(100% - 13px), calc(100% - 13px) 100%, 0 100%, 0 13px);
  box-shadow: none;
  cursor: pointer;
  transition: background 0.16s ease;
  transform: none;
}
.upgrade:hover { filter: none; transform: none; }
.upgrade:active { transform: none; }
.upgrade .u-in {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
  background: #0f0c11;
  clip-path: polygon(12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%, 0 12px);
  padding: 16px 12px 13px;
}
/* Reserved on every card, filled only on the ultimate — an empty slot keeps
   the icons on one line instead of stepping the ultimate down by its caption. */
.upgrade .u-cat {
  height: 13px; min-height: 0; margin: 0;
  text-align: center;
  font: 400 8px/13px var(--font-ui); letter-spacing: 0.2em;
  color: rgba(255, 255, 255, 0.3);
}
/* the icon frame is a diamond, so its contents are turned back */
.upgrade .u-orb {
  width: 34px; height: 34px; margin: 0 auto; flex: none;
  border: 1px dashed rgba(255, 255, 255, 0.22);
  transform: rotate(45deg);
  display: flex; align-items: center; justify-content: center;
}
.upgrade .u-orb > * { transform: rotate(-45deg); }
.upgrade .u-icon { font-size: 15px; line-height: 1; height: auto; }
.upgrade .u-img { width: 20px; height: 20px; object-fit: contain; image-rendering: pixelated; border: 0; }
.upgrade .u-name {
  margin-top: 13px;
  text-align: center;
  font: 700 14px var(--font-display); letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.65);
}
.upgrade .u-tip {
  margin-top: 7px;
  text-align: center;
  font: 400 10px/1.55 var(--font-ui);
  color: rgba(255, 255, 255, 0.32);
  text-wrap: pretty;
  height: 31px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.upgrade .u-rule {
  display: block;
  margin: 13px auto; width: 60%; height: 1px;
  background: rgba(255, 255, 255, 0.08);
}
.upgrade .u-desc {
  margin: 0; padding: 0; border: 0;
  text-align: center;
  font: 400 10.5px/1.55 var(--font-ui);
  color: rgba(255, 255, 255, 0.35);
  height: 33px;
  overflow: hidden;
}
.upgrade .u-lvl {
  margin-top: auto;
  padding-top: 13px;
  display: flex; justify-content: center;
}
.upgrade .u-lvl::before {
  content: attr(data-badge);
  font: 500 9.5px var(--font-ui); letter-spacing: 0.16em;
  padding: 5px 11px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.4);
  white-space: nowrap;
}

/* locked: nothing spent on it yet, and the dashed frame says so */
.upgrade.locked .u-name { color: rgba(255, 255, 255, 0.65); }

/* unlocked and rankable: lit, and the badge becomes solid gold */
.upgrade.owned {
  background: linear-gradient(160deg, rgba(217, 177, 96, 0.9), rgba(217, 177, 96, 0.25));
  box-shadow: 0 0 38px -12px rgba(217, 177, 96, 0.6);
}
.upgrade.owned .u-in { background: linear-gradient(180deg, rgba(217, 177, 96, 0.15), rgba(217, 177, 96, 0.02)), #100d12; }
.upgrade.owned .u-orb { border-style: solid; border-color: rgba(217, 177, 96, 0.6); background: rgba(217, 177, 96, 0.12); }
.upgrade.owned .u-name { color: #f5ecdd; }
.upgrade.owned .u-tip { color: rgba(255, 255, 255, 0.45); }
.upgrade.owned .u-rule { background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.4), transparent); }
.upgrade.owned .u-desc { color: rgba(255, 255, 255, 0.6); }
.upgrade.owned .u-lvl::before {
  background: linear-gradient(160deg, #f0d08a, #d9b160);
  color: #120f0a;
  border: 0;
  font-weight: 700;
  clip-path: polygon(6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%, 0 6px);
}

/* an ultimate, sealed or not */
.upgrade.ult { background: linear-gradient(160deg, rgba(217, 177, 96, 0.5), rgba(217, 177, 96, 0.12)); }
.upgrade.ult .u-in { background: linear-gradient(180deg, rgba(217, 177, 96, 0.07), rgba(255, 255, 255, 0.006)), #0f0c11; }
.upgrade.ult .u-cat { letter-spacing: 0.22em; color: rgba(217, 177, 96, 0.75); }
.upgrade.ult .u-orb { border-style: solid; border-color: rgba(217, 177, 96, 0.45); background: rgba(217, 177, 96, 0.07); }
.upgrade.ult .u-name { color: #f0d08a; }
.upgrade.ult .u-rule { background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.3), transparent); }
.upgrade.ult .u-desc { color: rgba(255, 255, 255, 0.4); }
.upgrade.ult .u-lvl::before { border-color: rgba(217, 177, 96, 0.35); color: rgba(217, 177, 96, 0.8); }

/* passives: always available, never locked */
.upgrade.passive { background: linear-gradient(160deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.05)); }
.upgrade.passive .u-in { background: #100d12; }
.upgrade.passive .u-orb { border-style: solid; border-color: rgba(255, 255, 255, 0.24); }
.upgrade.passive .u-name { color: #e8e2d6; }
.upgrade.passive .u-tip { color: rgba(255, 255, 255, 0.4); }
.upgrade.passive .u-desc { color: rgba(255, 255, 255, 0.55); }
.upgrade.passive .u-lvl::before { border-color: rgba(255, 255, 255, 0.16); color: rgba(255, 255, 255, 0.5); }

/* the one you have picked, before you commit the point to it */
.upgrade.picked {
  background: linear-gradient(160deg, #f0d08a, rgba(217, 177, 96, 0.45)) !important;
  box-shadow: 0 0 44px -10px rgba(217, 177, 96, 0.85) !important;
}
/* ...and its face warms from the bottom, so the pick reads on the card itself
   and not only on its edge — the edge alone was easy to miss in a row of six. */
.upgrade.picked .u-in {
  background: linear-gradient(0deg, rgba(217, 177, 96, 0.22), rgba(217, 177, 96, 0.04) 55%, transparent), #100d12;
}
.upgrade:not(.disabled):hover { background: linear-gradient(160deg, rgba(217, 177, 96, 0.7), rgba(217, 177, 96, 0.18)); }
.upgrade.disabled { cursor: not-allowed; opacity: 0.45; filter: none; }
.upgrade.disabled:hover { background: linear-gradient(160deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.045)); }

/* the point is being kept rather than spent */
#upgradeCards.saving .upgrade:not(.picked) { opacity: 0.3; }

/* ---- footer ---- */
.vic-foot {
  flex: none;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 20px; row-gap: 14px;
  padding: 18px 34px 20px;
  border-top: 1px solid rgba(217, 177, 96, 0.2);
  background: linear-gradient(180deg, transparent, rgba(217, 177, 96, 0.05));
}
.vic-next { grid-column: 2; display: flex; align-items: center; gap: 12px; }
.vic-tick {
  width: 28px; height: 28px; flex: none;
  display: grid; place-items: center;
  border: 0;
  background: #100d12;
  clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px);
  box-shadow: inset 0 0 0 1px rgba(217, 177, 96, 0.5);
  font: 700 11px var(--font-ui);
  color: #f0d08a;
}
/* the last seconds beat once a second, so the number stops being a readout
   and starts being a deadline */
.vic-tick.urgent {
  animation: lobPulse 1s steps(2, end) infinite;
  box-shadow: inset 0 0 0 1px #e0604f;
  color: #e0604f;
}
.next-round { font: 400 11.5px var(--font-ui); letter-spacing: 0.1em; color: rgba(255, 255, 255, 0.45); }

.vic-actions { grid-column: 3; justify-self: end; display: flex; align-items: center; gap: 10px; }

/* The match-over footer. Three things, three places: BACK TO LOBBY on the
   left, the countdown line over a large REMATCH in the centre — the one thing
   most players want next, under the one line they are reading — and CHANGE
   LOADOUT on the right. The round-intermission footer above keeps its shape;
   this only rearranges what is already there, by grid placement. */
.vic-foot.over { grid-template-columns: 1fr auto 1fr; grid-template-rows: auto auto; row-gap: 12px; }
.vic-foot.over .vic-next { grid-column: 2; grid-row: 1; justify-self: center; }
.vic-foot.over .vic-actions { display: contents; }
.vic-foot.over #vicLeaveBtn { grid-column: 1; grid-row: 1 / 3; justify-self: start; align-self: center; }
.vic-foot.over #changeLoadoutBtn { grid-column: 3; grid-row: 1 / 3; justify-self: end; align-self: center; }
.vic-foot.over #rematchBtn {
  grid-column: 2; grid-row: 2; justify-self: center;
  height: 52px; padding: 0 44px;
  font-size: 13.5px; letter-spacing: 0.24em;
  clip-path: polygon(15px 0, 100% 0, 100% calc(100% - 15px), calc(100% - 15px) 100%, 0 100%, 0 15px);
}
.vic-btn {
  font-family: var(--font-ui);
  border: 0; border-radius: 0;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.16s ease, color 0.16s ease, box-shadow 0.16s ease;
}
.vic-btn.hidden { display: none; }
.vic-btn.ghost {
  height: 40px; padding: 0 18px;
  background: none;
  font: 500 11px var(--font-ui); letter-spacing: 0.18em;
  color: rgba(255, 255, 255, 0.42);
}
.vic-btn.ghost:hover { color: #d9b160; background: none; }
/* One layer, not two: these buttons carry a label the client writes, so there
   is no inner element to give the face to. A clipped inset border traces the
   same notch the two-layer tiles get. */
.vic-btn.outline {
  height: 40px; padding: 0 18px;
  display: flex; align-items: center;
  background: #100d12;
  clip-path: polygon(11px 0, 100% 0, 100% calc(100% - 11px), calc(100% - 11px) 100%, 0 100%, 0 11px);
  box-shadow: inset 0 0 0 1px rgba(217, 177, 96, 0.5);
  font: 600 11px var(--font-ui); letter-spacing: 0.18em;
  color: #d9b160;
}
.vic-btn.outline:hover { background: rgba(217, 177, 96, 0.1); box-shadow: inset 0 0 0 1px #d9b160; }
.vic-btn.primary {
  height: 40px;
  display: flex; align-items: center; gap: 12px;
  padding: 0 30px;
  background: linear-gradient(160deg, #f0d08a, #d9b160 55%, #c39c4c);
  clip-path: polygon(13px 0, 100% 0, 100% calc(100% - 13px), calc(100% - 13px) 100%, 0 100%, 0 13px);
  box-shadow: 0 0 34px -8px rgba(217, 177, 96, 0.6);
  color: #120f0a;
  font: 700 11.5px var(--font-ui); letter-spacing: 0.2em;
}
.vic-btn.primary:hover:not(:disabled) { background: linear-gradient(160deg, #f7dda0, #e6be6e 55%, #d0a856); }
.vic-btn.primary:disabled {
  background: #191419;
  color: rgba(255, 255, 255, 0.25);
  box-shadow: none;
  cursor: not-allowed;
}

#upgradeCards::-webkit-scrollbar { width: 8px; }
#upgradeCards::-webkit-scrollbar-thumb { background: rgba(217, 177, 96, 0.35); }
#upgradeCards::-webkit-scrollbar-track { background: rgba(255, 255, 255, 0.03); }
#upgradeCards { scrollbar-width: thin; scrollbar-color: rgba(217, 177, 96, 0.4) transparent; }

/* ---- match result stage ---------------------------------------------------
   From the "Match Victory" handoff, in the same language as the rest of the
   screen. Victor left and larger, defeated right, smaller and dimmed — the
   roles are fixed to the SIDES rather than to you, so losing is drawn the same
   shape as winning, which is the honest way round.

   The handoff marks both portraits with <image-slot>, its drag-a-file
   placeholder. The class sprites go straight in instead.                    */

#matchVictory { flex: 1; min-height: 0; display: grid; align-content: center; }
#matchVictory.hidden { display: none; }

.mv-stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 26px;
  padding: 8px 0 4px;
}

.mv-side { display: flex; align-items: center; flex-wrap: wrap; row-gap: 16px; }
.mv-left { gap: 22px; justify-content: flex-end; text-align: right; }
.mv-right { gap: 20px; }

/* ---- the two nameplates ---- */
.mv-lbl {
  display: flex; align-items: center; gap: 9px;
  margin-bottom: 9px;
  font: 400 9px var(--font-ui); letter-spacing: 0.24em;
  color: rgba(255, 255, 255, 0.3); white-space: nowrap;
}
.mv-left .mv-lbl { justify-content: flex-end; }
.mv-lbl.gold { color: rgba(217, 177, 96, 0.75); }
.mv-bullet {
  width: 7px; height: 7px; flex: none;
  border: 1px solid rgba(255, 255, 255, 0.24);
  transform: rotate(45deg);
}
.mv-lbl.gold .mv-bullet { border-color: rgba(217, 177, 96, 0.75); }

.mv-name { font: 700 21px var(--font-display); letter-spacing: 0.08em; color: rgba(255, 255, 255, 0.6); }
.mv-side.winner .mv-name {
  font-size: 28px; letter-spacing: 0.1em;
  color: #f5ecdd; text-shadow: 0 0 24px rgba(217, 177, 96, 0.4);
}
.mv-rule { display: block; margin-top: 11px; width: 80%; height: 1px; background: linear-gradient(90deg, rgba(255, 255, 255, 0.14), transparent); }
.mv-left .mv-rule { margin-left: auto; background: linear-gradient(270deg, rgba(255, 255, 255, 0.14), transparent); }
.mv-left.winner .mv-rule { background: linear-gradient(270deg, rgba(217, 177, 96, 0.45), transparent); }
.mv-right.winner .mv-rule { background: linear-gradient(90deg, rgba(217, 177, 96, 0.45), transparent); }

.mv-stats {
  display: flex; gap: 12px; margin-top: 11px;
  font: 400 10.5px var(--font-ui); color: rgba(255, 255, 255, 0.3); white-space: nowrap;
}
.mv-left .mv-stats { justify-content: flex-end; }
.mv-side.winner .mv-stats { color: rgba(255, 255, 255, 0.42); }
.mv-pipe { width: 1px; background: rgba(255, 255, 255, 0.12); }
.mv-side.winner .mv-pipe { background: rgba(255, 255, 255, 0.16); }
/* an empty second stat would leave a divider floating with nothing beside it */
.mv-extra:empty, .mv-extra:empty + .mv-pipe, .mv-pipe:has(+ .mv-extra:empty) { display: none; }

/* ---- the portraits ---- */
.mv-frame {
  position: relative; flex: none;
  padding: 2px;
  background: linear-gradient(160deg, rgba(217, 177, 96, 0.9), rgba(217, 177, 96, 0.2) 40%,
                              rgba(217, 177, 96, 0.12) 62%, rgba(217, 177, 96, 0.75));
  clip-path: polygon(16px 0, calc(100% - 16px) 0, 100% 16px, 100% calc(100% - 16px),
                     calc(100% - 16px) 100%, 16px 100%, 0 calc(100% - 16px), 0 16px);
  box-shadow: 0 0 54px -12px rgba(217, 177, 96, 0.6);
}
.mv-frame-in {
  position: relative;
  width: 172px; height: 206px;
  overflow: hidden;
  display: grid; place-items: center;
  background: linear-gradient(180deg, #181118, #0d0a0e);
  clip-path: polygon(15px 0, calc(100% - 15px) 0, 100% 15px, 100% calc(100% - 15px),
                     calc(100% - 15px) 100%, 15px 100%, 0 calc(100% - 15px), 0 15px);
}
.mv-wash {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(65% 52% at 50% 44%, rgba(217, 177, 96, 0.2), transparent 72%),
    repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.016) 0 9px, transparent 9px 18px);
}
.mv-ring {
  position: absolute; left: 50%; top: 30px;
  width: 132px; height: 132px; margin-left: -66px;
  border: 1px solid rgba(217, 177, 96, 0.3);
  border-radius: 50%;
  pointer-events: none;
}
.mv-ring.inner {
  top: 46px; width: 100px; height: 100px; margin-left: -50px;
  border: 1px dashed rgba(217, 177, 96, 0.16);
}
.mv-corner { position: absolute; width: 20px; height: 20px; pointer-events: none; z-index: 2; }
.mv-corner.tl { top: 8px; left: 8px; border-top: 1px solid rgba(217, 177, 96, 0.75); border-left: 1px solid rgba(217, 177, 96, 0.75); }
.mv-corner.tr { top: 8px; right: 8px; border-top: 1px solid rgba(217, 177, 96, 0.75); border-right: 1px solid rgba(217, 177, 96, 0.75); }
.mv-corner.bl { bottom: 8px; left: 8px; border-bottom: 1px solid rgba(217, 177, 96, 0.6); border-left: 1px solid rgba(217, 177, 96, 0.6); }
.mv-corner.br { bottom: 8px; right: 8px; border-bottom: 1px solid rgba(217, 177, 96, 0.6); border-right: 1px solid rgba(217, 177, 96, 0.6); }
/* The crown, over the victor's head and INSIDE the frame — the old one was
   absolutely positioned against whatever happened to be the nearest positioned
   ancestor, which after the redesign was the whole panel. Keyed on .winner,
   not on the left slot: you are always on the left now, win or lose. */
.mv-side.winner .mv-frame-in::after {
  content: '\1F451';
  position: absolute;
  left: 50%; top: 14px;
  transform: translateX(-50%);
  font-size: 30px;
  line-height: 1;
  z-index: 2;
  pointer-events: none;
  filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.8));
  animation: crownDrop 0.5s ease-out 0.85s both;
}
/* one ornament at the top of the frame, not two */
.mv-side.winner .mv-pin { display: none; }

/* the diamond pinned to the top edge, straddling it */
.mv-pin {
  position: absolute; left: 50%; top: -9px; margin-left: -9px;
  width: 18px; height: 18px;
  border: 1px solid #d9b160;
  background: #0d0a0e;
  transform: rotate(45deg);
  box-shadow: 0 0 16px rgba(217, 177, 96, 0.7);
}

/* the defeated side: smaller, plainer, dimmed */
.mv-frame.small {
  padding: 1px;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.05));
  box-shadow: none;
  opacity: 0.65;
  clip-path: polygon(12px 0, calc(100% - 12px) 0, 100% 12px, 100% calc(100% - 12px),
                     calc(100% - 12px) 100%, 12px 100%, 0 calc(100% - 12px), 0 12px);
}
.mv-frame.small .mv-frame-in {
  width: 118px; height: 142px;
  background: #0f0c11;
  clip-path: polygon(11px 0, calc(100% - 11px) 0, 100% 11px, 100% calc(100% - 11px),
                     calc(100% - 11px) 100%, 11px 100%, 0 calc(100% - 11px), 0 11px);
}
.mv-frame.small .mv-wash { background: repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.012) 0 9px, transparent 9px 18px); }

.victor-av {
  position: relative; z-index: 1;
  max-width: 74%; max-height: 82%;
  width: auto; height: auto;
  margin: 0;
  object-fit: contain;
  image-rendering: pixelated;
  filter: drop-shadow(0 10px 22px rgba(0, 0, 0, 0.7));
}

/* ---- the divider between them ---- */
.mv-vs { display: flex; flex-direction: column; align-items: center; gap: 9px; }
.mv-line { width: 1px; height: 52px; background: linear-gradient(180deg, transparent, rgba(217, 177, 96, 0.4)); }
.mv-line:last-child { background: linear-gradient(0deg, transparent, rgba(217, 177, 96, 0.4)); }
.mv-dia { width: 11px; height: 11px; border: 1px solid rgba(217, 177, 96, 0.7); transform: rotate(45deg); }
.mv-vs span { font: 600 13px var(--font-display); letter-spacing: 0.24em; color: rgba(217, 177, 96, 0.7); }

/* The winner/loser classes the client sets are already expressed by the SIDE
   an entry sits on — the stage is built so the victor is always on the left.
   Kept as hooks, with nothing hanging off them. */
.victor-wiz.winner, .victor-wiz.loser { }

@media (max-width: 860px) {
  .mv-stage { grid-template-columns: 1fr; gap: 16px; justify-items: center; }
  .mv-left, .mv-right { justify-content: center; text-align: center; }
  .mv-left .mv-stats, .mv-left .mv-lbl { justify-content: center; }
  .mv-left .mv-rule, .mv-rule { margin-left: auto; margin-right: auto; }
  .mv-vs { flex-direction: row; }
  .mv-line { width: 36px; height: 1px; background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.4)); }
  .mv-line:last-child { background: linear-gradient(270deg, transparent, rgba(217, 177, 96, 0.4)); }
}

/* On a short screen 16:9 stops being worth what it costs — the header and
   footer are a fixed size, so the ratio squeezes the middle to nothing. Below
   this the panel takes its natural height and the backdrop scrolls. */
@media (max-width: 860px) {
  .vic-foot { grid-template-columns: 1fr; justify-items: center; }
  .vic-next, .vic-actions { grid-column: 1; justify-self: center; }
  .vic-actions { flex-wrap: wrap; justify-content: center; }
}

@media (max-height: 640px) {
  .vic-frame { height: auto; aspect-ratio: auto; width: min(1240px, 94vw); }
  .vic-head { padding: 20px 26px 18px; }
  .vic-title { font-size: 30px; }
  .vic-tally-mine, .vic-tally-theirs { font-size: 21px; }
  .vic-body { padding: 18px 26px 20px; }
  .vic-foot { padding: 14px 26px 16px; }
  #upgradeCards { min-height: 250px; }
}



/* ================= LOADOUT ===============================================
   Rebuilt from the "Loadout" handoff, from scratch. The screen is drawn from
   two shapes and nothing else: a rectangle with notched corners, and a square
   turned 45 degrees. Every frame, tile, button and bullet is one of those two,
   which is what makes the panel read as a single object rather than a form.

   One thing carried over from the build this replaces, because it solves a
   problem the handoff never had to think about: the ultimate list and the
   ability pool SCROLL at a fixed height. Earth has three ultimates and
   everyone else has two, so a list that grows to fit resizes the whole panel
   every time you click a different class.                                    */

.ldx-frame {
  width: min(1240px, 96vw);
  padding: 2px;                       /* the gilt edge is a gradient underneath */
  background: linear-gradient(150deg,
    rgba(217, 177, 96, 0.8),
    rgba(217, 177, 96, 0.14) 32%,
    rgba(217, 177, 96, 0.08) 68%,
    rgba(217, 177, 96, 0.65));
  clip-path: polygon(26px 0, calc(100% - 26px) 0, 100% 26px, 100% calc(100% - 26px),
                     calc(100% - 26px) 100%, 26px 100%, 0 calc(100% - 26px), 0 26px);
  box-shadow: 0 40px 110px -35px #000;
}
.ldx {
  position: relative;
  background: #0c0a0e;
  text-align: left;
  clip-path: polygon(25px 0, calc(100% - 25px) 0, 100% 25px, 100% calc(100% - 25px),
                     calc(100% - 25px) 100%, 25px 100%, 0 calc(100% - 25px), 0 25px);
}

/* ---- crest ---- */
.ldx-head {
  position: relative;
  overflow: hidden;
  padding: 28px 34px 22px;
  border-bottom: 1px solid rgba(217, 177, 96, 0.2);
  background: radial-gradient(120% 130% at 50% -30%, rgba(217, 177, 96, 0.12), transparent 62%);
}
.ldx-sweep {
  position: absolute; top: 0; left: 0;
  width: 22%; height: 2px;
  background: linear-gradient(90deg, transparent, #d9b160, transparent);
  animation: ldx-sweep 3.4s linear infinite;
}
@keyframes ldx-sweep { from { transform: translateX(-100%); } to { transform: translateX(300%); } }

.ldx-crest { display: flex; align-items: center; justify-content: center; gap: 16px; }
.ldx-rule { flex: 1; height: 1px; background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.5)); }
.ldx-rule.flip { background: linear-gradient(270deg, transparent, rgba(217, 177, 96, 0.5)); }
.ldx-title {
  font: 700 24px var(--font-display);
  letter-spacing: 0.3em;
  color: #f5ecdd;
  text-shadow: 0 0 28px rgba(217, 177, 96, 0.4);
  white-space: nowrap;
}

/* The diamond. One rotated square, at three sizes and two weights — it is the
   bullet, the crest mark, the divider node and the icon frame. */
.ldx-dia {
  width: 11px; height: 11px; flex: none;
  border: 1px solid #d9b160;
  transform: rotate(45deg);
  box-shadow: 0 0 14px rgba(217, 177, 96, 0.6);
}
.ldx-dia.solid { background: #0d0a0e; }
.ldx-div .ldx-dia { width: 8px; height: 8px; border-color: rgba(217, 177, 96, 0.55); box-shadow: none; }
.ldx-bullet {
  width: 7px; height: 7px; flex: none;
  border: 1px solid rgba(217, 177, 96, 0.7);
  transform: rotate(45deg);
}

/* ---- section headers: bullet, label, hairline, optional note ---- */
.ldx-eyebrow { display: flex; align-items: center; gap: 9px; margin-bottom: 13px; }
.ldx-eyebrow.spaced { margin-top: 24px; }
.ldx-eyebrow > span {
  font: 400 9.5px var(--font-ui); letter-spacing: 0.2em;
  color: rgba(255, 255, 255, 0.34); white-space: nowrap;
}
.ldx-hair { flex: 1; height: 1px; background: linear-gradient(90deg, rgba(217, 177, 96, 0.3), transparent); }
.ldx-eyebrow > span.ldx-note {
  font: 400 9px var(--font-ui); letter-spacing: 0.16em; color: rgba(217, 177, 96, 0.75);
}
.ldx-eyebrow > span.ldx-count {
  font: 500 9.5px var(--font-ui); letter-spacing: 0.14em; color: rgba(217, 177, 96, 0.85);
}
.ldx-div { display: flex; align-items: center; gap: 9px; }
.ldx-div i { flex: 1; height: 1px; background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.3)); }
.ldx-div i:last-child { background: linear-gradient(270deg, transparent, rgba(217, 177, 96, 0.3)); }

.ldx-note-line { margin-top: 11px; font: 400 10px/1.6 var(--font-ui); color: rgba(255, 255, 255, 0.3); text-wrap: pretty; }
/* the one rule new players trip on, said in six words: caps, spaced, gold */
.ldx-note-line.punch { font: 600 10.5px/1.7 var(--font-ui); letter-spacing: 0.16em; color: rgba(239, 231, 216, 0.55); }
.ldx-note-line.punch b { color: #f0d08a; font-weight: 700; }

/* ---- the three columns ---- */
.ldx-cols {
  display: grid;
  grid-template-columns: minmax(230px, 272px) minmax(0, 1fr) minmax(230px, 304px);
  align-items: stretch;
}
.ldx-side { padding: 24px 22px; background: linear-gradient(180deg, rgba(217, 177, 96, 0.06), transparent 42%); }
.ldx-side.left { border-right: 1px solid rgba(217, 177, 96, 0.14); }
.ldx-side.right { border-left: 1px solid rgba(217, 177, 96, 0.14); display: flex; flex-direction: column; gap: 20px; }
.ldx-mid { padding: 24px 26px; }

/* ---- the wizard: a gilded reliquary, notched on all four corners ---- */
.ldx-hero {
  position: relative;
  padding: 2px;
  background: linear-gradient(160deg, rgba(217, 177, 96, 0.85), rgba(217, 177, 96, 0.18) 38%,
                              rgba(217, 177, 96, 0.1) 62%, rgba(217, 177, 96, 0.7));
  clip-path: polygon(18px 0, calc(100% - 18px) 0, 100% 18px, 100% calc(100% - 18px),
                     calc(100% - 18px) 100%, 18px 100%, 0 calc(100% - 18px), 0 18px);
  box-shadow: 0 0 46px -14px rgba(217, 177, 96, 0.5);
}
.ldx-hero-in {
  position: relative;
  background: linear-gradient(180deg, #171017, #0d0a0e 55%, #0b090c);
  clip-path: polygon(17px 0, calc(100% - 17px) 0, 100% 17px, 100% calc(100% - 17px),
                     calc(100% - 17px) 100%, 17px 100%, 0 calc(100% - 17px), 0 17px);
}
.ldx-hero-art {
  position: relative;
  height: 246px;
  overflow: hidden;
  display: grid; place-items: center;
  background: repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.016) 0 9px, transparent 9px 18px);
}
/* the two circles the wizard stands inside */
.ldx-ring {
  position: absolute; left: 50%; top: 34px;
  width: 150px; height: 150px; margin-left: -75px;
  border: 1px solid rgba(217, 177, 96, 0.28);
  border-radius: 50%;
  pointer-events: none;
}
.ldx-ring.inner {
  top: 52px; width: 114px; height: 114px; margin-left: -57px;
  border: 1px dashed rgba(217, 177, 96, 0.16);
}
/* The handoff draws two crisp gold rings behind the wizard, and the old build
   drew a pulsing ring tinted by class. Three concentric circles is one too
   many: the gold rings are the frame, and the class keeps the soft wash behind
   them, which is what actually reads as fire versus frost. */
.ldx-hero-art .ld-sigil { display: none; }
.ldx-hero-art .ld-glow {
  top: 108px;
  width: 210px; height: 210px; margin: -105px 0 0 -105px;
}
.ldx-hero-art .ld-wizard {
  position: relative; z-index: 1;
  /* the base rule lifts the sprite 54px to clear a caption that is no longer
     under it — it sits centred in the frame now, feet in the fade */
  margin: 0;
  max-width: 74%; max-height: 84%;
  width: auto; height: auto;
  object-fit: contain;
  image-rendering: pixelated;
}
/* the art fades into the nameplate rather than stopping at an edge */
.ldx-artfade {
  position: absolute; left: 0; right: 0; bottom: 0; height: 90px;
  background: linear-gradient(0deg, #0d0a0e, transparent);
  pointer-events: none; z-index: 2;
}
.ldx-corner { position: absolute; width: 22px; height: 22px; pointer-events: none; z-index: 3; }
.ldx-corner.tl { top: 9px; left: 9px; border-top: 1px solid rgba(217, 177, 96, 0.7); border-left: 1px solid rgba(217, 177, 96, 0.7); }
.ldx-corner.tr { top: 9px; right: 9px; border-top: 1px solid rgba(217, 177, 96, 0.7); border-right: 1px solid rgba(217, 177, 96, 0.7); }
.ldx-corner.bl { bottom: 9px; left: 9px; border-bottom: 1px solid rgba(217, 177, 96, 0.55); border-left: 1px solid rgba(217, 177, 96, 0.55); }
.ldx-corner.br { bottom: 9px; right: 9px; border-bottom: 1px solid rgba(217, 177, 96, 0.55); border-right: 1px solid rgba(217, 177, 96, 0.55); }

/* the diamond that pins the art to the nameplate, straddling the seam */
.ldx-hero-sep {
  position: relative; z-index: 4;
  margin-top: -13px;
  display: flex; align-items: center; gap: 9px;
  padding: 0 14px;
}
.ldx-hero-sep i { flex: 1; height: 1px; background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.55)); }
.ldx-hero-sep i:last-child { background: linear-gradient(270deg, transparent, rgba(217, 177, 96, 0.55)); }

.ldx-hero-meta { padding: 14px 16px 18px; text-align: center; }
.ldx-hero-name {
  font: 700 22px var(--font-display); letter-spacing: 0.08em;
  color: #f0d08a; text-shadow: 0 0 22px rgba(217, 177, 96, 0.45);
}
.ldx-hero-tag {
  margin-top: 6px; min-height: 11px;
  font: 400 8.5px var(--font-ui); letter-spacing: 0.26em; color: rgba(217, 177, 96, 0.65);
}
/* Two lines reserved for each of these: the classes describe themselves at
   different lengths, and without a floor the card grows and shrinks as you
   click through them. */
.ldx-hero-line {
  margin-top: 11px; min-height: 36px;
  font: 400 11px/1.65 var(--font-ui); color: rgba(255, 255, 255, 0.45); text-wrap: pretty;
}
.ldx-hero-rule {
  display: block; margin: 13px auto 0; width: 70%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.35), transparent);
}
.ldx-hero-sig {
  margin-top: 11px; min-height: 32px;
  font: 400 10px/1.6 var(--font-ui); color: rgba(255, 255, 255, 0.32); text-wrap: pretty;
}

/* ---- tiles: the shared two-layer notch ----------------------------------
   Every card the client builds is an outer div (which becomes the 1px gilt
   edge) wrapping .ld-card-in (the face). That is exactly the handoff's
   construction, so the two layers take the two clip paths and nothing about
   the markup the client generates has to change.                            */
.ldx .ld-card {
  position: relative;
  padding: 1px;
  border: 0;
  border-radius: 0;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.05));
  clip-path: polygon(12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%, 0 12px);
  box-shadow: none;
  cursor: pointer;
  transition: background 0.16s ease;
}
.ldx .ld-card:hover { background: linear-gradient(160deg, rgba(217, 177, 96, 0.7), rgba(217, 177, 96, 0.18)); }
/* the client sets border/shadow/background inline on the chosen card, in the
   old flat-card idiom — this is the one place that has to win outright */
.ldx .ld-card.on {
  border: 0 !important;
  background: linear-gradient(160deg, rgba(217, 177, 96, 0.85), rgba(217, 177, 96, 0.25)) !important;
  box-shadow: 0 0 34px -12px rgba(217, 177, 96, 0.6) !important;
}
.ldx .ld-card.disabled { opacity: 0.4; cursor: not-allowed; }
.ldx .ld-card.disabled:hover { background: linear-gradient(160deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.05)); }
.ldx .ld-card.static { cursor: default; }

.ldx .ld-card .ld-card-in {
  height: 100%;
  display: flex; flex-direction: column;
  /* .ld-card-in centres its flex children, which sizes each one to its own
     text — a short name was a 26px box, and the hairline under it 55% of
     that, so "Oil" got 14px of rule. Full width, centred by text-align. */
  align-items: stretch;
  gap: 0;
  background: #100d12;
  border-radius: 0;
  clip-path: polygon(11px 0, 100% 0, 100% calc(100% - 11px), calc(100% - 11px) 100%, 0 100%, 0 11px);
  padding: 15px 11px 13px;
  text-align: center;
}
.ldx .ld-card.on .ld-card-in {
  background: linear-gradient(180deg, rgba(217, 177, 96, 0.16), rgba(217, 177, 96, 0.03)), #100d12;
}

/* The icon frame is the same diamond as everything else, so whatever sits
   inside it has to be turned back the other way. */
.ldx .ld-orb {
  width: 32px; height: 32px;
  margin: 0 auto;
  flex: none;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 0;
  transform: rotate(45deg);
  display: flex; align-items: center; justify-content: center;
  background: none;                 /* the old radial glow is gone; the diamond is the frame */
  overflow: visible;
}
.ldx .ld-card.on .ld-orb { border-color: rgba(217, 177, 96, 0.6); background: rgba(217, 177, 96, 0.12) !important; }
.ldx .ld-orb > * { transform: rotate(-45deg); }
.ldx .ld-orb img { width: 20px; height: 20px; object-fit: contain; image-rendering: pixelated; }
.ldx .ld-orb-icon { font-size: 15px; line-height: 1; }

.ldx .ld-name {
  margin-top: 12px;
  font: 700 13.5px var(--font-display); letter-spacing: 0.06em;
  color: #e8e2d6;
}
.ldx .ld-card.on .ld-name { color: #f5ecdd; }
/* the hairline under every card name */
.ldx .ld-name::after {
  content: '';
  display: block;
  margin: 8px auto 0; width: 55%; height: 1px;
  background: rgba(255, 255, 255, 0.08);
}
.ldx .ld-card.on .ld-name::after { background: linear-gradient(90deg, transparent, rgba(217, 177, 96, 0.4), transparent); }
.ldx .ld-desc {
  margin-top: 9px;
  font: 400 10px/1.55 var(--font-ui); color: rgba(255, 255, 255, 0.4);
  text-wrap: pretty;
}
.ldx .ld-tag {
  margin-top: 7px;
  font: 400 8.5px var(--font-ui); letter-spacing: 0.16em;
  color: rgba(255, 255, 255, 0.32);
}
.ldx .ld-card.on .ld-tag { color: rgba(217, 177, 96, 0.85); }

/* ---- classes ---- */
.ldx-classes { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 9px; }
.ldx .ldx-classes .ld-card-in { padding: 15px 8px 13px; }
.ldx .ldx-classes .ld-name { font-size: 13px; letter-spacing: 0.05em; }
.ldx .ldx-classes .ld-name::after { width: 60%; }

/* ---- always on: the same tile, smaller, and the starter is the lit one ---- */
.ldx-baseline { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.ldx-baseline .ld-card {
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.05));
  clip-path: polygon(9px 0, 100% 0, 100% calc(100% - 9px), calc(100% - 9px) 100%, 0 100%, 0 9px);
}
.ldx-baseline .ld-card:first-child { background: linear-gradient(160deg, rgba(217, 177, 96, 0.45), rgba(255, 255, 255, 0.07)); }
.ldx .ldx-baseline .ld-card-in {
  clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px);
  padding: 11px 6px;
}
.ldx .ldx-baseline .ld-orb { width: 26px; height: 26px; }
.ldx .ldx-baseline .ld-card:first-child .ld-orb { border-color: rgba(217, 177, 96, 0.4); }
.ldx .ldx-baseline .ld-orb img { width: 16px; height: 16px; }
.ldx .ldx-baseline .ld-orb-icon { font-size: 13px; }
.ldx .ldx-baseline .ld-name {
  margin-top: 9px;
  font: 500 9px var(--font-ui); letter-spacing: 0.1em; color: rgba(255, 255, 255, 0.58);
}
.ldx .ldx-baseline .ld-name::after { content: none; }

/* ---- the ability pool ----------------------------------------------------
   A fixed-height scroller. Five cards over two rows fit at this width; the
   height is held either way so that switching class cannot move the footer. */
.ldx-pool {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 9px;
  align-content: start;
  /* two rows of cards plus the gap. Measured, not guessed: a card is 191px
     and five of them lay out 3 + 2. */
  height: 391px;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 4px;
}
.ldx .ldx-pool .ld-card-in { min-height: 176px; }
/* the EQUIP pill, pinned to the bottom of every pool card */
.ldx-pool .ld-card-in::after {
  content: 'EQUIP';
  margin: auto auto 0;
  padding: 4px 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  font: 500 9px var(--font-ui); letter-spacing: 0.16em;
  color: rgba(255, 255, 255, 0.45);
  white-space: nowrap;
}
.ldx-pool .ld-card.on .ld-card-in::after {
  content: 'EQUIPPED';
  border-color: rgba(217, 177, 96, 0.55);
  color: #f0d08a;
}
.ldx .ldx-pool .ld-desc { margin-bottom: 12px; }
/* The pick number, which is the only thing that makes "the order you pick sets
   what unlocks first" legible. A diamond, like everything else. */
.ldx .ldx-pool .ld-order {
  position: absolute; top: 9px; right: 9px;
  width: 20px; height: 20px;
  display: grid; place-items: center;
  border: 1px solid rgba(217, 177, 96, 0.7);
  border-radius: 0;
  background: #100d12;
  transform: rotate(45deg);
  font: 700 9px var(--font-ui); color: #f0d08a;
  z-index: 2;
}
/* and the numeral turns back out of it */
.ldx .ldx-pool .ld-order > span { display: block; transform: rotate(-45deg); }
/* The round-1 marker stays a SOLID green diamond — the base rule fills it, and
   it must not read as one more shade of gold on a gold panel. */
.ldx .ldx-pool .ld-card.first .ld-order {
  background: #64d98a;
  border-color: #64d98a;
  color: #07240f;
}

/* ---- ultimates: rows, not cards -----------------------------------------
   Same fixed height. Earth has three ultimates and the others two, so the box
   holds two and scrolls for the third rather than growing.                   */
.ldx-ults {
  display: flex; flex-direction: column; gap: 8px;
  /* exactly two rows plus their gap, measured at 85px a row */
  height: 178px;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 4px;
}
.ldx-ults > * { flex: none; }
.ldx-ults .ld-card {
  clip-path: polygon(13px 0, 100% 0, 100% calc(100% - 13px), calc(100% - 13px) 100%, 0 100%, 0 13px);
}
/* Three classes deep, to beat .ld-card.ability .ld-card-in — which pins a
   152px floor meant for pool cards and would make every row that tall. */
.ldx-ults .ld-card.ability .ld-card-in {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: 'orb name' 'orb desc';
  align-items: start;
  gap: 6px 12px;
  padding: 14px 13px;
  text-align: left;
  min-height: 0;
  clip-path: polygon(12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%, 0 12px);
}
.ldx .ldx-ults .ld-orb { grid-area: orb; align-self: center; margin: 0; }
.ldx .ldx-ults .ld-name { grid-area: name; margin-top: 0; }
.ldx .ldx-ults .ld-name::after { content: none; }
.ldx .ldx-ults .ld-desc {
  grid-area: desc; margin-top: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* ---- key binds: four notched squares across ---- */
.ldx-slots { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; }
.ldx-slotgroup { display: contents; }
.ldx-slots .ld-slot {
  position: relative;
  width: auto; height: auto;
  aspect-ratio: 1;
  min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  border: 0;
  border-radius: 0;
  padding: 0;
  overflow: hidden;
  background: #100d12;
  clip-path: polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16);
}
.ldx-slots .ld-slot.filled { box-shadow: inset 0 0 0 1px rgba(217, 177, 96, 0.35); }
.ldx-slots .ld-slot:hover { box-shadow: inset 0 0 0 1px #d9b160; }
.ldx-slots .ld-slot-key { font: 700 12px var(--font-ui); color: rgba(255, 255, 255, 0.48); line-height: 1; }
.ldx-slots .ld-slot.filled .ld-slot-key { color: rgba(240, 208, 138, 0.9); }
.ldx-slots .ld-slot-icon { font-size: 14px; line-height: 1; }
.ldx-slots .ld-slot-icon img { width: 17px; height: 17px; object-fit: contain; image-rendering: pixelated; }
/* the ability's name does not fit a 60px box, and its card already carries it */
.ldx-slots .ld-slot-label { display: none; }
/* The starter's slot carries the pick number, the same one its card shows in
   the pool. It was a 3px bar with the text hidden, which said "this one is
   special" without saying what about it. Green because it is a status, not a
   third shade of gold — and square, because a rotated one would need the
   numeral turned back inside it for no gain at this size. */
.ldx-slots .ld-slot-badge {
  position: absolute; top: 4px; right: 4px;
  width: 14px; height: 14px;
  display: grid; place-items: center;
  /* the same green as the 1 on its card in the pool, so the two read as one
     marker rather than two things that happen to be green */
  background: #64d98a;
  clip-path: polygon(4px 0, 100% 0, 100% calc(100% - 4px), calc(100% - 4px) 100%, 0 100%, 0 4px);
  font: 700 9px var(--font-ui); line-height: 1;
  color: #07240f;
}

/* ---- footer ---- */
.ldx-foot {
  display: flex; align-items: center; justify-content: flex-end;   /* actions only, since the hint line went */
  gap: 20px; row-gap: 14px; flex-wrap: wrap;
  padding: 18px 34px 20px;
  border-top: 1px solid rgba(217, 177, 96, 0.2);
  background: linear-gradient(180deg, transparent, rgba(217, 177, 96, 0.05));
}

.ldx-actions { display: flex; align-items: center; gap: 10px; }
.ldx-btn { font-family: var(--font-ui); border: 0; border-radius: 0; cursor: pointer; white-space: nowrap; }
.ldx-btn.ghost {
  height: 40px; padding: 0 18px;
  background: none;
  font: 500 11px var(--font-ui); letter-spacing: 0.18em;
  color: rgba(255, 255, 255, 0.42);
  transition: color 0.16s ease;
}
.ldx-btn.ghost:hover { color: #d9b160; }
/* RESET is the same two-layer notch as the tiles */
.ldx-btn.outline {
  padding: 1px;
  background: linear-gradient(160deg, rgba(217, 177, 96, 0.5), rgba(217, 177, 96, 0.14));
  clip-path: polygon(11px 0, 100% 0, 100% calc(100% - 11px), calc(100% - 11px) 100%, 0 100%, 0 11px);
  transition: background 0.16s ease;
}
.ldx-btn.outline:hover { background: linear-gradient(160deg, #d9b160, rgba(217, 177, 96, 0.35)); }
.ldx-btn.outline span {
  display: flex; align-items: center;
  height: 38px; padding: 0 18px;
  background: #100d12;
  clip-path: polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
  font: 600 11px var(--font-ui); letter-spacing: 0.18em; color: #d9b160;
}
.ldx-btn.primary {
  height: 40px;
  display: flex; align-items: center; gap: 12px;
  padding: 0 30px;
  background: linear-gradient(160deg, #f0d08a, #d9b160 55%, #c39c4c);
  clip-path: polygon(13px 0, 100% 0, 100% calc(100% - 13px), calc(100% - 13px) 100%, 0 100%, 0 13px);
  box-shadow: 0 0 34px -8px rgba(217, 177, 96, 0.6);
  color: #120f0a;
  font: 700 11.5px var(--font-ui); letter-spacing: 0.2em;
}
.ldx-btn.primary:disabled {
  background: #191419;
  color: rgba(255, 255, 255, 0.25);
  box-shadow: none;
  cursor: not-allowed;
}

/* ---- scrollbars, thin and gold so the racks read as part of the frame ---- */
.ldx-ults::-webkit-scrollbar, .ldx-pool::-webkit-scrollbar { width: 8px; }
.ldx-ults::-webkit-scrollbar-thumb, .ldx-pool::-webkit-scrollbar-thumb { background: rgba(217, 177, 96, 0.35); }
.ldx-ults::-webkit-scrollbar-track, .ldx-pool::-webkit-scrollbar-track { background: rgba(255, 255, 255, 0.03); }
.ldx-ults, .ldx-pool { scrollbar-width: thin; scrollbar-color: rgba(217, 177, 96, 0.4) transparent; }

/* On a short screen the racks give up height rather than the panel growing
   past the bottom of it. They already scroll — this only decides how much of
   each one you see at once. A 1440-tall display never reaches this. */
@media (max-height: 900px) {
  #loadout.overlay { padding: 20px 24px; }
  .ldx-hero-art { height: 176px; }
  .ldx-ring { top: 20px; width: 118px; height: 118px; margin-left: -59px; }
  .ldx-ring.inner { top: 34px; width: 90px; height: 90px; margin-left: -45px; }
  .ldx-hero-line { min-height: 0; }
  .ldx-hero-sig { min-height: 0; }
  /* the cards lose their reserved height too, or a 232px rack shows one row
     and a sliver of the next */
  .ldx .ldx-pool .ld-card-in { min-height: 132px; padding: 13px 10px 11px; }
  .ldx .ldx-pool .ld-desc { margin-bottom: 9px; }
  .ldx-pool { height: 262px; }
  .ldx-ults { height: 93px; }
  .ldx-head { padding: 20px 34px 16px; }
  .ldx-side, .ldx-mid { padding-top: 18px; padding-bottom: 18px; }
}

@media (max-width: 900px) {
  .ldx-cols { grid-template-columns: 1fr; }
  .ldx-side.left { border-right: 0; border-bottom: 1px solid rgba(217, 177, 96, 0.14); }
  .ldx-side.right { border-left: 0; border-top: 1px solid rgba(217, 177, 96, 0.14); }
}

/* ================= STOREFRONT (landing.html) ==============================
   What the bare domain shows while the purchase gate is on. It borrows the
   menu's stage, panel, logo, rule and tagline wholesale, and its one button is
   a .mn-item that happens to be a link — same notch, same gilt edge, always in
   the hovered state because there is nothing else to choose. */
.land-blurb {
  margin: 34px 0 0;
  width: 100%;
  font: 400 17px/1.55 var(--font-body);
  letter-spacing: 0.02em;
  color: rgba(239, 231, 216, 0.78);
}
.land-cta {
  margin-top: 26px;
  text-decoration: none;
  background: linear-gradient(160deg, #d9b160, rgba(217, 177, 96, 0.3));
  box-shadow: 0 0 40px -12px rgba(217, 177, 96, 0.65);
}
.land-cta::before {
  background: linear-gradient(100deg, rgba(217, 177, 96, 0.2), rgba(217, 177, 96, 0.03)), rgba(16, 13, 18, 0.94);
}
.land-cta .mn-dot { background: #f0d08a; box-shadow: 0 0 12px rgba(217, 177, 96, 0.9); }
.land-cta .mn-label { color: #f5ecdd; text-shadow: 0 0 20px rgba(217, 177, 96, 0.5); }
.land-cta .mn-hint { color: rgba(240, 208, 138, 0.85); font-weight: 500; }
.land-cta:hover { background: linear-gradient(160deg, #f0d08a, rgba(217, 177, 96, 0.45)); }
.land-cta:hover .mn-label { color: #fff8ea; }

/* A friend's invite carried a room code the storefront cannot act on, so it is
   at least handed back, large, for typing in once the game is open. */
.land-room {
  margin-top: 24px;
  padding: 14px 20px;
  border: 1px solid rgba(232, 198, 106, 0.35);
  background: rgba(12, 12, 16, 0.72);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.land-room-lbl { font-size: 12px; letter-spacing: 0.28em; color: rgba(239, 231, 216, 0.5); }
.land-room-code { font: 700 34px var(--font-ui); letter-spacing: 0.3em; color: var(--mn-gold); }

.land-own {
  margin: 22px 0 0;
  width: 100%;
  font: 400 14px/1.5 var(--font-body);
  color: rgba(239, 231, 216, 0.45);
}

/* ================= BIG SCREENS ============================================
   Two scales, set by game.js, never below 1 so laptops are untouched.

   --ui-scale is for the HUD, which overlaps the arena and is comfortable as
   drawn up to a 2560×1440 window; it grows only past that. --panel-scale is
   for the panels — loadout, match result, lobby, settings — which sit on a
   dimmed overlay and were drawn to fill 1080p; they grow from there, so on a
   1440p window they are a third larger while the HUD is not. The WORLD has a
   rule of its own again (see more arena before anything scales).

   The main menu is not here: its stage is fitted by transform. Nor are the
   full-screen overlays themselves — zooming inset:0 is meaningless — only the
   panels inside them. */
:root { --ui-scale: 1; --panel-scale: 1; }
#playerBar, #roundBanner, #roomBadge, #respawn, .status, #chatFeed, #chatInput, #countNum, #countHint {
  zoom: var(--ui-scale);
}
.ldx-frame, .vic-frame, .lob-frame, #settingsModal .mn-dialog {
  zoom: var(--panel-scale);
}

/* ================= TOUCH DEVICES ==========================================
   A plaque over the menu when the primary pointer is a finger. Fixed to the
   viewport, not to the scaled stage. `hover: none` alongside `pointer: coarse`
   keeps a touchscreen laptop, whose primary pointer is still the mouse, from
   seeing it. */
#touchNote { display: none; }
@media (pointer: coarse) and (hover: none) {
  #touchNote {
    position: fixed;
    left: 50%; bottom: 8vh;
    transform: translateX(-50%);
    z-index: 35;
    width: min(86vw, 420px);
    padding: 16px 20px;
    text-align: center;
    background: rgba(12, 10, 14, 0.94);
    border: 1px solid rgba(217, 177, 96, 0.55);
    clip-path: polygon(12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%, 0 12px);
    color: #f5ecdd;
    font: 700 13px/1.5 var(--font-ui);
    letter-spacing: 0.14em;
    display: flex; flex-direction: column; gap: 6px;
  }
  #touchNote small {
    font: 400 11px/1.5 var(--font-ui);
    letter-spacing: 0.04em;
    color: rgba(239, 231, 216, 0.6);
  }
}

/* ================= THE HUD IS NOT A THING YOU CLICK ========================
   Every piece of it is display only, so clicks fall through to the canvas
   and firing keeps working with the cursor over the bar — before this, a
   click that landed on the HUD was swallowed, which mid-fight read as the
   game ignoring you. The chat input is the one interactive element inside
   it; the feed re-enables itself while open (see #chatFeed.log). */
#hud { pointer-events: none; }
#chatInput { pointer-events: auto; }

/* ================= THE DUEL PASS BUTTON ====================================
   Lives inside the waiting banner's sub-line, which is re-rendered every
   frame; a small notched button in the banner's own type. */
.banner-btn {
  pointer-events: auto;        /* the HUD around it is click-through */
  margin-left: 6px;
  padding: 3px 10px 2px;
  border: 0; border-radius: 0;
  background: linear-gradient(160deg, #f0d08a, #d9b160);
  clip-path: polygon(7px 0, 100% 0, 100% calc(100% - 7px), calc(100% - 7px) 100%, 0 100%, 0 7px);
  color: #120f0a;
  font: 700 10px var(--font-ui); letter-spacing: 0.16em;
  cursor: pointer;
  vertical-align: middle;
}
.banner-btn:hover { background: linear-gradient(160deg, #f7dda0, #e6be6e); }
/* the storefront's spent-pass note shares the invite box's dress */
.land-pass-txt { font: 400 13px/1.5 var(--font-body); color: rgba(239, 231, 216, 0.7); }
/* the pass button on its own row under the banner text, centred */
#roundBanner .pass-row { margin-top: 7px; text-align: center; }
#roundBanner .pass-row .banner-btn { margin-left: 0; padding: 5px 14px 4px; font-size: 10.5px; }

/* ================= SPELLBOOK ==============================================
   Every ability per class, in the lobby's gilded shell. A plain list: the
   bar's icon in the house diamond, the name, the loadout's description, the
   numbers in mono, what each rank adds. Class tabs in the crest header. */
.sb-tabs { display: flex; justify-content: center; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
.sb-tab {
  padding: 7px 14px;
  border: 1px solid rgba(217, 177, 96, 0.28); border-radius: 0;
  background: rgba(0, 0, 0, 0.25);
  clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px);
  font: 600 10.5px var(--font-ui); letter-spacing: 0.16em;
  color: rgba(239, 231, 216, 0.6);
  cursor: pointer;
}
.sb-tab:hover { color: #f5ecdd; border-color: rgba(217, 177, 96, 0.55); }
.sb-tab.on { background: linear-gradient(160deg, #f0d08a, #d9b160); color: #120f0a; border-color: transparent; }

.sb-list {
  padding: 18px 26px 22px;
  max-height: min(62vh, 640px);
  overflow-y: auto;
}
.sb-list::-webkit-scrollbar { width: 8px; }
.sb-list::-webkit-scrollbar-thumb { background: rgba(217, 177, 96, 0.35); }
.sb-eyebrow {
  display: flex; align-items: center; gap: 10px;
  margin: 16px 0 8px;
  font: 400 9.5px var(--font-ui); letter-spacing: 0.26em;
  color: rgba(217, 177, 96, 0.75);
}
.sb-eyebrow:first-child { margin-top: 0; }
.sb-row {
  display: flex; align-items: flex-start; gap: 16px;
  padding: 10px 12px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.02);
  clip-path: polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
}
.sb-row + .sb-row { margin-top: 6px; }
/* the diamond: rotated, with its contents turned back — see .ld-orb */
.sb-orb {
  flex: none; width: 34px; height: 34px; margin: 6px 4px 0 6px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  transform: rotate(45deg);
  display: flex; align-items: center; justify-content: center;
}
.sb-orb > * { transform: rotate(-45deg); }
.sb-orb span { font-size: 16px; line-height: 1; }
.sb-orb img { width: 20px; height: 20px; object-fit: contain; image-rendering: pixelated; }
.sb-body { min-width: 0; flex: 1; }
.sb-name { font: 700 15px var(--font-display); letter-spacing: 0.04em; color: #f5ecdd; }
.sb-key {
  margin-left: 8px; padding: 2px 7px; vertical-align: middle;
  border: 1px solid rgba(217, 177, 96, 0.45);
  font: 600 9px var(--font-ui); letter-spacing: 0.16em; color: #f0d08a;
}
.sb-desc { margin-top: 3px; font: 400 12.5px/1.45 var(--font-body); color: rgba(239, 227, 200, 0.62); }
.sb-stats { margin-top: 5px; font: 500 10px var(--font-ui); letter-spacing: 0.1em; color: rgba(239, 231, 216, 0.5); }
.sb-rank { display: block; margin-top: 3px; font: 400 10px var(--font-ui); letter-spacing: 0.06em; color: rgba(217, 177, 96, 0.7); }
/* the spellbook's footer has only BACK, so it sits right, not left */
#spellbookModal .lob-foot { justify-content: flex-end; }
/* the invited page's one button: the same gold as GET IT ON ITCH.IO, inside the plaque */
.land-claim { margin-top: 12px; width: 100%; }
.land-claim:disabled { opacity: 0.7; cursor: default; }
