:root {
  --bg: #0b0806;
  --panel: rgba(26, 18, 11, 0.92);
  --accent: #ff7a2f;
  --text: #f6edda;
}
* { box-sizing: border-box; }
html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
  font-family: "Segoe UI", system-ui, sans-serif;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
}
canvas { display: block; position: fixed; inset: 0; cursor: crosshair; }

.hidden { display: none !important; }

/* ---- Menu overlay ---- */
.overlay {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 50% 30%, #2a0f0f, #0b0806 70%);
  z-index: 10;
}
.panel {
  width: min(440px, 92vw);
  max-height: 94vh;            /* never taller than the viewport… */
  max-height: 94svh;          /* …(small-viewport unit accounts for mobile browser chrome) */
  overflow-y: auto;           /* scroll inside instead of overflowing off-screen */
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;        /* allow finger-scroll despite the global touch-action:none */
  background: var(--panel);
  border: 1px solid #4a3320;
  border-radius: 16px;
  padding: 26px 28px 22px;
  box-shadow: 0 20px 60px rgba(0,0,0,.6), 0 0 0 1px rgba(255,122,47,.15);
}

/* ---- Main-menu hero art: layered CraftPix hell/lava scene w/ mouse parallax ---- */
#menu, #welcome { overflow: hidden; }            /* clip the oversized parallax layers */
.menuScene {
  position: absolute; inset: 0; z-index: 0;
  overflow: hidden; pointer-events: none;
  background: #e7ac6a;                            /* sky tone: fallback before images load */
}
.msLayer {
  position: absolute; inset: -7%;                 /* oversize so parallax never bares an edge */
  background: center bottom / cover no-repeat;
  image-rendering: pixelated;                     /* crisp pixel-art upscaling */
  /* --mx/--my come from initMenuScene (−1..1); --d is this layer's parallax depth (px) */
  transform: translate3d(calc(var(--mx,0) * var(--d) * 1px), calc(var(--my,0) * var(--d) * .5px), 0);
  transition: transform .2s ease-out;
  will-change: transform;
}
.msLayer.l7 { background-image: url("assets/menu/bg7.png"); --d: 3; }
.msLayer.l6 { background-image: url("assets/menu/bg6.png"); --d: 6; }
.msLayer.l5 { background-image: url("assets/menu/bg5.png"); --d: 9; }
.msLayer.l4 { background-image: url("assets/menu/bg4.png"); --d: 13; }
.msLayer.l3 { background-image: url("assets/menu/bg3.png"); --d: 18; }
.msLayer.l2 { background-image: url("assets/menu/bg2.png"); --d: 24; }
.msLayer.l1 { background-image: url("assets/menu/bg1.png"); --d: 34; }
/* pulsing lava light rising off the ridgeline */
.msGlow {
  position: absolute; left: 50%; bottom: -10%; transform: translateX(-50%);
  width: 130%; height: 62%; pointer-events: none; mix-blend-mode: screen;
  background: radial-gradient(ellipse at 50% 100%, rgba(255,120,40,.55), rgba(255,70,20,0) 62%);
  animation: msFlicker 5s ease-in-out infinite;
}
@keyframes msFlicker { 0%,100% { opacity: .5; } 50% { opacity: .92; } }
/* legibility veil so the panel + title read cleanly over the art */
.msVeil {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(125% 92% at 50% 6%, rgba(10,7,16,0) 42%, rgba(10,7,16,.5) 100%),
    linear-gradient(180deg, rgba(10,7,16,.22) 0%, rgba(10,7,16,.03) 34%, rgba(10,7,16,.72) 100%);
}
/* the menu panel + title sit above the scene */
#menu > .panel, #welcome > .panel { position: relative; z-index: 1; }
#menu > .panel h1, #welcome > .panel h1 {
  color: #fff;
  text-shadow: 0 2px 8px rgba(0,0,0,.6), 0 0 24px rgba(255,120,40,.45);
}
@media (prefers-reduced-motion: reduce) {
  .msLayer { transition: none; }
  .msGlow { animation: none; opacity: .68; }
}

/* in-game pause menu — sits above the HUD/shop, with a see-through backdrop */
#escMenu { z-index: 30; background: rgba(10,7,16,.72); }
#escMenu .escDanger { color: #ff8a8a; border-color: #7a2a2a; }
#escMenu .escDanger:hover { background-color: #3a1414; }
h1 { margin: 0 0 4px; font-size: 34px; text-align: center; letter-spacing: .5px; }
.tag { margin: 0 0 18px; text-align: center; color: #c7b596; font-size: 14px; }
label { display: block; font-size: 13px; color: #d4c4a4; margin: 12px 0 4px; }
.hint { color: #8d7a58; font-weight: normal; }
input {
  width: 100%; padding: 11px 12px; margin-top: 4px;
  background: #191007; border: 1px solid #4a3320; border-radius: 9px;
  color: var(--text); font-size: 15px; outline: none;
}
input:focus { border-color: var(--accent); }
button {
  width: 100%; margin-top: 20px; padding: 13px;
  background: linear-gradient(180deg, #ff8a3d, #f0641e);
  border: none; border-radius: 10px; color: #1a0d00;
  font-size: 17px; font-weight: 700; cursor: pointer;
  transition: transform .06s ease, filter .15s;
}
button:hover { filter: brightness(1.08); }
button:active { transform: translateY(1px); }

.controls { margin-top: 22px; padding-top: 16px; border-top: 1px solid #3a2817; font-size: 13px; color: #d4c4a4; }
.controls .grid { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin-top: 10px; align-items: center; }
.controls small { display:block; margin-top:10px; color:#8d7a58; }
kbd {
  display: inline-block; padding: 2px 7px; margin: 0 1px;
  background: #281b0e; border: 1px solid #5c4526; border-bottom-width: 2px;
  border-radius: 5px; font-size: 12px; font-family: inherit;
}
.status { min-height: 18px; margin: 14px 0 0; text-align: center; color: #ffcf3f; font-size: 13px; }

/* ---- online + server browser ---- */
.online { text-align: center; font-size: 13px; color: #9fd8a0; margin: 14px 0 4px; }
.online b { color: #d7ffd8; }
.browserTop { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.browserTop .online { margin: 0; }
.browserTop button.ghost { width: auto; margin: 0; padding: 6px 12px; }
#search { margin-bottom: 12px; }
#serverList { max-height: 46vh; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
.srv {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  padding: 11px 13px; margin-bottom: 7px;
  background: #191007; border: 1px solid #3a2817; border-radius: 9px;
  transition: border-color .1s, background .1s;
}
.srv:hover { border-color: var(--accent); background: #221808; }
.srv.full { opacity: .5; cursor: not-allowed; }
.srv .sflag { flex: none; display: inline-flex; width: 21px; height: 14px; margin-right: -2px; border-radius: 2px; overflow: hidden; box-shadow: 0 0 0 1px rgba(0,0,0,.45), inset 0 0 0 1px rgba(255,255,255,.12); }
.srv .sflag svg { display: block; width: 100%; height: 100%; }
.srv .sflag.code { align-items: center; justify-content: center; background: #2a2216; color: #c7b596; font-size: 9px; font-weight: 700; letter-spacing: .5px; }
.srv .sname { flex: 1; font-size: 15px; font-weight: 600; }
.srv .scount { font-size: 13px; color: #c7b596; white-space: nowrap; }
.srv .scount .live { color: #5ee06a; }
.srv .go { color: var(--accent); font-weight: 700; }
.createRow { display: flex; gap: 8px; margin-top: 10px; }
.createRow input { margin: 0; }
.createRow button { width: auto; margin: 0; padding: 0 16px; font-size: 14px; white-space: nowrap; }

/* ---- Persistent wallet HUD (banked 🪙 gold + 💵 cash, top-left, always on
   top). Menu values from /auth/wallet; live in-match values from the snapshot. ---- */
#walletHud {
  position: fixed; top: 10px; left: 12px; z-index: 41;
  display: flex; align-items: center; gap: 7px;
  pointer-events: none; user-select: none;
}
#walletHud .whItem {
  display: inline-flex; align-items: center; gap: 5px;
  background: rgba(10,7,16,.72); border: 1px solid #4a3320; border-radius: 20px;
  padding: 5px 12px; font-size: 14px; font-weight: 700; color: #f0e2c4;
  text-shadow: 0 1px 2px #000; box-shadow: 0 2px 8px rgba(0,0,0,.4);
  backdrop-filter: blur(3px);
}
#walletHud .whItem.gold b { color: #ffd94a; }
#walletHud .whItem.cash b { color: #8fe89a; }
@media (max-width: 560px) { #walletHud .whItem { font-size: 12px; padding: 4px 9px; } }

/* ---- Audio controls (always on top) ---- */
#audioCtl {
  position: fixed; top: 10px; right: 12px; z-index: 40;
  display: flex; align-items: center; gap: 8px;
  background: rgba(10,7,16,.72); border: 1px solid #4a3320; border-radius: 20px;
  padding: 5px 12px 5px 9px; backdrop-filter: blur(3px);
  touch-action: auto; /* let the slider/button receive touch despite global touch-action:none */
}
#audioCtl button {
  width: auto; margin: 0; padding: 0; background: none; border: none;
  font-size: 20px; line-height: 1; cursor: pointer; filter: none;
}
#audioCtl button:hover { filter: brightness(1.2); }
#audioCtl input[type=range] {
  width: 74px; height: 18px; margin: 0; padding: 0;
  background: transparent; border: none; accent-color: var(--accent); cursor: pointer;
}
#audioCtl .audioSep { width: 1px; height: 20px; background: #4a3320; }

/* ---- HUD ---- */
#hud { position: fixed; inset: 0; pointer-events: none; z-index: 5; }
/* Training-only controls — bottom-left corner, clear of the spellbar. A flex row
   so the pills sit side by side (never stretched to full width by base button{}). */
#trainCtl {
  position: absolute; left: 14px; bottom: 16px; z-index: 8; pointer-events: auto;
  display: flex; gap: 8px; align-items: flex-end;
}
#trainCtl button {
  width: auto; margin: 0; /* override base button{width:100%} so pills don't span the HUD */
  padding: 9px 14px; font-size: 14px; font-weight: 700; cursor: pointer;
  color: #ffe9c2; border-radius: 10px; position: relative; overflow: hidden;
}
/* 🎒 Loadout — shiny ember pill with a pulsing glow + a shine sweep to draw the eye. */
#trainShopBtn {
  background: linear-gradient(180deg, #4a2c66 0%, #2a1740 55%, #1c1030 100%);
  border: 1px solid #b28cff;
  box-shadow: 0 3px 12px rgba(0,0,0,.5), 0 0 14px rgba(150,100,255,.4);
  animation: trainShopPulse 2.2s ease-in-out infinite;
}
#trainShopBtn::before { /* diagonal light streak that periodically sweeps across */
  content: ""; position: absolute; top: 0; left: -75%; width: 45%; height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255,240,210,.55), transparent);
  transform: skewX(-20deg); pointer-events: none;
  animation: trainShopShine 3.6s ease-in-out infinite;
}
#trainShopBtn:hover { filter: brightness(1.12); border-color: #d8c4ff; }
@keyframes trainShopPulse {
  0%, 100% { box-shadow: 0 3px 12px rgba(0,0,0,.5), 0 0 12px rgba(150,100,255,.35); }
  50%      { box-shadow: 0 3px 16px rgba(0,0,0,.55), 0 0 26px rgba(180,140,255,.85); }
}
@keyframes trainShopShine { 0% { left: -75%; } 55%, 100% { left: 130%; } }
@media (prefers-reduced-motion: reduce) {
  #trainShopBtn { animation: none; }
  #trainShopBtn::before { animation: none; display: none; }
}
/* ⬆️ Level Up — warm gold pill so it reads as a distinct "power up" action. */
#trainLevelBtn {
  background: linear-gradient(180deg, #6a4a12 0%, #3a2708 100%);
  border: 1px solid #ffcf5a;
  box-shadow: 0 3px 12px rgba(0,0,0,.5), 0 0 12px rgba(255,190,70,.35);
}
#trainLevelBtn:hover { filter: brightness(1.12); border-color: #ffe08a; }
#trainLevelBtn:disabled { filter: grayscale(.5) brightness(.8); cursor: default; opacity: .7; }
#topbar {
  position: absolute; top: 12px; left: 0; right: 0;
  display: flex; justify-content: space-between; align-items: flex-start;
  padding: 0 16px;
}
#phaseInfo {
  background: rgba(10,7,16,.7); border: 1px solid #4a3320; border-radius: 10px;
  padding: 8px 14px; font-size: 15px; font-weight: 600;
  /* Drop below the fixed top-left wallet pill (#walletHud, z-index 41) so the
     gold/cash chips never render on top of the match info. The scoreboard (the
     topbar's right-hand item) stays at the top edge. */
  margin-top: 34px;
}
#scoreboard {
  background: rgba(10,7,16,.7); border: 1px solid #4a3320; border-radius: 10px;
  padding: 8px 14px; font-size: 13px; min-width: 150px;
  margin-top: 40px; /* drop below the audio control in the top-right corner */
}
#scoreboard .row { display: flex; justify-content: space-between; gap: 12px; padding: 2px 0; }
#scoreboard .row.dead { opacity: .45; text-decoration: line-through; }
#scoreboard .dot { display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:6px; vertical-align:middle; }
#scoreboard .sc { white-space: nowrap; font-size: 12px; }
#scoreboard .pips { color: #ffcf3f; letter-spacing: 1px; margin-right: 3px; }
#scoreboard .champPts { color: #ffd94a; font-weight: 700; text-shadow: 0 0 6px rgba(255,193,60,.45); }

/* Full standings overlay — hold TAB during a match (see updateTabScore in main.js).
   pointer-events:none so holding TAB never blocks mouse aim underneath. */
#tabScore {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  z-index: 40; width: min(560px, 94vw); max-height: 82vh; overflow-y: auto;
  background: rgba(10,7,16,.92); border: 1px solid #4a3320; border-radius: 14px;
  padding: 12px 14px; box-shadow: 0 12px 44px rgba(0,0,0,.6);
  pointer-events: none; font-size: 13px;
}
#tabScore .tsTitle {
  text-align: center; font-weight: 800; font-size: 16px; letter-spacing: .5px;
  color: #ffcf3f; margin-bottom: 8px;
}
#tabScore .tsRow {
  display: grid; grid-template-columns: 26px 1fr 40px 40px 54px 58px 66px;
  align-items: center; gap: 4px; padding: 3px 5px; border-radius: 6px;
}
/* Championship adds a leading ✨ Points column (its running total decides the champ). */
#tabScore.champ .tsRow { grid-template-columns: 26px 1fr 52px 40px 40px 54px 58px 66px; }
#tabScore .tsNum.pts { color: #ffd94a; font-weight: 700; }
#tabScore .tsRow.tsHead { color: #b79a7a; font-size: 12px; border-bottom: 1px solid #3a2a1a; margin-bottom: 3px; align-items: end; }
/* header stat columns: icon stacked over a short word (kills/deaths/gold/damage/ping) */
#tabScore .tsRow.tsHead .tsNum { display: flex; flex-direction: column; align-items: center; gap: 1px; line-height: 1.05; }
#tabScore .tsRow.tsHead .tsIco { font-size: 13px; }
#tabScore .tsCol { color: #8a7a68; font-size: 9px; text-transform: uppercase; letter-spacing: .3px; }
#tabScore .tsRow:not(.tsHead):nth-child(even) { background: rgba(255,255,255,.03); }
#tabScore .tsRow.me { background: rgba(255,207,63,.14); outline: 1px solid rgba(255,207,63,.4); }
#tabScore .tsRow.dead { opacity: .5; }
#tabScore .tsRow.dead .tsName { text-decoration: line-through; }
#tabScore .tsRow.elim { opacity: .35; }
#tabScore .tsRank { text-align: center; color: #8a7a68; font-variant-numeric: tabular-nums; }
#tabScore .tsName { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#tabScore .tsName .dot { display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:6px; vertical-align:middle; }
#tabScore .tsNum { text-align: center; font-variant-numeric: tabular-nums; white-space: nowrap; }
#tabScore .tsNum.ping { color: #7fe0ff; }
#tabScore .tsNum small { color: #8a7a68; font-size: 10px; }
#tabScore .tsMore { text-align: center; color: #8a7a68; margin-top: 6px; font-size: 12px; }
/* the "hold TAB" nudge under the countdown banner */
#banner .sub.tabHint { font-size: 14px; color: #9fe8ff; opacity: .85; margin-top: 10px; }

/* Big segmented HP + mana bars for you (or the mage you're spectating) */
#selfBars {
  position: absolute; top: 56px; left: 50%; transform: translateX(-50%);
  width: min(560px, 80vw); display: flex; flex-direction: column; gap: 5px;
}
#selfBars .sbName {
  text-align: center; font-size: 14px; font-weight: 700; color: #fff;
  text-shadow: 0 1px 3px #000; letter-spacing: .3px;
}
#selfBars .sbNums { color: #ffcf3f; font-weight: 600; margin-left: 8px; font-size: 13px; }
#selfBars .sbBar {
  position: relative; height: 22px; border-radius: 7px; overflow: hidden;
  background: rgba(10,7,16,.72); border: 1px solid rgba(255,255,255,.2);
  box-shadow: 0 2px 8px rgba(0,0,0,.45);
}
#selfBars .sbBar.mana { height: 15px; }
#selfBars .sbFill { height: 100%; width: 0; }
#selfBars .sbBar.mana .sbFill { background: #4aa3ff; }
/* tiny XP strip under the mana bar — fills toward the next player level */
#selfBars .sbBar.xp { height: 5px; border-radius: 3px; }
#selfBars .sbBar.xp .sbFill { background: linear-gradient(90deg, #b98a2c, #ffd94a); }
#selfBars .sbLvl { color: #ffd94a; font-size: 12.5px; margin-right: 2px; }
#selfBars .sbTicks { position: absolute; inset: 0; pointer-events: none; }

/* passive + status chips directly under the mana bar: a centered box whose
   chips pack from the left to the right (and wrap downward when they overflow) */
#statusBar {
  display: flex; gap: 5px; justify-content: flex-start; flex-wrap: wrap;
  align-self: center; max-width: 100%; margin-top: 4px; pointer-events: auto;
}
#statusBar .chip {
  width: 27px; height: 27px; display: flex; align-items: center; justify-content: center;
  font-size: 15px; border-radius: 7px; cursor: help;
  background: rgba(10,7,16,.72); border: 1px solid rgba(255,255,255,.2);
}
#statusBar .chip.status { border-color: rgba(255,140,90,.55); }
#statusBar .chip.buff { border-color: rgba(120,220,255,.55); background: rgba(20,30,44,.72); }
#statusBar .chip.aegis { border-color: rgba(150,205,255,.9); box-shadow: 0 0 8px rgba(140,200,255,.45); animation: lavaPulse .9s ease-in-out infinite; }
#statusBar .chip.lava { border-color: #ff5a2f; background: rgba(60,14,6,.85); box-shadow: 0 0 10px rgba(255,90,47,.6); animation: lavaPulse .7s ease-in-out infinite; }
@keyframes lavaPulse { 0%,100% { box-shadow: 0 0 6px rgba(255,90,47,.5); } 50% { box-shadow: 0 0 14px rgba(255,90,47,.9); } }
#selfBars .sbShield { color: #7fd8ff; font-weight: 700; margin: 0 4px; }
#fxTip {
  position: fixed; transform: translateX(-50%); z-index: 30; max-width: 230px;
  background: rgba(10,7,16,.96); border: 1px solid #4a3320; color: #fff;
  font-size: 12px; line-height: 1.35; padding: 6px 9px; border-radius: 8px;
  pointer-events: none; text-align: center; box-shadow: 0 4px 14px rgba(0,0,0,.55);
}

/* main-menu language picker */
#langPick { display: flex; align-items: center; gap: 8px; justify-content: center; margin: 4px 0; flex-wrap: wrap; }
#langBtns, #charEdLangBtns { display: flex; gap: 6px; flex-wrap: wrap; }
.langBtn {
  width: auto; margin: 0; background: rgba(10,7,16,.5); border: 1px solid #4a3320; color: #dac7a2;
  border-radius: 8px; padding: 6px 11px; font-size: 12px; cursor: pointer;
}
.langBtn.active { border-color: #ffcf3f; color: #fff; box-shadow: 0 0 8px rgba(255,207,63,.3); }

/* Spell bar centered along the bottom-middle (desktop), hotkeys shown */
#spellbar {
  position: absolute; bottom: 22px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 8px;
  padding: 7px; border-radius: 13px;
  background: rgba(10,7,16,.4); backdrop-filter: blur(3px);
}
.slot {
  position: relative; width: 58px; height: 58px;
  background: rgba(10,7,16,.66); border: 2px solid #4a3320; border-radius: 10px;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.slot .key {
  position: absolute; top: 2px; left: 3px; z-index: 3;
  font-size: 12px; font-weight: 800; color: #ffdb5c;
  text-shadow: 0 1px 2px #000, 0 0 3px #000; letter-spacing: .3px;
  padding: 0 3px; border-radius: 4px; background: rgba(6,4,2,.5);
}
.slot .key.long { /* spelled-out labels ("space bar") shrink to fit the chip */
  font-size: 9px; letter-spacing: 0; white-space: nowrap;
}
/* Controller-button chips (swapped in while a gamepad is the live input device).
   Xbox face buttons keep their signature colours; triggers/bumpers stay gold. */
.slot .key.pad { min-width: 14px; text-align: center; letter-spacing: 0; }
.slot .key.pad-a { color: #6cc04a; } /* A — green  */
.slot .key.pad-b { color: #e5453b; } /* B — red    */
.slot .key.pad-x { color: #3b7cf0; } /* X — blue   */
.slot .key.pad-y { color: #f2c521; } /* Y — yellow */
.slot .el2 { /* element-combo badge: the secondary element's emoji in the corner */
  position: absolute; top: 1px; right: 3px; font-size: 12px; line-height: 1;
  filter: drop-shadow(0 0 3px var(--el2, #fff));
}
.slot .icon { font-size: 30px; line-height: 1; }
/* Pixel-art spell icons (CraftPix magic packs 671189 & 781160). Rendered crisp
   (no smoothing) and sized to sit inside the 58px slot clear of the corner
   badges; the nomana/silenced filters above still grey them like the emoji. */
.slot .icon img.pixIco {
  width: 36px; height: 36px; display: block;
  image-rendering: pixelated;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.6));
}
.slot .cover {
  position: absolute; inset: 0; background: rgba(0,0,0,.6);
  display: flex; align-items: center; justify-content: center;
  font-size: 19px; font-weight: 700; color: #fff;
}
.slot.active { border-color: var(--accent); box-shadow: 0 0 12px rgba(255,122,47,.4); }
/* FUSED slot (5+5 archetype): the whole chip breathes with the fusion's glow */
.slot.fused { animation: fusSlot 2.2s ease-in-out infinite; }
@keyframes fusSlot {
  0%, 100% { box-shadow: 0 0 5px var(--el, #ffd35a); }
  50%      { box-shadow: 0 0 15px var(--el, #ffd35a); }
}
.slot .el2.fus { font-size: 13px; }
/* Meditate slot pulsing green while the channel is active */
.slot.meditating { border-color: #8fe6b0; animation: medPulse 1.1s ease-in-out infinite alternate; }
@keyframes medPulse { from { box-shadow: 0 0 6px rgba(143,230,176,.35); } to { box-shadow: 0 0 16px rgba(143,230,176,.75); } }
.slot .elbadge {
  position: absolute; bottom: 1px; right: 2px;
  font-size: 15px; line-height: 1; text-shadow: 0 1px 2px #000;
}
/* mana cost printed on the slot; slot dims when you can't afford it */
.slot .mana {
  position: absolute; bottom: 2px; left: 3px; z-index: 3;
  font-size: 11px; font-weight: 800; color: #8fd8ff;
  text-shadow: 0 1px 2px #000, 0 0 3px #000; line-height: 1;
  padding: 0 3px; border-radius: 4px; background: rgba(6,4,2,.5);
}
.slot.nomana .icon, .slot.nomana .elbadge { filter: grayscale(1) brightness(.55); opacity: .5; }
.slot.nomana .mana { color: #ff6a6a; }
/* Charge pips: arcane Q (Spiral Orb) / W (Seeker Orb) bank 2-3 casts per cooldown.
   A dot per charge, lit ones = banked; sits above the recharge cover so you can
   read "2 of 3 ready" at a glance. */
.slot .charges {
  position: absolute; bottom: 3px; right: 3px; z-index: 4;
  display: flex; gap: 2px; pointer-events: none;
}
.slot .charges.hidden { display: none; }
.slot .charges i {
  width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255,210,74,.22); box-shadow: 0 0 2px rgba(0,0,0,.85);
}
.slot .charges i.on { background: #ffd24a; box-shadow: 0 0 5px rgba(255,200,60,.95); }
/* electric-quake SILENCE: every owned spell greys out until it wears off */
.slot.silenced { position: relative; }
.slot.silenced .icon, .slot.silenced .elbadge, .slot.silenced .mana, .slot.silenced .key {
  filter: grayscale(1) brightness(.5); opacity: .45;
}
.slot.silenced::before {
  content: "🔇"; position: absolute; inset: 0; z-index: 3;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; opacity: .8; pointer-events: none;
  text-shadow: 0 1px 3px #000;
}
#spellbar.silenced { animation: silencePulse 0.6s ease-in-out infinite alternate; }
@keyframes silencePulse { from { filter: none; } to { filter: brightness(1.15) drop-shadow(0 0 6px rgba(255,225,74,.55)); } }

/* ---- Lobby ---- */
h1.small { font-size: 24px; }
/* Compact vertical rhythm so the whole lobby fits without a scrollbar. */
/* ================= Lobby — classic game-room layout =================
   A room-identity bar on top, a WC3-style roster on the left, framed map +
   game-settings + invite cards on the right, and a sticky ready/start bar
   at the bottom. The bronze frame comes from `.overlay > .panel`. */
#lobby .panel { text-align: left; padding: 0; width: min(1040px, 96vw); overflow: hidden; }
.lobbyPanel { display: flex; flex-direction: column; max-height: 92vh; max-height: 92svh; min-height: 0; }
/* Neutralize the base `button { width:100%; margin-top:20px }` for lobby controls
   (the old #lobby button reset is gone). cpArrow keeps its own fixed 36px width. */
#lobby .cpArrow { margin: 0; }
#lobby .tsBtn, #lobby .tpBtn, #lobby #startBtn { width: auto; margin: 0; }

/* --- room identity bar --- */
.lobbyHeader {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 20px 11px; flex: none;
  border-bottom: 1px solid #3a2817;
  background: linear-gradient(180deg, rgba(72,42,16,.55), rgba(25,16,7,0));
}
.lobbyIdent { display: flex; align-items: center; gap: 12px; min-width: 0; }
.lobbyGlyph { font-size: 30px; line-height: 1; flex: none; filter: drop-shadow(0 0 9px rgba(255,140,50,.6)); }
.lobbyTitleWrap { min-width: 0; }
.lobbyTitleWrap h1.small { margin: 0; line-height: 1.05; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lobbySub { margin-top: 4px; }
.modeBadge {
  display: inline-block; font-size: 12px; font-weight: 700; color: #ffcf7a; letter-spacing: .3px;
  background: rgba(255,180,60,.12); border: 1px solid #6a4b23; border-radius: 999px; padding: 2px 11px;
}
.lobbyCount {
  flex: none; text-align: center; line-height: 1.05;
  background: #191007; border: 1px solid #3a2817; border-radius: 11px; padding: 6px 13px;
}
.lobbyCount #lobbyCountNum { display: block; font-size: 20px; font-weight: 800; color: #ffe7c2; }
.lobbyCount .lobbyCountLbl { font-size: 9.5px; text-transform: uppercase; letter-spacing: 1.2px; color: #b7a888; }

/* --- body: roster (left) · side cards (right) --- */
.lobbyBody {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr);
  gap: 14px; padding: 14px 20px; overflow-y: auto; align-items: start; min-height: 0;
}
.lobbyRoster, .lobbyCard {
  background: #150d06; border: 1px solid #3a2817; border-radius: 12px; padding: 11px 13px; margin: 0;
}
.lobbySide { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.cardHead {
  font-size: 11.5px; font-weight: 800; letter-spacing: .6px; text-transform: uppercase;
  color: #ffcf7a; margin-bottom: 9px; padding-bottom: 6px; border-bottom: 1px solid #2c1e10;
}

/* --- roster list (auto-scrolls when the roster is big) --- */
#lobbyList { display: flex; flex-direction: column; gap: 5px; max-height: 44vh; overflow-y: auto; padding-right: 3px; }
.lobbyRow {
  display: flex; align-items: center; gap: 8px; padding: 6px 9px; min-width: 0;
  background: #1c1208; border: 1px solid #33220f; border-radius: 9px; font-size: 14px;
}
.lobbyRow.me { border-color: #ffcf3f; box-shadow: inset 0 0 0 1px rgba(255,207,63,.22); }
.lobbyRow.host { background: linear-gradient(90deg, rgba(255,180,60,.12), #1c1208 42%); }
.lobbyRow .slotNo { font-size: 11px; font-weight: 800; color: #7a6444; width: 15px; text-align: center; flex: none; }
.lobbyRow .dot { width: 12px; height: 12px; border-radius: 50%; flex: none; box-shadow: 0 0 0 1px rgba(0,0,0,.45); }
.lobbyRow .who { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lobbyRow .crown { font-size: 13px; flex: none; }
/* GunBound-style ready lamp: a glowing green light when readied */
.lobbyRow .lamp { width: 13px; height: 13px; border-radius: 50%; flex: none; border: 1px solid rgba(0,0,0,.45); }
.lobbyRow .lamp.yes { background: radial-gradient(circle at 34% 30%, #c6ffcc, #35c24c); box-shadow: 0 0 9px rgba(80,230,110,.75); }
.lobbyRow .lamp.no  { background: #45351f; box-shadow: inset 0 0 3px rgba(0,0,0,.6); }
.lobbyRow .lamp.spec { background: radial-gradient(circle at 34% 30%, #c9f1ff, #3aa9e0); box-shadow: 0 0 8px rgba(90,190,255,.65); }

/* mage skin picker — same layout & square swatch as the old cursor picker */
#skinPick { display: flex; align-items: center; justify-content: center; gap: 12px; margin: 8px 0 4px; }
#skinPick .cpLabel { font-size: 13px; color: #d4c4a4; }
#skinPick .cpArrow {
  width: auto; margin: 0; padding: 4px 12px; font-size: 16px; border-radius: 8px;
  background: #281b0e; border: 1px solid #5c4526; color: var(--text);
}
#skinPick .cpArrow:hover { background: #3a2a14; }
#skinPreview { width: 34px; height: 34px; border-radius: 8px; border: 1px solid rgba(255,255,255,.45); box-shadow: 0 0 10px rgba(0,0,0,.4) inset; }
/* full-palette swatch grid under the arrow row — capped, self-contained scroll
   so a big palette doesn't stretch the Options panel into a scrollbar. */
.swGrid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(26px, 1fr)); gap: 5px;
  margin: 6px 0 2px; max-height: 88px; overflow-y: auto; padding-right: 2px;
}
.swGrid .skinSw {
  width: 24px; height: 24px; padding: 0; border-radius: 6px; cursor: pointer;
  border: 2px solid transparent; box-shadow: 0 0 6px rgba(0,0,0,.4) inset; transition: transform .08s;
}
.swGrid .skinSw:hover { transform: scale(1.14); }
.swGrid .skinSw.sel { border-color: #fff; box-shadow: 0 0 8px rgba(255,255,255,.6); }
/* 💵 premium (locked) swatch: dimmed with a small padlock; still clickable to
   preview + open the paywall. Selected-while-previewing keeps the white ring. */
.swGrid .skinSw.locked { position: relative; opacity: .82; }
.swGrid .skinSw.locked::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: repeating-linear-gradient(45deg, transparent 0 3px, rgba(0,0,0,.28) 3px 6px);
  pointer-events: none;
}
.swGrid .skinSw.locked .swLock {
  position: absolute; right: -3px; top: -5px; font-size: 10px; line-height: 1;
  filter: drop-shadow(0 1px 1px #000); pointer-events: none;
}
.swGrid .skinSw.locked.sel { border-color: #ffd94a; box-shadow: 0 0 8px rgba(255,217,74,.6); }

/* Options: two columns (left = language/skin/cursor, right = hotkeys/controls)
   so everything — even with the hotkey remapper open — fits without scrolling. */
.optionsPanel { width: min(680px, 94vw); }
#optionsBody { display: flex; gap: 22px; align-items: flex-start; }
#optionsBody .optCol { flex: 1 1 0; min-width: 0; }
#optionsBody .optCol > *:first-child { margin-top: 0; }
#optionsBody .controls { margin-top: 0; }

/* ---- hotkey remapping + controller hint (main menu) ---- */
/* Display options: window mode + resolution (Options panel, 2nd column) */
#displayPick { margin: 4px 0 10px; }
#displayPick .cpLabel { display: block; font-size: 13px; color: #d4c4a4; margin-bottom: 7px; }
.winModeBtns { display: flex; gap: 6px; flex-wrap: wrap; }
.winModeBtn {
  width: auto; margin: 0; background: rgba(10,7,16,.5); border: 1px solid #4a3320; color: #dac7a2;
  border-radius: 8px; padding: 6px 11px; font-size: 12px; cursor: pointer;
}
.winModeBtn:hover { background: rgba(58,42,20,.6); }
.winModeBtn.active { border-color: #ffcf3f; color: #fff; box-shadow: 0 0 8px rgba(255,207,63,.3); }
.resPick { display: flex; align-items: center; gap: 8px; margin-top: 9px; font-size: 12px; color: #d4c4a4; }
.resPick select {
  width: auto; margin: 0; background: #281b0e; border: 1px solid #5c4526; color: var(--text);
  border-radius: 8px; padding: 5px 9px; font-size: 12px; cursor: pointer;
}
.resPick select:disabled { opacity: .45; cursor: default; }

/* Sound options (Options panel, 2nd column): experimental-VFX-sounds checkbox */
#soundPick { margin: 4px 0 10px; }
#soundPick .cpLabel { display: block; font-size: 13px; color: #d4c4a4; margin-bottom: 7px; }
.optCheck { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #dac7a2; cursor: pointer; }
.optCheck input { width: auto; margin: 0; accent-color: #ffcf3f; cursor: pointer; }

/* ---- Character editor: live sprite preview + appearance pickers.
   Reuses the Options widgets (.cpLabel/.cpArrow/.swGrid/.winModeBtns); the
   preview is the real magePortrait, upscaled pixelated. */
.charEdPanel { width: min(760px, 94vw); }
#charEdBody { display: flex; gap: 22px; align-items: flex-start; }
#charEdBody .optCol { flex: 1 1 0; min-width: 0; }
.charEdPreviewCol { flex: 0 0 auto !important; display: flex; flex-direction: column; align-items: center; }
#charEdPortraitBox { display: flex; flex-direction: column; align-items: center; gap: 6px; }
#charEdPortraitBox small { font-size: 11px; color: #a89a78; max-width: 260px; text-align: center; }
#charEdPortrait {
  display: flex; align-items: center; justify-content: center;
  width: 264px; height: 264px; border-radius: 10px;
  background: radial-gradient(ellipse at 50% 72%, #2c1c0c 0%, #191007 70%);
  border: 1px solid #5c4526;
}
#charEdSpriteCv {
  /* undo the global `canvas { position: fixed; inset: 0 }` (game canvas) rule */
  position: static; inset: auto; cursor: default;
  width: 240px; height: 240px; image-rendering: pixelated;
}
#charEdRotate { display: flex; gap: 10px; }
#charEdRotate .cpArrow {
  width: auto; margin: 0; padding: 4px 16px; font-size: 16px; border-radius: 8px;
  background: #281b0e; border: 1px solid #5c4526; color: var(--text);
}
#charEdRotate .cpArrow:hover { background: #3a2a14; }
.charEdField { margin: 6px 0; }
.charEdField .cpLabel { display: block; font-size: 13px; color: #d4c4a4; margin-bottom: 4px; }
/* Kill .swGrid's capped-scroll behavior (meant for Options' grid) so no
   scrollbar can ever appear, and shrink the swatches a notch — four palettes
   (incl. the 28-color robe grid) must fit a 720p panel without scrolling. */
#charEditor .swGrid { max-height: none; overflow: visible; padding-right: 0; grid-template-columns: repeat(auto-fill, 22px); gap: 4px; }
#charEditor .swGrid .skinSw { width: 20px; height: 20px; }
/* Hair-style swatches reuse the .skinSw square but carry a centered style
   number (styles have no single color, so the square is tinted with the hair
   color and the number identifies it). */
.swGrid .skinSw.styleSw { display: flex; align-items: center; justify-content: center; }
.styleSw .styleNum {
  font-size: 11px; font-weight: 700; color: #fff; line-height: 1;
  text-shadow: 0 1px 2px rgba(0,0,0,.85); pointer-events: none;
}
.charEdActions { display: flex; gap: 8px; margin-top: 12px; }
.charEdActions button { width: auto; margin: 0; font-size: 13px; padding: 8px 12px; }
/* First-join setup strip (a fresh account's first sign-in): one-time name pick
   + Save & Play. Compact overrides so the panel still fits 720p unscrolled. */
#charEdSetup { margin-top: 10px; border-top: 1px solid #5c4526; padding-top: 8px; }
#charEdSetup .welcomeName { margin: 0 0 6px; }
#charEdSetup .welcomeName input { font-size: 15px; padding: 8px; }
#charEdSetup .welcomeName span { font-size: 12px; color: #d4c4a4; }
#charEdSaveBtn { width: 100%; font-size: 15px; padding: 10px; margin-top: 2px; }
#charEdSetup .status { min-height: 16px; margin: 6px 0 0; }

/* Quit Game (main menu): a quieter ghost button set apart from the play buttons */
#menu .menuBtns .quitBtn { color: #ff9a9a; border-color: #6a2626; }
#menu .menuBtns .quitBtn:hover { background: #3a1414; }

#hotkeyPick { margin: 8px 0 4px; }
#hotkeyPick #hotkeyToggle { margin: 0; font-size: 13px; padding: 8px 10px; }
#hotkeyPanel { margin-top: 8px; }
#hotkeyList {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px;
  background: #191007; border: 1px solid #3a2817; border-radius: 10px; padding: 10px;
}
.hkRow { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.hkName { font-size: 12px; color: #d4c4a4; }
.hkKey {
  width: auto; margin: 0; padding: 4px 10px; min-width: 46px; font-size: 13px; font-weight: 700;
  border-radius: 7px; background: #281b0e; border: 1px solid #5c4526; color: var(--text);
}
.hkKey:hover { background: #3a2a14; filter: none; }
.hkKey.capturing { border-color: var(--accent); color: #ffcf3f; background: #2a1a10; animation: countPulse .7s ease-in-out infinite; }
#hotkeyReset { margin-top: 8px; font-size: 12px; padding: 6px 10px; }
.hkNote { margin-top: 8px; font-size: 11.5px; color: #9d8b6c; line-height: 1.4; }

/* ---- multikill announcer banner ---- */
#multikill {
  position: absolute; top: 26%; left: 50%; transform: translateX(-50%);
  text-align: center; font-weight: 900; font-size: 46px; letter-spacing: 1px;
  color: #ffcf3f; text-shadow: 0 0 18px rgba(255,120,40,.9), 0 3px 8px #000;
  pointer-events: none; z-index: 8; white-space: nowrap;
}
#multikill .mkSub { font-size: 18px; font-weight: 700; color: #ff8a3d; margin-top: 2px; letter-spacing: 0; }
#multikill .mkWho { color: #fff; text-shadow: 0 0 14px rgba(255,255,255,.55), 0 3px 8px #000; }
#multikill.pop { animation: mkPop .5s cubic-bezier(.2,1.4,.4,1) both; }
@keyframes mkPop { 0% { transform: translateX(-50%) scale(.4); opacity: 0; } 60% { transform: translateX(-50%) scale(1.15); opacity: 1; } 100% { transform: translateX(-50%) scale(1); opacity: 1; } }

/* ---- ⬆️ level-up toast (your own level-ups only) ---- */
#lvlToast {
  position: absolute; top: 36%; left: 50%; transform: translateX(-50%);
  text-align: center; font-weight: 900; font-size: 26px; letter-spacing: .5px;
  color: #ffd94a; text-shadow: 0 0 14px rgba(255,200,60,.85), 0 3px 8px #000;
  pointer-events: none; z-index: 8; white-space: nowrap;
}
#lvlToast.pop { animation: mkPop .5s cubic-bezier(.2,1.4,.4,1) both; }

/* ---- 🛠 server-update pill (deploy drain notice, see {t:"maint"}) ---- */
#maintNote {
  position: fixed; top: 10px; left: 50%; transform: translateX(-50%);
  background: rgba(42, 27, 9, .94); border: 1px solid #b97a2a; border-radius: 999px;
  color: #ffd94a; font-weight: 700; font-size: 13px; padding: 6px 16px;
  text-shadow: 0 1px 3px #000; box-shadow: 0 4px 14px rgba(0,0,0,.5);
  pointer-events: none; z-index: 90; white-space: nowrap;
}

/* lobby game-mode chooser — mode TILES in a responsive grid */
.gmOpt { margin: 6px 0; }
.gmLabel { display: block; font-size: 12px; color: #d4c4a4; margin-bottom: 3px; }
#gmBtns { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 6px; }

/* Lobby map-theme picker: ◀ [big preview] ▶ (fills the Battleground card) */
.themeSel { display: flex; align-items: center; justify-content: center; gap: 10px; }
.themeSel .cpArrow { background: #281c10; color: #e9e0cf; border: 1px solid #5a4629;
  border-radius: 8px; width: 36px; height: 36px; font-size: 17px; cursor: pointer; flex: none; }
.themeSel .cpArrow:hover:not(:disabled) { background: #3a2a14; }
.themeSel .cpArrow:disabled { opacity: .35; cursor: default; }
.themeMid { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 1; min-width: 0; }
#themePreview { position: static; inset: auto; cursor: default; /* override the global fullscreen canvas rule */
  width: 100%; max-width: 340px; height: auto; aspect-ratio: 240 / 150; border-radius: 10px; border: 1px solid #5a4629;
  background: #0e0b08; box-shadow: 0 4px 16px rgba(0,0,0,.4); image-rendering: auto; }
.themeName { font-size: 14px; font-weight: 700; color: #ffcf7a; letter-spacing: .3px; }
.gmBtn {
  width: auto; margin: 0; background: rgba(10,7,16,.5); border: 1px solid #4a3320;
  color: #dac7a2; border-radius: 9px; padding: 8px 11px; font-size: 11.5px; line-height: 1.3;
  cursor: pointer; text-align: left; transition: border-color .12s, box-shadow .12s, transform .06s;
}
.gmBtn:hover:not(:disabled):not(.active) { border-color: #6a4b23; transform: translateY(-1px); }
.gmBtn.active { border-color: #ffcf3f; color: #fff; background: rgba(255,180,60,.10);
  box-shadow: 0 0 10px rgba(255,207,63,.3), inset 0 0 0 1px rgba(255,207,63,.25); }
.gmBtn:disabled { cursor: default; opacity: .8; }

/* ---- Teams option (host controls) ---------------------------------------- */
#teamCfg { margin: 4px 0 2px; padding: 6px 8px; border: 1px solid #4a3320;
  border-radius: 8px; background: rgba(10,7,16,.35); }
.teamCfgRow { display: flex; align-items: center; gap: 8px; margin: 3px 0; flex-wrap: wrap; }
.teamCfgRow .gmLabel { margin: 0; min-width: 66px; }
#teamSizeBtns, #teamPickBtns { display: flex; gap: 4px; flex-wrap: wrap; }
.tsBtn, .tpBtn { background: rgba(10,7,16,.5); border: 1px solid #4a3320; color: #dac7a2;
  border-radius: 7px; padding: 4px 9px; font-size: 11.5px; cursor: pointer; }
.tsBtn.active, .tpBtn.active { border-color: #ffcf3f; color: #fff; box-shadow: 0 0 7px rgba(255,207,63,.3); }
.tsBtn:disabled, .tpBtn:disabled { cursor: default; opacity: .6; }

/* ---- Team-picker squares (everyone) -------------------------------------- */
#teamPicker { margin: 6px 0 2px; }
.teamSquares { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px; }
.teamSquare { border: 2px solid color-mix(in srgb, var(--tc) 55%, #2a2016);
  border-radius: 10px; padding: 7px 8px; background: color-mix(in srgb, var(--tc) 10%, rgba(10,7,16,.55));
  transition: border-color .12s, box-shadow .12s, transform .08s; }
.teamSquares.pick .teamSquare.pickable { cursor: pointer; }
.teamSquares.pick .teamSquare.pickable:hover { border-color: var(--tc);
  box-shadow: 0 0 12px color-mix(in srgb, var(--tc) 45%, transparent); transform: translateY(-1px); }
.teamSquare.mine { border-color: #ffcf3f; box-shadow: 0 0 10px rgba(255,207,63,.28); }
.teamSquare.locked { opacity: .5; cursor: not-allowed; }
.tsHead { display: flex; align-items: center; gap: 6px; font-weight: 700; font-size: 13px;
  color: #f0e6d2; margin-bottom: 5px; }
.tsHead .dot { width: 12px; height: 12px; border-radius: 50%; flex: none; }
.tsHead .tsName { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tsHead .tsCount { font-size: 12px; color: #d4c4a4; font-weight: 600; }
.tsHead .tsFull { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
  color: #ff9a7a; border: 1px solid #7a3a28; border-radius: 5px; padding: 1px 4px; }
.tsSlots { display: flex; flex-direction: column; gap: 3px; }
.tsSlot { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #dac7a2;
  padding: 2px 4px; border-radius: 5px; background: rgba(0,0,0,.18); min-height: 20px; }
.tsSlot .dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.tsSlot.bot { opacity: .62; font-style: italic; }
.tsSlot.you { color: #fff; font-weight: 700; background: rgba(255,207,63,.15); }
.tsSlot.empty { opacity: .4; font-style: italic; justify-content: center; }
.teamHint { font-size: 11.5px; color: #b7a888; text-align: center; margin: 6px 2px 0; }
/* survival: eliminated rows + lives count in the scoreboard */
#scoreboard .row.elim { opacity: .4; }
#scoreboard .livesN { color: #ff8a9a; margin-left: 3px; font-size: 11px; }
/* "scan to join" invite card (only shown when an ngrok tunnel is up) */
/* Compact: QR on the left, title + link + copy stacked on the right, so the card
   is short enough to sit beside the map picker without scrolling the lobby. */
#lobbyInvite {
  display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 4px 10px;
  margin: 0; padding: 9px 11px;
  background: #191007; border: 1px solid #3a2817; border-radius: 12px;
}
#lobbyInvite .inviteTitle { grid-column: 1 / -1; font-size: 12.5px; font-weight: 700; color: #ffcf3f; }
#lobbyInvite .qr {
  grid-row: span 2; width: 92px; height: 92px; border-radius: 8px; background: #fff; padding: 5px;
  image-rendering: pixelated;
}
#lobbyInvite .inviteUrl {
  font-size: 12px; color: #7fe0ff; word-break: break-all; text-align: left; text-decoration: none; align-self: end;
}
#lobbyInvite .inviteUrl:hover { text-decoration: underline; }
button.ghost {
  background: transparent; border: 1px solid #5c4526; color: var(--text);
  font-size: 14px; margin-top: 10px;
}
button.ghost:hover { background: #281b0e; }
button.readied { background: linear-gradient(180deg, #5ee06a, #34b84a); color: #05230b; }

/* ---- Main menu (Play / Options / Rank) — compact, never scrolls ---- */
/* The whole menu is auto-scaled to fit short viewports (see fitMenuScale in
   main.js): it sizes to its natural height and JS shrinks it uniformly rather
   than showing a scrollbar or reflowing the buttons. */
#menu .menuHome {
  max-height: none;
  overflow: visible;
  transform-origin: 50% 50%;
  will-change: transform;
}
.menuHome { text-align: center; }
/* sign-in / register screen (the old first-run welcome, repurposed) */
.welcomeName { display: block; text-align: left; margin: 18px 0 4px; }
.welcomeName input { font-size: 18px; padding: 13px; text-align: center; }
#welcome #welcomeBtn { font-size: 19px; padding: 15px; margin-top: 14px; width: 100%; }
.authPanel .welcomeName { margin: 12px 0 2px; }
.authPanel .welcomeName input { font-size: 16px; padding: 11px; }
.authTabs { display: flex; gap: 8px; margin: 4px 0 2px; }
.authTabs .authTab {
  flex: 1; margin-top: 0; padding: 9px; font-size: 14px; font-weight: 700;
  background: transparent; border: 1px solid #5c4526; border-radius: 9px; color: var(--text);
}
.authTabs .authTab:hover { background: #281b0e; }
.authTabs .authTab.active {
  background: linear-gradient(180deg, #ff8a3d, #f0641e);
  border-color: transparent; color: #1a0d00;
}
.authOauth { margin-top: 14px; }
.authOr { margin: 0 0 8px; font-size: 12px; color: #8d7a58; text-align: center; }
#authOauthBtns { display: flex; gap: 8px; }
.oauthBtn {
  flex: 1; margin-top: 0; padding: 10px; font-size: 14px; font-weight: 700;
  border: 1px solid #4a3320; border-radius: 9px; background: #191007; color: var(--text);
}
.oauthBtn.google:hover { border-color: #ea4335; }
.oauthBtn.facebook:hover { border-color: #1877f2; }
.oauthBtn.instagram:hover { border-color: #e1306c; }
.authLinks { display: flex; gap: 14px; justify-content: center; margin: 12px 0 0; }
.linkBtn {
  width: auto; margin: 0; padding: 0; background: none; border: none;
  color: #c7b596; font-size: 12px; text-decoration: underline; cursor: pointer; font-weight: 500;
}
.linkBtn:hover { color: #ffcf3f; filter: none; }
.accountRow { margin: 2px 0 0; font-size: 12px; color: #c7b596; display: flex; gap: 10px; justify-content: center; align-items: baseline; }
.accountRow .linkBtn { font-size: 12px; }

/* Report & Feedback (cheater / bug / feedback tickets) */
.reportPanel { width: min(440px, 92vw); text-align: left; }
.reportTypes { display: flex; gap: 8px; margin-top: 12px; }
.reportTypes .reportType {
  flex: 1; margin-top: 0; padding: 9px 4px; font-size: 13px; font-weight: 700;
  background: transparent; border: 1px solid #5c4526; border-radius: 9px; color: var(--text);
}
.reportTypes .reportType.active {
  background: linear-gradient(180deg, #ff8a3d, #f0641e);
  border-color: transparent; color: #1a0d00;
}
.reportPanel textarea {
  width: 100%; padding: 11px 12px; margin-top: 4px; resize: vertical; min-height: 96px;
  background: #191007; border: 1px solid #4a3320; border-radius: 9px;
  color: var(--text); font-size: 14px; outline: none; font-family: inherit;
}
.reportPanel textarea:focus { border-color: var(--accent); }
.shake { animation: shake .38s; border-color: #ff5a5a !important; }
@keyframes shake { 0%,100% { transform: translateX(0); } 20%,60% { transform: translateX(-7px); } 40%,80% { transform: translateX(7px); } }
.menuBtns { margin-top: 16px; }
.menuBtns #playBtn { font-size: 19px; padding: 15px; margin-top: 6px; }
/* Quick Gameplay — a distinct teal/green call-to-action, set apart from Play */
.menuBtns #quickBtn {
  font-size: 20px; padding: 16px; width: 100%; font-weight: 800; color: #05231f;
  background: linear-gradient(180deg, #3ff0c0, #16b48c); border: none;
  box-shadow: 0 6px 18px -6px rgba(22,180,140,.7);
}
.menuBtns #quickBtn:hover { filter: brightness(1.06); transform: translateY(-1px); }
.lobbyRow.botsRow { opacity: .7; font-style: italic; justify-content: center; }

/* Solo "Start now" — the host force-start button, promoted to a primary CTA when
   you're the only human (starting the match against bots). */
#startBtn.solo {
  display: block; opacity: 1; color: #05231f; font-weight: 800;
  background: linear-gradient(180deg, #3ff0c0, #16b48c); border: none;
  box-shadow: 0 6px 18px -6px rgba(22,180,140,.7);
}
#startBtn.solo:hover { filter: brightness(1.06); }

/* Generic confirm dialog (sits above every other overlay). */
#confirmModal { z-index: 60; }
.confirmPanel { width: min(400px, 92vw); text-align: center; }
.confirmPanel #confirmMsg { margin: 8px 0 18px; color: #e4d6ba; line-height: 1.5; }
/* ---- First-buy build-plan chooser (Pure vs Combine) ---- */
.planPanel { width: min(780px, 94vw); }
.planPanel #planMsg { margin: 6px 0 4px; color: #e4d6ba; line-height: 1.5; }
.planCards { display: flex; gap: 12px; margin: 12px 0 4px; }
.planCard {
  flex: 1; width: auto; margin: 0; padding: 13px 14px; text-align: left;
  background: rgba(20, 12, 30, .55); border: 1px solid rgba(255, 211, 90, .35);
  border-radius: 12px; color: #e4d6ba; font-size: 12.5px; font-weight: 400;
  transition: transform .08s ease, border-color .15s, box-shadow .15s, background .15s;
}
/* ---- Animated strategy demo inside each plan card (see planDemoSVG, main.js):
   a looping mini spell-branch where a mouse cursor clicks through the whole
   plan. Pure = 8s loop (5 buys + milestone flare); Combine = 9s loop (+ pin,
   alternating buys, fusion). All timing is keyframe percentages — no JS. ---- */
.planCard svg.planDemo {
  width: 100%; height: auto; display: block; margin: 0 0 10px;
  background: radial-gradient(120% 100% at 50% 0%, rgba(120,64,28,.18), transparent 70%), rgba(10,7,16,.6);
  border: 1px solid #3a2817; border-radius: 10px;
}
.planDemo text { pointer-events: none; user-select: none; }
.planDemo .pdRail { stroke: #241733; stroke-width: 3; stroke-linecap: round; }
.planDemo .pdRail.lit { stroke: var(--pa); stroke-width: 3.5; opacity: .9;
  transform-box: fill-box; transform-origin: left center; transform: scaleX(0); }
.planDemo .cb { stroke: var(--pb); }
.planDemo .pdAnchor circle { fill: #17101f; stroke: var(--pa); stroke-width: 2.5; }
.planDemo .pdAnchor.ci circle { stroke: var(--pb); }
.planDemo .pdDot { fill: #17101f; stroke: var(--pa); stroke-width: 2; stroke-opacity: .45;
  transform-box: fill-box; transform-origin: center; }
.planDemo .pdDot.cb { stroke: var(--pb); }
.planDemo .pdRip { fill: none; stroke: #fff; stroke-width: 1.6; opacity: 0; }
.planDemo .pdPin circle { fill: #17101f; stroke: var(--pb); stroke-width: 2; stroke-opacity: .5;
  transform-box: fill-box; transform-origin: center; }
.planDemo .pdPin text { fill: #cdb6ff; font-weight: 800; }
.planDemo .pdFlare { fill: none; stroke: var(--pa); stroke-width: 2.5; opacity: 0; }
.planDemo .pdConv { stroke-width: 3; stroke-linecap: round; stroke: var(--pa);
  stroke-dasharray: 100; stroke-dashoffset: 100; opacity: 0; }
.planDemo .pdBadge { transform-box: fill-box; transform-origin: center; transform: scale(0); }
.planDemo .pdBadge circle { fill: #1d1229; stroke: #ffd35a; stroke-width: 2.5;
  filter: drop-shadow(0 0 6px rgba(255,211,90,.8)); }
.planDemo .pdBurst { fill: none; stroke: #ffd35a; stroke-width: 2.5; opacity: 0; }
.planDemo .pdCur path { fill: #fff; stroke: #1a1208; stroke-width: 1.1;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,.65)); }
/* --- PURE timeline (8s): buys at 10/22/34/46/58%, flare, fade-reset --- */
#planPure .pdCur { animation: pdCurP 8s ease-in-out infinite; }
@keyframes pdCurP {
  0% { transform: translate(48px,82px) scale(1); }
  8.5%, 9% { transform: translate(62px,55px) scale(1); }
  10% { transform: translate(62px,55px) scale(.8); }
  11.5% { transform: translate(62px,55px) scale(1); }
  20.5%, 21% { transform: translate(98px,55px) scale(1); }
  22% { transform: translate(98px,55px) scale(.8); }
  23.5% { transform: translate(98px,55px) scale(1); }
  32.5%, 33% { transform: translate(134px,55px) scale(1); }
  34% { transform: translate(134px,55px) scale(.8); }
  35.5% { transform: translate(134px,55px) scale(1); }
  44.5%, 45% { transform: translate(170px,55px) scale(1); }
  46% { transform: translate(170px,55px) scale(.8); }
  47.5% { transform: translate(170px,55px) scale(1); }
  56.5%, 57% { transform: translate(206px,55px) scale(1); }
  58% { transform: translate(206px,55px) scale(.8); }
  59.5% { transform: translate(206px,55px) scale(1); }
  66%, 86% { transform: translate(216px,76px) scale(1); }
  100% { transform: translate(48px,82px) scale(1); }
}
#planPure .pdRail.lit { animation: pdRailP 8s linear infinite; }
@keyframes pdRailP {
  0%, 10% { transform: scaleX(0); }   12% { transform: scaleX(.145); }
  21.5% { transform: scaleX(.145); }  23.5% { transform: scaleX(.36); }
  33.5% { transform: scaleX(.36); }   35.5% { transform: scaleX(.575); }
  45.5% { transform: scaleX(.575); }  47.5% { transform: scaleX(.79); }
  57.5% { transform: scaleX(.79); }   59.5%, 90% { transform: scaleX(1); }
  96%, 100% { transform: scaleX(0); }
}
/* dot k lights right after its click; everything dims for the loop reset */
@keyframes pdD1 { 0%,10.5% { fill:#17101f; stroke-opacity:.45; } 11.5%,90% { fill:var(--pa); stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.45; } }
@keyframes pdD2 { 0%,22.5% { fill:#17101f; stroke-opacity:.45; } 23.5%,90% { fill:var(--pa); stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.45; } }
@keyframes pdD3 { 0%,34.5% { fill:#17101f; stroke-opacity:.45; } 35.5%,90% { fill:var(--pa); stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.45; } }
@keyframes pdD4 { 0%,46.5% { fill:#17101f; stroke-opacity:.45; } 47.5%,90% { fill:var(--pa); stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.45; } }
@keyframes pdD5 { 0%,58.5% { fill:#17101f; stroke-opacity:.45; transform:scale(1); } 59.5% { fill:var(--pa); stroke-opacity:1; transform:scale(1.3); } 63% { transform:scale(1); } 90% { fill:var(--pa); stroke-opacity:1; transform:scale(1); } 96%,100% { fill:#17101f; stroke-opacity:.45; transform:scale(1); } }
#planPure .pdDot.pp1 { animation: pdD1 8s linear infinite; }
#planPure .pdDot.pp2 { animation: pdD2 8s linear infinite; }
#planPure .pdDot.pp3 { animation: pdD3 8s linear infinite; }
#planPure .pdDot.pp4 { animation: pdD4 8s linear infinite; }
#planPure .pdDot.pp5 { animation: pdD5 8s linear infinite; }
/* white click-ripple at each buy */
@keyframes pdR10 { 0%,10% { r:5px; opacity:0; } 10.5% { r:6px; opacity:.9; } 16%,100% { r:18px; opacity:0; } }
@keyframes pdR22 { 0%,22% { r:5px; opacity:0; } 22.5% { r:6px; opacity:.9; } 28%,100% { r:18px; opacity:0; } }
@keyframes pdR34 { 0%,34% { r:5px; opacity:0; } 34.5% { r:6px; opacity:.9; } 40%,100% { r:18px; opacity:0; } }
@keyframes pdR46 { 0%,46% { r:5px; opacity:0; } 46.5% { r:6px; opacity:.9; } 52%,100% { r:18px; opacity:0; } }
@keyframes pdR58 { 0%,58% { r:5px; opacity:0; } 58.5% { r:6px; opacity:.9; } 64%,100% { r:18px; opacity:0; } }
#planPure .pdRip.pp1 { animation: pdR10 8s linear infinite; }
#planPure .pdRip.pp2 { animation: pdR22 8s linear infinite; }
#planPure .pdRip.pp3 { animation: pdR34 8s linear infinite; }
#planPure .pdRip.pp4 { animation: pdR46 8s linear infinite; }
#planPure .pdRip.pp5 { animation: pdR58 8s linear infinite; }
#planPure .pdFlare { animation: pdFlareP 8s linear infinite; }
@keyframes pdFlareP { 0%,58.5% { r:9px; opacity:0; } 59.5% { r:10px; opacity:.95; } 72%,100% { r:30px; opacity:0; } }
/* --- COMBINE timeline (9s): +pin at 6%, buys at 16/26/36/46/56/66%, fusion --- */
#planCombo .pdCur { animation: pdCurC 9s ease-in-out infinite; }
@keyframes pdCurC {
  0% { transform: translate(52px,92px) scale(1); }
  4.5%, 5% { transform: translate(41px,61px) scale(1); }
  6% { transform: translate(41px,61px) scale(.8); }
  7.5% { transform: translate(41px,61px) scale(1); }
  14.5%, 15% { transform: translate(62px,34px) scale(1); }
  16% { transform: translate(62px,34px) scale(.8); }
  17.5% { transform: translate(62px,34px) scale(1); }
  24.5%, 25% { transform: translate(62px,74px) scale(1); }
  26% { transform: translate(62px,74px) scale(.8); }
  27.5% { transform: translate(62px,74px) scale(1); }
  34.5%, 35% { transform: translate(98px,34px) scale(1); }
  36% { transform: translate(98px,34px) scale(.8); }
  37.5% { transform: translate(98px,34px) scale(1); }
  44.5%, 45% { transform: translate(98px,74px) scale(1); }
  46% { transform: translate(98px,74px) scale(.8); }
  47.5% { transform: translate(98px,74px) scale(1); }
  54.5%, 55% { transform: translate(134px,34px) scale(1); }
  56% { transform: translate(134px,34px) scale(.8); }
  57.5% { transform: translate(134px,34px) scale(1); }
  64.5%, 65% { transform: translate(134px,74px) scale(1); }
  66% { transform: translate(134px,74px) scale(.8); }
  67.5% { transform: translate(134px,74px) scale(1); }
  74%, 88% { transform: translate(202px,66px) scale(1); }
  100% { transform: translate(52px,92px) scale(1); }
}
#planCombo .pdPin { animation: pdPinC 9s linear infinite; }
@keyframes pdPinC {
  0%, 6.5% { transform: scale(1); }
  7.5% { transform: scale(1.35); }
  10%, 100% { transform: scale(1); }
}
#planCombo .pdPin circle { animation: pdPinLitC 9s linear infinite; }
@keyframes pdPinLitC { 0%,6.5% { fill:#17101f; stroke-opacity:.5; } 7.5%,90% { fill:#2a1c3c; stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.5; } }
#planCombo .pdAnchor.ci { animation: pdAnchC 9s linear infinite; }
@keyframes pdAnchC { 0%,7% { opacity:.4; } 9%,90% { opacity:1; } 96%,100% { opacity:.4; } }
#planCombo .pdRail.lit.cfr { animation: pdRailCF 9s linear infinite; }
@keyframes pdRailCF {
  0%, 16.5% { transform: scaleX(0); }  17.5% { transform: scaleX(.25); }
  36.5% { transform: scaleX(.25); }    37.5% { transform: scaleX(.625); }
  56.5% { transform: scaleX(.625); }   57.5%, 90% { transform: scaleX(1); }
  96%, 100% { transform: scaleX(0); }
}
#planCombo .pdRail.lit.cir { animation: pdRailCI 9s linear infinite; }
@keyframes pdRailCI {
  0%, 26.5% { transform: scaleX(0); }  27.5% { transform: scaleX(.25); }
  46.5% { transform: scaleX(.25); }    47.5% { transform: scaleX(.625); }
  66.5% { transform: scaleX(.625); }   67.5%, 90% { transform: scaleX(1); }
  96%, 100% { transform: scaleX(0); }
}
@keyframes pdDC16 { 0%,16.5% { fill:#17101f; stroke-opacity:.45; } 17.5%,90% { fill:var(--pa); stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.45; } }
@keyframes pdDC26 { 0%,26.5% { fill:#17101f; stroke-opacity:.45; } 27.5%,90% { fill:var(--pb); stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.45; } }
@keyframes pdDC36 { 0%,36.5% { fill:#17101f; stroke-opacity:.45; } 37.5%,90% { fill:var(--pa); stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.45; } }
@keyframes pdDC46 { 0%,46.5% { fill:#17101f; stroke-opacity:.45; } 47.5%,90% { fill:var(--pb); stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.45; } }
@keyframes pdDC56 { 0%,56.5% { fill:#17101f; stroke-opacity:.45; } 57.5%,90% { fill:var(--pa); stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.45; } }
@keyframes pdDC66 { 0%,66.5% { fill:#17101f; stroke-opacity:.45; } 67.5%,90% { fill:var(--pb); stroke-opacity:1; } 96%,100% { fill:#17101f; stroke-opacity:.45; } }
#planCombo .pdDot.cf1 { animation: pdDC16 9s linear infinite; }
#planCombo .pdDot.ci1 { animation: pdDC26 9s linear infinite; }
#planCombo .pdDot.cf2 { animation: pdDC36 9s linear infinite; }
#planCombo .pdDot.ci2 { animation: pdDC46 9s linear infinite; }
#planCombo .pdDot.cf3 { animation: pdDC56 9s linear infinite; }
#planCombo .pdDot.ci3 { animation: pdDC66 9s linear infinite; }
@keyframes pdRC6  { 0%,6%  { r:5px; opacity:0; } 6.5%  { r:6px; opacity:.9; } 12%,100% { r:16px; opacity:0; } }
@keyframes pdRC16 { 0%,16% { r:5px; opacity:0; } 16.5% { r:6px; opacity:.9; } 22%,100% { r:16px; opacity:0; } }
@keyframes pdRC26 { 0%,26% { r:5px; opacity:0; } 26.5% { r:6px; opacity:.9; } 32%,100% { r:16px; opacity:0; } }
@keyframes pdRC36 { 0%,36% { r:5px; opacity:0; } 36.5% { r:6px; opacity:.9; } 42%,100% { r:16px; opacity:0; } }
@keyframes pdRC46 { 0%,46% { r:5px; opacity:0; } 46.5% { r:6px; opacity:.9; } 52%,100% { r:16px; opacity:0; } }
@keyframes pdRC56 { 0%,56% { r:5px; opacity:0; } 56.5% { r:6px; opacity:.9; } 62%,100% { r:16px; opacity:0; } }
@keyframes pdRC66 { 0%,66% { r:5px; opacity:0; } 66.5% { r:6px; opacity:.9; } 72%,100% { r:16px; opacity:0; } }
#planCombo .pdRip.cpin { animation: pdRC6 9s linear infinite; }
#planCombo .pdRip.cf1 { animation: pdRC16 9s linear infinite; }
#planCombo .pdRip.ci1 { animation: pdRC26 9s linear infinite; }
#planCombo .pdRip.cf2 { animation: pdRC36 9s linear infinite; }
#planCombo .pdRip.ci2 { animation: pdRC46 9s linear infinite; }
#planCombo .pdRip.cf3 { animation: pdRC56 9s linear infinite; }
#planCombo .pdRip.ci3 { animation: pdRC66 9s linear infinite; }
/* the two branches converge and FUSE: paths draw in, badge pops, ring bursts */
#planCombo .pdConv { animation: pdConvC 9s linear infinite; }
@keyframes pdConvC {
  0%, 69% { stroke-dashoffset: 100; opacity: 0; }
  70% { stroke-dashoffset: 100; opacity: .9; }
  78%, 90% { stroke-dashoffset: 0; opacity: .9; }
  96%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
#planCombo .pdBadge { animation: pdBadgeC 9s linear infinite; }
@keyframes pdBadgeC {
  0%, 71% { transform: scale(0); opacity: 0; }
  72% { opacity: 1; }
  76% { transform: scale(1.2); opacity: 1; }
  79%, 90% { transform: scale(1); opacity: 1; }
  96%, 100% { transform: scale(0); opacity: 0; }
}
#planCombo .pdBurst { animation: pdBurstC 9s linear infinite; }
@keyframes pdBurstC { 0%,73% { r:10px; opacity:0; } 74% { r:11px; opacity:.9; } 84%,100% { r:32px; opacity:0; } }
.planCard:hover {
  border-color: #ffd35a; background: rgba(255, 211, 90, .08);
  box-shadow: 0 0 16px rgba(255, 211, 90, .3); transform: translateY(-2px); filter: none;
}
.planCard b { display: block; font-size: 16px; margin-bottom: 6px; color: #ffd35a; }
.planCard span { display: block; line-height: 1.45; color: #cdbfa4; }
.planPanel .planNote { margin: 8px 0 2px; font-size: 11.5px; color: #8d7a58; line-height: 1.4; }
.planPanel .planMute {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  margin: 6px 0 0; font-size: 11.5px; color: #a08c66; cursor: pointer; user-select: none;
}
.planPanel .planMute input { width: auto; margin: 0; accent-color: #ffd35a; cursor: pointer; }
.planPanel .confirmBtns button.ghost { margin-top: 8px; }
.confirmBtns { display: flex; gap: 10px; justify-content: center; }
.confirmBtns button { flex: 1; }
.menuBtns .ghost { margin-top: 10px; }

/* Training submenu: the two training modes tucked under the Training plate,
   slightly smaller so they read as children of the button above. */
#menu .menuBtns #trainMenu button {
  max-width: 272px; min-height: 46px; font-size: 14.5px;
  margin-top: 7px; padding: 9px 22px 13px;
}

/* ===== Molten-lava fire skin (CraftPix rpg-game-ui) =========================
   Every overlay (main menu, welcome, pause, options, codex, server browser,
   lobby, shop, confirm) wears the fire UI kit: a dark bronze-framed window
   (border-image) with glowing molten-plate primary buttons. The shared purple
   chrome (fields, borders, rows, tabs, labels) was warmed to ember above so the
   interiors read as one theme with the frame. */

/* Bronze-framed window for every overlay panel */
.overlay > .panel {
  background: transparent;                 /* the frame's fill provides the interior */
  border: 11px solid transparent;
  border-image: url("assets/menu-ui/panel.png") 8 fill / 11px / 0 stretch;
  border-radius: 0;
  box-shadow:
    0 24px 64px rgba(0,0,0,.72),
    0 0 46px -8px rgba(255,120,40,.24);
}

/* Glowing molten plates for the primary calls-to-action across the menus. */
#menu .menuBtns button,
#welcome #welcomeBtn,
#escMenu .menuBtns button,
#lobby #readyBtn,
#shop #shopReadyBtn,
#confirmModal .confirmBtns button,
#renameModal .confirmBtns button {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 100%;
  min-height: 56px;
  padding: 12px 26px 16px;                 /* extra bottom pad lifts the label off the skirt */
  background: url("assets/menu-ui/btn.png") center / 100% 100% no-repeat;
  border: none; border-radius: 0;
  color: #ffe7c2;
  font-size: 16px; font-weight: 800; letter-spacing: .4px;
  text-shadow: 0 1px 2px #000, 0 2px 7px rgba(0,0,0,.75);
  box-shadow: none;
  filter: none;
  transition: filter .12s ease, transform .06s ease;
}
#menu .menuBtns button:hover,
#welcome #welcomeBtn:hover,
#escMenu .menuBtns button:hover,
#lobby #readyBtn:hover,
#shop #shopReadyBtn:hover,
#confirmModal .confirmBtns button:hover,
#renameModal .confirmBtns button:hover {
  background-image: url("assets/menu-ui/btn-hover.png");
  filter: brightness(1.07);
}
#menu .menuBtns button:active,
#welcome #welcomeBtn:active,
#escMenu .menuBtns button:active,
#lobby #readyBtn:active,
#shop #shopReadyBtn:active,
#confirmModal .confirmBtns button:active,
#renameModal .confirmBtns button:active {
  background-image: url("assets/menu-ui/btn-push.png");
  transform: translateY(1px);
}
/* A paywall's Pay button when purchasing isn't live yet — greyed & inert.
   Declared after :hover/:active so it wins on a hovered disabled button. */
#confirmModal .confirmBtns button:disabled {
  filter: grayscale(.7) brightness(.75);
  opacity: .65;
  cursor: default;
  transform: none;
}
/* the vertical menu stacks cap their width and center each plate */
#menu .menuBtns button,
#welcome #welcomeBtn,
#escMenu .menuBtns button {
  max-width: 320px; margin: 11px auto 0; min-height: 60px; padding: 12px 30px 17px; font-size: 17px;
}
/* the "readied" (green) state keeps its meaning even on a molten plate */
#lobby #readyBtn.readied,
#shop #shopReadyBtn.readied {
  background: linear-gradient(180deg, #5ee06a, #34b84a); color: #05230b;
  filter: none;
}
/* the two primary calls-to-action stand a little taller with a warm glow */
#menu .menuBtns #quickBtn,
#menu .menuBtns #playBtn,
#welcome #welcomeBtn {
  min-height: 66px; font-size: 19px;
}
#menu .menuBtns #quickBtn {
  filter: drop-shadow(0 0 12px rgba(255,140,50,.5));
  animation: menuCtaGlow 2.6s ease-in-out infinite;
}
@keyframes menuCtaGlow {
  0%, 100% { filter: drop-shadow(0 0 8px rgba(255,140,50,.35)); }
  50%      { filter: drop-shadow(0 0 16px rgba(255,170,70,.65)); }
}
@media (prefers-reduced-motion: reduce) {
  #menu .menuBtns #quickBtn { animation: none; }
}

.browserTop h1 { margin: 0; }

/* host option checkbox */
.opt {
  display: flex; align-items: center; gap: 9px; margin: 12px 0 2px;
  font-size: 13.5px; color: #d4c4a4; cursor: pointer;
}
.opt input { width: 18px; height: 18px; accent-color: var(--accent); margin: 0; flex: none; }
.opt input:disabled { cursor: default; }
/* #hostOpts is a .lobbyCard (frame comes from that); these just tune spacing. */
#hostOpts .opt { margin: 8px 0 2px; }
#hostOpts .gmOpt + .gmOpt, #hostOpts .gmOpt + .opt { margin-top: 10px; padding-top: 9px; border-top: 1px solid #2c1e10; }
.gmOpt { margin: 2px 0; }

/* ---- Lobby sticky action bar (spectate · status · ready/start) ---- */
.lobbyFooter {
  display: flex; align-items: center; gap: 14px; flex: none;
  padding: 11px 20px 13px; border-top: 1px solid #3a2817;
  background: linear-gradient(0deg, rgba(72,42,16,.42), rgba(25,16,7,0));
}
.lobbyFooter #spectateOpt { margin: 0; flex: 0 1 auto; font-size: 12.5px; }
.lobbyFooter #lobbyStatus { flex: 1 1 auto; margin: 0; text-align: center; font-size: 13px; min-width: 0; }
#lobbyActions { display: flex; align-items: center; gap: 10px; flex: none; margin: 0; }
#lobby #startBtn { margin: 0; min-height: 44px; padding: 8px 16px; white-space: nowrap; }
/* Solo host: "Start now" is the only CTA — promote it from ghost to a gold plate. */
#lobby #startBtn.solo {
  background: linear-gradient(180deg, #ffcf3f, #e0952a); color: #2a1806; border: none;
  font-weight: 800; min-height: 52px; padding: 10px 26px; box-shadow: 0 0 13px rgba(255,180,60,.42);
}
#lobby #startBtn.solo:hover { filter: brightness(1.06); }
#lobby #readyBtn { margin: 0; width: auto; min-width: 190px; min-height: 52px; padding: 10px 30px 14px; }
@media (max-width: 720px) {
  .lobbyFooter { flex-wrap: wrap; }
  .lobbyFooter #lobbyStatus { order: 3; flex-basis: 100%; }
  #lobbyActions { flex: 1 1 auto; justify-content: flex-end; }
}

/* ---- Short-screen lobby: shrink to fit so the panel never grows a scrollbar.
   The right column's map preview is the tallest element, so it scales
   CONTINUOUSLY with viewport height (no stair-step gaps between breakpoints);
   the discrete tiers then tighten paddings, gaps and type. Keyed on viewport
   HEIGHT (the binding constraint); placed after the base lobby rules so they win
   by source order. */
#themePreview { max-width: min(340px, 24vh); }
@media (max-height: 900px) {
  .lobbyPanel { max-height: 95vh; max-height: 95svh; }
  .lobbyBody { gap: 11px; padding: 12px 20px; }
  .lobbySide { gap: 10px; }
  .lobbyRoster, .lobbyCard { padding: 9px 12px; }
  #botHint { margin-top: 6px; padding: 6px 10px; font-size: 12px; }
}
@media (max-height: 800px) {
  .lobbyHeader { padding: 10px 20px 9px; }
  .lobbyFooter { padding: 9px 20px 10px; }
  .cardHead { margin-bottom: 7px; padding-bottom: 5px; }
  #lobbyList { max-height: 26vh; }
  #hostOpts .gmOpt + .gmOpt, #hostOpts .gmOpt + .opt { margin-top: 8px; padding-top: 7px; }
}
@media (max-height: 720px) {
  .lobbyPanel { max-height: 96vh; max-height: 96svh; }
  .lobbyGlyph { font-size: 24px; }
  .lobbyTitleWrap h1.small { font-size: 18px; }
  .lobbyBody { gap: 9px; padding: 10px 18px; }
  .lobbySide { gap: 8px; }
  .lobbyRoster, .lobbyCard { padding: 8px 11px; }
  .gmBtn { padding: 6px 9px; font-size: 11px; line-height: 1.25; }
  #gmBtns { gap: 5px; }
  #lobbyList { max-height: 24vh; }
  #lobby #readyBtn { min-height: 46px; min-width: 158px; padding: 8px 24px 12px; }
  #lobby #startBtn.solo { min-height: 46px; padding: 8px 22px; }
  #lobby #startBtn { min-height: 40px; }
  .lobbyFooter #spectateOpt { font-size: 12px; }
}
@media (max-height: 700px) {
  .lobbyPanel { max-height: 97vh; max-height: 97svh; }
  .lobbyHeader { padding: 7px 16px 6px; }
  .lobbyGlyph { font-size: 21px; }
  .lobbyTitleWrap h1.small { font-size: 16px; }
  .lobbyCount { padding: 4px 10px; }
  .lobbyCount #lobbyCountNum { font-size: 17px; }
  .lobbyBody { gap: 8px; padding: 8px 16px; }
  .lobbySide { gap: 7px; }
  .lobbyRoster, .lobbyCard { padding: 7px 10px; }
  .cardHead { margin-bottom: 5px; padding-bottom: 4px; font-size: 11px; }
  .lobbyFooter { padding: 6px 16px 7px; }
  #lobbyList { max-height: 22vh; }
}

/* ---- Shop ---- */
/* Wider + compact so all three stalls' content fits without a scrollbar. */
/* Wide marketplace: expands horizontally and uses multi-column lists so the
   whole shop fits on screen without scrolling. */
.panel.wide { width: min(1040px, 96vw); max-height: 96vh; max-height: 96svh; overflow-y: auto; padding: 14px 20px 12px; }
/* Spells stall: the tree + diorama + detail columns want ROOM — while the spells
   panel is the open one, the shop window expands to nearly the whole screen.
   (Also outranks the townpanel's 880px width below; the dead-shop corner panel
   is exempt and keeps its compact box.) */
#shop:not(.deadmode) > .panel:has(#panel-spells:not(.hidden)) { width: min(1840px, 97vw); }
/* Skill-tree stall: same near-fullscreen idea, but the web is SQUARE — the tree
   grows to the viewport's HEIGHT (see #skillTree) and the panel width follows
   it, instead of stranding the square in a huge empty panel. Outranks the
   townpanel width below; the dead-shop corner panel is exempt. */
#shop:not(.deadmode) > .panel:has(#panel-tree:not(.hidden)) {
  width: min(1360px, max(880px, calc(92vh - 40px)), 97vw);
}
/* Armory & weaponsmith stalls: wider than the 880px townpanel default so the
   racks flatten (outfits 6-up → 2 rows, staves 5-up → 3 rows) and the panel
   stays scroll-free; the dead-shop corner panel is exempt. */
#shop:not(.deadmode) > .panel:has(#panel-armory:not(.hidden)),
#shop:not(.deadmode) > .panel:has(#panel-weapons:not(.hidden)) { width: min(1160px, 94vw); }
#shop h1.small { margin-bottom: 2px; }
/* countdown + gold share one compact row to reclaim vertical space */
.shopTop { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; margin: 2px 0 6px; }
#shopCountdown {
  text-align: left; font-size: 20px; font-weight: 800; letter-spacing: .5px;
  color: #ffcf3f; text-shadow: 0 2px 10px rgba(255,140,40,.5);
}
#shopCountdown.urgent {
  color: #ff5a5a; animation: countPulse .6s ease-in-out infinite;
}
@keyframes countPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.14); } }
#goldRow { text-align: right; font-size: 15px; color: #ffcf3f; white-space: nowrap; }
#goldRow b { font-size: 19px; }
#spRow { text-align: right; font-size: 15px; color: #9fd0ff; white-space: nowrap; }
#spRow b { font-size: 19px; }
/* tiny XP readout: "Lv N [▓▓▓░░] xp/need" */
#xpRow { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #cdbf9f; white-space: nowrap; }
#xpRow b { color: #ffd94a; font-size: 13px; }
.xpBar {
  display: inline-block; width: 92px; height: 7px; border-radius: 4px; overflow: hidden;
  background: rgba(10,7,16,.7); border: 1px solid rgba(255,217,74,.35); vertical-align: middle;
}
.xpBar > span { display: block; height: 100%; width: 0; background: linear-gradient(90deg, #b98a2c, #ffd94a); }
.xpBar.mini { width: 54px; height: 5px; }
/* golden "LvN" chip prefixed to mage names (scoreboard / TAB / MVP card) */
.lvTag { color: #ffd94a; font-weight: 800; font-size: .82em; opacity: .95; }
.shopHead { font-size: 12px; letter-spacing: .4px; text-transform: uppercase; color: #9d8b6c; margin: 4px 0 4px; }

/* element picker */
#elementList { display: flex; gap: 8px; margin-bottom: 4px; flex-wrap: wrap; }
.elCard {
  flex: 1 1 92px; min-width: 88px; cursor: pointer;
  padding: 6px 8px; border-radius: 10px; text-align: center;
  background: #191007; border: 2px solid #3a2817; transition: border-color .1s, background .1s;
}
.elCard:hover { background: #221808; }
.elCard.selected { border-color: var(--el, var(--accent)); background: #2e1f10; box-shadow: 0 0 12px -2px var(--el, var(--accent)); }
.elCard .elEmoji { font-size: 24px; }
.elCard .elName { font-size: 12px; font-weight: 700; margin-top: 2px; }
.elCard .elTag { font-size: 10.5px; margin-top: 2px; color: #9d8b6c; }
.elCard .elTag.owned { color: #5ee06a; }
.elCard .elDesc { font-size: 10px; color: #8d7a58; margin-top: 4px; line-height: 1.25; }

#elementBadge {
  position: absolute; bottom: 66px; left: 14px;
  font-size: 12px; font-weight: 700; color: #fff;
  background: rgba(10,7,16,.6); border: 1.5px solid #4a3320; border-radius: 8px;
  padding: 3px 9px; backdrop-filter: blur(3px);
}
#shopList { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 4px; }
#passiveList { display: block; }
.passCards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
/* element filter tabs for the passive shop */
.passTabs { display: flex; gap: 6px; justify-content: center; margin-bottom: 8px; }
.passTab {
  position: relative; padding: 6px 10px; border-radius: 9px; font-size: 17px; line-height: 1;
  background: rgba(255,255,255,.05); border: 1.5px solid rgba(255,255,255,.12); cursor: pointer;
  transition: transform .08s, border-color .12s, background .12s;
}
.passTab:hover { transform: translateY(-1px); background: rgba(255,255,255,.09); }
.passTab.on { border-color: var(--el); background: color-mix(in srgb, var(--el) 22%, transparent); box-shadow: 0 0 10px -2px var(--el); }
.passOwn {
  position: absolute; top: -5px; right: -5px; min-width: 15px; height: 15px; padding: 0 3px;
  border-radius: 8px; background: var(--el); color: #10121c; font-size: 10px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}
.shopCard {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 7px 10px; background: #191007; border: 1px solid #3a2817; border-radius: 10px;
}
/* per-slot element chooser inside a spell card (compact row under the card) */
.slotEls { flex-basis: 100%; display: flex; gap: 3px; margin-top: 1px; }
.slotEl {
  width: auto; margin: 0; padding: 2px 5px; font-size: 13px; line-height: 1;
  border-radius: 6px; background: #201808; border: 1.5px solid #3a2817; cursor: pointer;
  filter: grayscale(.5) opacity(.7); transition: filter .1s, border-color .1s;
}
.slotEl:hover { filter: none; }
.slotEl.on { border-color: var(--el, var(--accent)); background: #2e1f10; filter: none; box-shadow: 0 0 8px -2px var(--el, var(--accent)); }
/* ELEMENT COMBO row: pick an optional SECOND element for the spell (∅ = pure) */
.slotEls.combo { margin-top: 0; opacity: .92; }
.slotEls.combo .comboLbl { font-size: 12px; font-weight: 800; color: #9d8b6c; align-self: center; padding: 0 1px; }
.slotEl.none { color: #9d8b6c; font-size: 12px; }
.shopCard .comboTag { font-size: 12px; color: #b98cff; }
.shopCard .sIcon { font-size: 24px; flex: none; }
.shopCard .sInfo { flex: 1; min-width: 0; }
.shopCard .sName { font-size: 14px; font-weight: 600; }
.shopCard .sDesc { font-size: 11px; color: #9d8b6c; }
.shopCard button {
  width: auto; margin: 0; padding: 7px 12px; font-size: 13px; border-radius: 8px;
  /* purchase = violet (never yellow, so it doesn't read as gold) */
  background: linear-gradient(180deg, #a06bff, #6e3fd6); color: #fff;
}
.shopCard button:disabled { background: #3a2817; color: #7d6a4c; cursor: not-allowed; }
.shopCard .owned { font-size: 13px; font-weight: 700; color: #5ee06a; white-space: nowrap; }
.shopCard.starter .owned { color: #c7b596; }
.shopCard.locked { opacity: .5; filter: grayscale(.5); }
.owned.locked { color: #9d8b6c; font-weight: 700; white-space: nowrap; }
.potSize.locked { opacity: .5; filter: grayscale(.5); }
.shopCard.elemental { border-color: var(--el); }
.shopCard .sIcon { position: relative; }
.shopCard .elchip {
  position: absolute; bottom: -4px; right: -6px;
  font-size: 13px; line-height: 1; text-shadow: 0 1px 2px #000;
}

/* ---- Skill tree (radial, Path-of-Exile-style) ---- */
/* Square SVG: near-fullscreen like the spells panel, but HEIGHT is the binding
   dimension for a square — so the cap is viewport-height-driven (minus the
   panel's chrome) and the tree shrinks to fit short screens without scrolling.
   The classic overlay keeps stalls + ready button (~270px of chrome); town mode
   strips them (they live on #townHud), so it gets the roomier cap below. */
#skillTree { position: relative; width: 100%; max-width: min(1280px, calc(96vh - 270px)); margin: 2px auto 0; }
.overlay.townpanel #skillTree { max-width: min(1280px, calc(92vh - 100px)); }
#treeSvg {
  width: 100%; height: auto; aspect-ratio: 1 / 1; display: block; cursor: grab;
  background: radial-gradient(circle at 50% 50%, rgba(120,64,28,.34), rgba(10,7,16,.12) 70%);
  border: 1px solid #4a3320; border-radius: 14px; touch-action: none; /* drag = pan, wheel = zoom */
}
#treeSvg:active { cursor: grabbing; }
.tedge { stroke: #2a1c3c; stroke-width: 2.2; }
.tedge.on { stroke: #b98cff; stroke-width: 3.2; }
.thub { fill: #d9c7ff; stroke: #fff; stroke-width: 2; }
/* central respec button (replaces the plain hub dot) */
.thubBtn { cursor: pointer; }
.thubBtn text { pointer-events: none; user-select: none; fill: #2a1c3c; font-weight: 800; }
.thubBtn:hover .thub { fill: #fff; filter: drop-shadow(0 0 6px #b98cff); }
.thubBtn.off { cursor: default; opacity: .55; }
.thubBtn.off:hover .thub { fill: #d9c7ff; filter: none; }
.tnode circle { fill: #17101f; stroke: var(--el, #fff); stroke-width: 2.5; transition: filter .08s ease; }
.tnode.notable circle { stroke-width: 3.5; }
.tnode.keystone circle { stroke-width: 4.5; filter: drop-shadow(0 0 5px var(--el, #ff5a7a)); }
.tnode.bridge circle { stroke-dasharray: 4 2.5; }
.tnode text { pointer-events: none; user-select: none; }
.tnode.off circle { opacity: .4; }          /* not yet reachable */
.tnode.off text { opacity: .55; }
.tnode.open { cursor: pointer; }             /* allocatable now */
.tnode.open circle { fill: #241636; filter: drop-shadow(0 0 6px var(--el, #b98cff)); }
.tnode.open:hover circle { filter: drop-shadow(0 0 11px var(--el, #b98cff)); }
.tnode.on circle { fill: var(--el, #b98cff); stroke: #fff; filter: drop-shadow(0 0 7px var(--el, #b98cff)); } /* allocated */
/* Big EARNED nodes (centers/bridges/keystones): never buyable — dim dashed shell
   until the skills around them are all owned, then they flip to a normal .on */
.tnode.auto { cursor: default; }
.tnode.auto circle:not(.tprog) { opacity: .5; stroke-dasharray: 3 3; }
.tnode.auto text { opacity: .6; }
.tnode.auto:hover circle:not(.tprog) { opacity: .8; filter: drop-shadow(0 0 6px var(--el, #b98cff)); }
/* completion arc around a locked earned node (dasharray % is inline, via pathLength) */
.tnode circle.tprog { fill: none; stroke: var(--el, #b98cff); stroke-width: 3; opacity: .9; stroke-linecap: round; }
#treePoints { color: #d6b8ff; font-size: 1.15em; }
/* Tip is an absolute overlay pinned to the bottom of the tree, so showing it on
   hover never grows the panel (which would pop a scrollbar). */
#treeTip {
  position: absolute; left: 6px; right: 6px; bottom: 6px; z-index: 3; text-align: left;
  background: rgba(10,7,16,.94); border: 1px solid #4a3320; border-radius: 10px;
  padding: 7px 12px; font-size: 13px; line-height: 1.45; pointer-events: none;
}
/* Hovering a LOWER node flips the tip to the top so it never covers that node. */
#treeTip.top { bottom: auto; top: 6px; }
#treeTip .tstat { display: block; color: #c7b596; font-size: 12px; margin-top: 2px; }

/* ---- Spell tree (radial, per spell slot) ---- */
.spellTabs { display: flex; gap: 6px; margin: 2px 0 8px; }
.spellTab {
  flex: 1; width: auto; margin: 0; padding: 7px 4px 6px; border-radius: 10px; cursor: pointer;
  position: relative; background: #191007; border: 2px solid #3a2817; color: var(--text);
  display: flex; flex-direction: column; align-items: center; gap: 1px; line-height: 1;
}
.spellTab .stIcon { font-size: 21px; }
.spellTab .stIcon img.pixIco { width: 24px; height: 24px; display: inline-block; vertical-align: middle; image-rendering: pixelated; }
.spellTab .stKey { font-size: 10px; font-weight: 700; color: #c7b596; letter-spacing: .5px; }
.spellTab:hover { background: #221808; }
.spellTab.sel { border-color: var(--el, var(--accent)); background: #2e1f10; box-shadow: 0 0 11px -2px var(--el, var(--accent)); }
.spellTab.locked { opacity: .55; }
.spellTab .stBadge {
  position: absolute; top: -5px; right: -4px; font-size: 12px; line-height: 1;
  text-shadow: 0 1px 2px #000; filter: drop-shadow(0 0 3px rgba(0,0,0,.6));
}
/* fused slot's tab: the archetype badge glows and the tab breathes its color */
.spellTab.fused { animation: fusSlot 2.2s ease-in-out infinite; }
.spellTab .stBadge.fus { filter: drop-shadow(0 0 4px var(--el, #ffd35a)); }
/* spendable slot: the tab shimmers gold so unspent 💠 never sits behind a tab you
   forgot to open. Gold border on the unselected tabs (the selected one keeps its
   element border as the "you're here" marker); the pulsing halo lands on all. */
.spellTab.canspend { animation: spellTabSpend 1.15s ease-in-out infinite; }
.spellTab.canspend:not(.sel) { border-color: #ffd35a; }
/* a fused slot that's also spendable keeps its element box-shadow breathing (fusSlot)
   AND gains the gold filter halo — different properties, so both run at once */
.spellTab.fused.canspend { animation: fusSlot 2.2s ease-in-out infinite, spellTabSpend 1.15s ease-in-out infinite; }
@keyframes spellTabSpend {
  0%, 100% { filter: drop-shadow(0 0 2px rgba(255,211,90,.55)); }
  50%      { filter: drop-shadow(0 0 10px rgba(255,211,90,.95)); }
}
/* preview (left) + tree (right) share one centered row; the preview column
   stretches to whatever height the tree's accordion takes this tab */
#spellTreeRow { display: flex; gap: 10px; align-items: stretch; justify-content: center; }
#spellPreview {
  position: relative; flex: 0 0 clamp(148px, 13vw, 260px); min-height: 190px;
  border: 1px solid #4a3320; border-radius: 14px; overflow: hidden;
  background:
    radial-gradient(120% 90% at 50% 30%, rgba(120, 64, 28, .18), transparent 70%),
    linear-gradient(180deg, #17100a, #0b0710);
}
#spellPreview canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* tight layouts drop the diorama: the corner dead-shop panel and small screens */
.overlay.deadmode #spellPreview { display: none; }
@media (max-width: 760px) { #spellPreview { display: none; } }
#spellTree { position: relative; width: 100%; max-width: 1560px; min-width: 0; }

/* ---- Right-hand detail window (description + exact stats of the hovered pick) ----
   Matches the diorama's card: bronze frame + dark molten fill, laid out as a
   stack of sections. Fed by spellShowDetail / spellHoverDetail (main.js). */
/* The panel is a positioned frame; its content lives in an ABSOLUTE inner
   scroller (.sdBody) so hover-swapping the content NEVER changes the panel's box
   height. (If it did, the shop panel would grow and the centered overlay would
   re-center mid-click, shifting the tree out from under the cursor — the skill
   tree dodges this by using a position:absolute tip.) */
#spellDetail {
  position: relative; flex: 0 0 clamp(232px, 18vw, 350px); min-width: 0; align-self: stretch; overflow: hidden;
  border: 1px solid #4a3320; border-radius: 14px;
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(120,64,28,.16), transparent 70%),
    linear-gradient(180deg, #17100a, #0b0710);
}
#spellDetail:empty { display: none; }
.sdBody {
  position: absolute; inset: 0; overflow-y: auto; overflow-x: hidden; padding: 11px 13px;
  text-align: left; font-size: 13px; line-height: 1.4; color: var(--text);
  display: flex; flex-direction: column; gap: 8px;
}
.sdHead { display: flex; align-items: center; gap: 9px; }
.sdIcon { font-size: 26px; line-height: 1; flex: none; }
.sdIcon img.pixIco { width: 30px; height: 30px; image-rendering: pixelated; display: block; }
.sdIcon .em { filter: drop-shadow(0 1px 2px #000); }
.sdTitle { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.sdTitle b { font-size: 15px; font-weight: 800; color: #ffe6b0; line-height: 1.1; }
.sdType { font-size: 11px; letter-spacing: .3px; color: #b79a6f; }
.sdDesc { color: #d6c4a2; font-size: 12.5px; }
.sdCombo {
  border-left: 3px solid #d6b8ff; padding: 5px 8px; border-radius: 6px;
  background: rgba(150,110,220,.12); color: #cbb6e6; font-size: 12px;
}
.sdCombo .sdComboHd { display: block; font-weight: 700; color: #e2c8ff; margin-bottom: 1px; }
.sdStats { display: flex; flex-direction: column; gap: 3px; border-top: 1px solid rgba(74,51,32,.5); padding-top: 6px; }
.sdStat { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.sdStat > span { color: #9d8b6c; font-size: 11.5px; text-transform: uppercase; letter-spacing: .4px; }
.sdStat > b { color: #f0dcae; font-weight: 700; white-space: nowrap; }
.sdStat i { color: #9d8b6c; font-style: normal; font-size: 10.5px; margin-left: 4px; font-weight: 500; }
.sdStat b.up { color: #7de08a; }
.sdNext {
  border: 1px solid #3a2817; border-radius: 9px; padding: 6px 8px;
  background: rgba(10,7,16,.5); display: flex; flex-direction: column; gap: 3px;
}
.sdNextHd { font-size: 11px; font-weight: 700; color: #9fd0ff; letter-spacing: .3px; }
.sdNextNote { font-size: 11.5px; color: #c7b596; }
.sdNext.maxed { color: #ffd35a; font-weight: 800; text-align: center; border-color: #6b4e18; }
.sdStatus { font-size: 12px; color: #c7b596; border-top: 1px solid rgba(74,51,32,.5); padding-top: 6px; }
/* The side panel supersedes the little bottom tooltip everywhere EXCEPT the
   cramped corner dead-shop, where the panel is hidden and the tip carries the
   hover descriptions instead. */
.overlay.deadmode #spellDetail { display: none; }
#spellTip { display: none; }
.overlay.deadmode #spellTip:not(.hidden) { display: block; }
/* narrower shops: the detail drops below the tree full-width (the diorama is the
   first thing to go, at 760px) so the tree keeps usable width */
@media (max-width: 900px) { #spellTreeRow { flex-wrap: wrap; } #spellDetail { flex: 1 1 100%; order: 3; align-self: auto; height: 220px; } }
#spellTreeSvg {
  width: 100%; height: auto; aspect-ratio: 640 / 268; display: block; cursor: grab;
  background: linear-gradient(180deg, rgba(120,64,28,.26), rgba(10,7,16,.10));
  border: 1px solid #4a3320; border-radius: 14px; touch-action: none; /* drag = pan, wheel = zoom */
  /* Near-fullscreen shop: the tree grows with the panel, but its HEIGHT is
     clamped to what the viewport can hold (head + tabs + guide + actions ≈
     350px of chrome) so the panel never pops a scrollbar. When the clamp bites
     a tall accordion tree, preserveAspectRatio="meet" letterboxes it. */
  max-height: max(240px, calc(92vh - 350px));
}
#spellTreeSvg:active { cursor: grabbing; }
.sedge { stroke: #2a1c3c; stroke-width: 3; fill: none; }
.sedge.on { stroke: var(--el, #b98cff); stroke-width: 4.5; opacity: .9; }
.sedge.vert { stroke-width: 2.5; }
/* element branch rails: dim base + a lit stretch over the invested levels */
.srail { stroke: #241733; stroke-width: 3; stroke-linecap: round; }
.srail.on { stroke: var(--el, #b98cff); stroke-width: 4; opacity: .85; stroke-linecap: round; }
/* the primary ⇄ lean link joining the two equipped branches at their anchors */
.slink { stroke: #3a2817; stroke-width: 2.5; fill: none; }
.slink.on { stroke: #ffd35a; filter: drop-shadow(0 0 5px rgba(255, 211, 90, .55)); }
.comboPlus { fill: #cdb6ff; font-weight: 800; pointer-events: none; }
.shub circle { fill: #17101f; stroke: var(--el, #fff); stroke-width: 3; }
.shub text { pointer-events: none; user-select: none; }
.shub .shubKey { fill: #ffe6b0; font-weight: 800; letter-spacing: .5px; paint-order: stroke; stroke: #0a0603; stroke-width: 3.5px; stroke-linejoin: round; }
.shub.locked circle { opacity: .5; }
.snode circle { fill: #17101f; stroke: var(--el, #fff); stroke-width: 2.5; transition: filter .08s ease; }
.snode text { pointer-events: none; user-select: none; }
.snode.off circle { opacity: .38; }              /* spell not usable yet */
.snode.off text { opacity: .5; }
.snode.open { cursor: pointer; }
.snode.open circle { fill: #241636; filter: drop-shadow(0 0 6px var(--el, #b98cff)); }
.snode.open:hover circle { filter: drop-shadow(0 0 11px var(--el, #b98cff)); }
.snode.on circle { fill: var(--el, #b98cff); stroke: #fff; filter: drop-shadow(0 0 8px var(--el, #b98cff)); }
.snode.blocked { cursor: not-allowed; }          /* already mixing 2 elements — 3rd not allowed */
.snode.blocked circle { opacity: .28; stroke-dasharray: 3 4; }
.snode.blocked text { opacity: .35; }
/* invested-level bubble on an equipped element node (its share of the slot's 10-level pool) */
.snode .snodeLvlBg { fill: #0d0815; stroke: var(--el, #fff); stroke-width: 1.5; opacity: 1 !important; stroke-dasharray: none !important; }
.snode .snodeLvl { fill: #fff; font-weight: 700; opacity: 1 !important; }
/* level icons along a branch (one per level of the slot's shared 10-level pool) */
.snode .hitArea { fill: transparent !important; stroke: none !important; filter: none !important; }
.snode.lvl.open circle:not(.hitArea) { animation: lvlPulse 1.3s ease-in-out infinite; }
@keyframes lvlPulse {
  0%, 100% { filter: drop-shadow(0 0 3px var(--el, #b98cff)); }
  50%      { filter: drop-shadow(0 0 11px var(--el, #b98cff)); }
}
.snode.lvl.reach { cursor: pointer; }               /* buyable in one multi-level jump */
.snode.lvl.reach circle:not(.hitArea) { fill: #1d1229; opacity: .55; }
.snode.lvl.reach text { opacity: .6; }
.snode.lvl.reach:hover circle:not(.hitArea) { opacity: .85; filter: drop-shadow(0 0 7px var(--el, #b98cff)); }
.snode.lvl.mile circle:not(.hitArea) { stroke-width: 3.5; } /* milestone levels (5 & 10) */
/* ---- Path fork (the primary element's branch splits into a branch per path) ---- */
/* faint tinted band framing the opened branch, so the expansion reads at a glance */
.sforkband { fill: color-mix(in srgb, var(--el, #b98cff) 9%, transparent);
  stroke: color-mix(in srgb, var(--el, #b98cff) 34%, transparent); stroke-width: 1.5; }
/* pulsing selection ring around the active path node */
.spathring { fill: none; stroke: var(--el, #b98cff); stroke-width: 2; opacity: .8;
  animation: sringPulse 1.6s ease-in-out infinite; }
@keyframes sringPulse { 0%,100% { opacity: .4; r: 20px; } 50% { opacity: .85; r: 22px; } }
/* the curved limb from the element anchor out to each path node */
.spathbranch { stroke: #2a1c3c; stroke-width: 3.5; fill: none; stroke-linecap: round; }
.spathbranch.on { stroke: var(--el, #b98cff); stroke-width: 5; opacity: .95;
  filter: drop-shadow(0 0 6px var(--el, #b98cff)); }
/* the chosen limb + its lit rail pulse with flowing energy toward the tips */
.spathbranch.flow, .srail.flow { stroke-dasharray: 2 12; animation: sflow 0.9s linear infinite; }
@keyframes sflow { to { stroke-dashoffset: -14; } }
/* ---- FUSION line (a 5+5 slot fused into its pair archetype) ----
   Everything on the line breathes with a slow molten glow, so the fused
   branch reads as the powerful, special thing it is. */
.sfusband { fill: color-mix(in srgb, var(--el, #ffd35a) 12%, transparent);
  stroke: color-mix(in srgb, var(--el, #ffd35a) 55%, transparent); stroke-width: 1.5;
  animation: fusBand 2.2s ease-in-out infinite; }
@keyframes fusBand {
  0%, 100% { filter: drop-shadow(0 0 4px var(--el, #ffd35a)); }
  50%      { filter: drop-shadow(0 0 12px var(--el, #ffd35a)); }
}
.sfuslabel { fill: var(--el, #ffd35a); font-weight: 800; letter-spacing: 1.1px;
  pointer-events: none; user-select: none; filter: drop-shadow(0 0 5px var(--el, #ffd35a)); }
.sedge.fus.on { filter: drop-shadow(0 0 6px var(--el, #ffd35a)); }
.srail.on.fus { stroke-width: 5; opacity: 1; filter: drop-shadow(0 0 6px var(--el, #ffd35a)); }
.shub.fus circle { animation: fusBand 2.2s ease-in-out infinite; }
.snode.fus circle:not(.hitArea) { stroke-width: 3; }
.snode.fus.on circle:not(.hitArea) { animation: fusNode 1.8s ease-in-out infinite; }
@keyframes fusNode {
  0%, 100% { filter: drop-shadow(0 0 5px var(--el, #ffd35a)); }
  50%      { filter: drop-shadow(0 0 14px var(--el, #ffd35a)); }
}
/* the path node (a spell-variant bud on the branch) */
.spathnode { cursor: pointer; }
.spathnode circle { fill: #17101f; stroke: var(--el, #b98cff); stroke-width: 2.5;
  opacity: .5; transition: transform .18s cubic-bezier(.34,1.56,.64,1), filter .18s ease, opacity .18s ease;
  transform-box: fill-box; transform-origin: center; }
.spathnode text { transition: transform .18s cubic-bezier(.34,1.56,.64,1);
  transform-box: fill-box; transform-origin: center; pointer-events: none; user-select: none; }
.spathnode:hover circle { opacity: .95; filter: drop-shadow(0 0 9px var(--el, #b98cff)); transform: scale(1.12); }
.spathnode:hover text { transform: scale(1.12); }
/* the ACTIVE path — it snaps onto the main limb, glowing and enlarged */
.spathnode.on circle { fill: var(--el, #b98cff); stroke: #fff; opacity: 1;
  filter: drop-shadow(0 0 11px var(--el, #b98cff)); transform: scale(1.18); }
.spathnode.on text { transform: scale(1.05); }
/* path name label beside each bud */
.spathlabel { fill: #a8946b; font-weight: 700; pointer-events: none; user-select: none;
  letter-spacing: .2px; }
.spathlabel.on { fill: #fff; filter: drop-shadow(0 0 4px var(--el, #b98cff)); }
/* Absolute overlay pinned to the tree's bottom — hovering never grows the panel.
   Hovering a LOWER branch flips it to the top (`.top`) so it never hides the
   branch being read. */
#spellTip {
  position: absolute; left: 6px; right: 6px; bottom: 6px; z-index: 3; text-align: left;
  background: rgba(10,7,16,.94); border: 1px solid #4a3320; border-radius: 10px;
  padding: 7px 12px; font-size: 13px; line-height: 1.4; pointer-events: none;
}
#spellTip.top { bottom: auto; top: 6px; }
#spellTip .stat { display: block; color: #c7b596; font-size: 12px; margin-top: 2px; }
/* ---- Build-plan guide strip: names the next recommended pick (Pure/Combine
   plan from the first-buy prompt); the tree pulses that node gold below. ---- */
#spellGuide {
  display: flex; align-items: center; gap: 8px; margin-top: 6px; padding: 5px 12px;
  background: rgba(255, 211, 90, .06); border: 1px dashed rgba(255, 211, 90, .38);
  border-radius: 10px; font-size: 12.5px; color: #e4d6ba; min-height: 30px;
}
#spellGuide.hidden { display: none; }
#spellGuide .gChip { color: #ffd35a; font-weight: 700; white-space: nowrap; flex: none; }
#spellGuide .gTxt { flex: 1; min-width: 0; line-height: 1.3; }
#spellGuide .gBtn {
  width: auto; margin: 0; padding: 3px 12px; font-size: 12px; font-weight: 700;
  background: rgba(255, 211, 90, .12); border: 1px solid rgba(255, 211, 90, .5);
  border-radius: 8px; color: #ffd35a; flex: none;
}
#spellGuide .gBtn:hover { background: rgba(255, 211, 90, .25); filter: none; }
#spellGuide .gChange { margin-left: auto; opacity: .7; font-weight: 400; }
#spellGuide .gChange:hover { opacity: 1; }
/* UNPLANNED slot: the strip becomes a beacon nobody misses — solid gold frame
   with a breathing glow, a sheen sweeping across the banner, a wiggling ⚗️ and
   a molten CTA (same visual language as the spendable-tab shimmer). */
#spellGuide.unplanned {
  border-style: solid; border-color: #ffd35a; padding: 8px 14px; font-size: 13.5px;
  background:
    linear-gradient(100deg, transparent 34%, rgba(255,224,130,.13) 46%, rgba(255,224,130,.24) 50%, rgba(255,224,130,.13) 54%, transparent 66%) 0 0 / 250% 100% no-repeat,
    linear-gradient(90deg, rgba(255,211,90,.10), rgba(196,107,255,.15) 55%, rgba(255,211,90,.10));
  animation: gSheen 2.8s linear infinite, gGlow 1.5s ease-in-out infinite;
}
@keyframes gSheen { from { background-position: 125% 0, 0 0; } to { background-position: -125% 0, 0 0; } }
@keyframes gGlow {
  0%, 100% { box-shadow: 0 0 7px -3px rgba(255,211,90,.55); }
  50%      { box-shadow: 0 0 20px -2px rgba(255,211,90,.95); }
}
#spellGuide.unplanned .gChip { font-size: 13px; letter-spacing: .5px; }
#spellGuide.unplanned .gTxt b { color: #ffd35a; }
#spellGuide.unplanned .gWig { display: inline-block; animation: gWig 1.9s ease-in-out infinite; }
@keyframes gWig {
  0%, 100% { transform: rotate(0deg) scale(1); }
  12% { transform: rotate(-14deg) scale(1.15); }
  24% { transform: rotate(11deg) scale(1.15); }
  36% { transform: rotate(-7deg) scale(1.05); }
  48% { transform: rotate(0deg) scale(1); }
}
#spellGuide.unplanned .gBtn.gCta {
  padding: 7px 16px; font-size: 13px; color: #241302; border-color: #ffe6a0;
  background: linear-gradient(180deg, #ffcf3f, #e08a20); cursor: pointer;
  /* glow pulse, NOT a transform pulse — a scaling box never sits still (jitters
     for readers and never counts as "stable" for click automation) */
  animation: gCtaPulse 1.15s ease-in-out infinite;
}
#spellGuide.unplanned .gBtn.gCta:hover { background: linear-gradient(180deg, #ffdf6f, #f09a30); }
@keyframes gCtaPulse {
  0%, 100% { box-shadow: 0 0 6px rgba(255,190,60,.4); }
  50%      { box-shadow: 0 0 18px 2px rgba(255,190,60,.9); }
}
/* the recommended node on the tree — a gold beacon over the element ring
   (doubled class outranks .snode.lvl.open's own lvlPulse animation) */
.snode.snode.guide circle:not(.hitArea) { animation: guideNode 1.1s ease-in-out infinite; }
@keyframes guideNode {
  0%, 100% { filter: drop-shadow(0 0 3px #ffd35a); }
  50%      { filter: drop-shadow(0 0 13px #ffd35a) drop-shadow(0 0 4px #fff); }
}
.spellActions { margin-top: 6px; }
.spellActRow {
  display: flex; align-items: center; gap: 10px;
  background: #191007; border: 1px solid #3a2817; border-radius: 10px; padding: 7px 12px;
}
.spellActRow .sIcon { font-size: 24px; flex: none; }
.spellActRow .sIcon img.pixIco { width: 30px; height: 30px; display: inline-block; vertical-align: middle; image-rendering: pixelated; }
.spellActRow .sInfo { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
/* Charge pips in the shop preview: a lit dot per banked cast (arcane Spiral/Seeker
   Orb). Grows as you invest more arcane depth — a live capacity preview. */
.spellActRow .sCharges { display: flex; gap: 3px; flex: none; align-items: center; padding: 0 2px; }
.spellActRow .sCharges i {
  width: 7px; height: 7px; border-radius: 50%;
  background: #c9a6ff; box-shadow: 0 0 5px rgba(180,120,255,.95);
}
.spellActRow .sName { font-weight: 700; white-space: nowrap; }
.spellActRow .sDesc { font-size: 12px; color: #c7b596; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.spellActRow .buyBtn { width: auto; margin: 0; padding: 9px 15px; font-size: 13px; border-radius: 9px; white-space: nowrap; flex: none; }
.spellActRow .comboTag { font-size: 12px; color: #d6b8ff; font-weight: 600; }
.spellActRow .comboTag.fus { color: var(--el, #ffd35a); text-shadow: 0 0 6px var(--el, #ffd35a); font-weight: 800; }
.spellActRow .buyBtn.fus { border-color: var(--el, #ffd35a); animation: fusSlot 2.2s ease-in-out infinite; }
.spellActRow .owned { font-size: 13px; color: #5ee06a; font-weight: 700; white-space: nowrap; }
.spellActRow .owned.locked { color: #c7b596; }
.spellActRow .owned.maxed { color: #ffcf3f; }
.respecRow { margin-top: 6px; justify-content: space-between; }
/* (Path selection moved onto the tree — the primary branch forks into path
   branches; see .spathnode / .spathbranch above.) */
/* Shop action buttons sit tight to the content — no big top margin. */
#shop #shopReadyBtn { margin-top: 8px; padding: 11px; }
.panel.wide { padding-bottom: 10px; }
.respecBtn {
  width: auto; margin: 0; padding: 8px 13px; font-size: 13px; font-weight: 700; white-space: nowrap;
  background: linear-gradient(180deg, #ff9a6b, #d8632f); color: #2b1005;
}
.respecBtn:disabled { background: #3a2817; color: #7d6a4c; }
.respecNote { font-size: 11px; color: #a8946b; text-align: right; }

/* ---- Marketplace stalls / panels ---- */
/* Horizontal pills (icon beside label) keep the stall row short. */
#stalls { display: flex; gap: 8px; margin: 4px 0 8px; }
.stall {
  flex: 1; width: auto; margin: 0; padding: 8px 10px; border-radius: 10px;
  background: #191007; border: 2px solid #3a2817; color: var(--text);
  display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 8px; font-size: 13px; font-weight: 600;
}
.stall .npc { font-size: 22px; line-height: 1; }
/* Skill-tree stall wears a carved rune glyph (an inline SVG) instead of an emoji. */
.stall .npc-rune { display: inline-flex; }
.stall .npc-rune svg { width: 26px; height: 26px; color: #ffd35a; filter: drop-shadow(0 0 5px rgba(255,193,60,.55)); }
.stall.active .npc-rune svg { color: #ffe39a; }
.stall:hover { background: #221808; }
.stall.active { border-color: var(--accent); background: #2e1f10; box-shadow: 0 0 12px -2px var(--accent); }
/* "you can spend something here" nudge: the closed stall blinks + wears a badge */
.stall { position: relative; }
.stall.nudge { border-color: #ffd35a; animation: stallNudge 1.1s ease-in-out infinite; }
@keyframes stallNudge {
  0%, 100% { box-shadow: 0 0 4px -2px rgba(255, 211, 90, .35); }
  50%      { box-shadow: 0 0 16px 1px rgba(255, 211, 90, .85); }
}
.notifDot {
  position: absolute; top: -7px; right: -6px; min-width: 18px; height: 18px; padding: 0 4px;
  border-radius: 9px; background: linear-gradient(180deg, #ffe14a, #ff9f2f); color: #3a2004;
  font-size: 11px; font-weight: 800; line-height: 18px; text-align: center;
  box-shadow: 0 0 8px rgba(255, 193, 60, .8); pointer-events: none;
  animation: notifPop 1.1s ease-in-out infinite;
}
@keyframes notifPop { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.18); } }
/* clickable hint line under the stalls naming what's waiting in the other tab */
#spendHint {
  display: block; width: 100%; margin: -2px 0 8px; padding: 6px 10px;
  background: rgba(255, 211, 90, .08); border: 1px dashed #b98a2e; border-radius: 9px;
  color: #ffd98a; font-size: 12.5px; font-weight: 600; text-align: center; cursor: pointer;
}
#spendHint:hover { background: rgba(255, 211, 90, .16); }
#spendHint.hidden { display: none; }
.mkPanel { min-height: 40px; }

/* ---- Grimoire (📖 Spells & Skills): a read-only main-menu reference ---- */
/* Header tag is compact; the card grid is a self-contained scroll region so the
   panel itself never scrolls (see menus-no-scrollbars). */
#codex .panel.wide { text-align: left; overflow: hidden; }
#codex .tag { margin: 2px 0 8px; font-size: 12.5px; }
#codexTabs { display: flex; gap: 8px; margin: 0 0 10px; }
.codexTab {
  flex: 1; width: auto; margin: 0; padding: 9px 10px; border-radius: 10px;
  background: #191007; border: 2px solid #3a2817; color: var(--text);
  font-size: 14px; font-weight: 700;
}
.codexTab:hover { background: #221808; }
.codexTab.active { border-color: var(--accent); background: #2e1f10; box-shadow: 0 0 12px -2px var(--accent); }
.codexBody {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(205px, 1fr));
  gap: 10px; align-items: start;
  max-height: min(560px, 66vh); overflow-y: auto;
  margin: 0 -4px; padding: 0 4px 2px;
}
.cxCard {
  background: #191007; border: 1px solid #3a2817; border-left: 3px solid var(--el, var(--accent));
  border-radius: 10px; padding: 9px 11px 4px;
}
.cxHead { display: flex; align-items: center; gap: 8px; }
.cxHead .cxEmoji { font-size: 21px; line-height: 1; }
.cxHead .cxName { font-size: 15px; font-weight: 800; color: var(--el, #fff); }
.cxSub { font-size: 10.5px; color: #9d8b6c; margin: 3px 0 7px; line-height: 1.3; }
.cxRow { display: flex; align-items: flex-start; gap: 8px; padding: 5px 0; border-top: 1px solid #281b0e; }
.cxHead + .cxRow, .cxSub + .cxRow { border-top: none; }
.cxRow .cxKey {
  flex: none; min-width: 20px; height: 20px; margin-top: 1px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  background: #281b0e; border: 1px solid #5c4526; border-bottom-width: 2px; border-radius: 5px;
  font-size: 11px; font-weight: 700; color: #d9c8a4;
}
.cxRow .cxKey.none { visibility: hidden; min-width: 0; width: 0; margin: 0; padding: 0; border: none; }
.cxRow .cxIco { flex: none; font-size: 18px; line-height: 1.2; width: 22px; text-align: center; }
.cxRow .cxIco img.pixIco { width: 20px; height: 20px; display: inline-block; vertical-align: middle; image-rendering: pixelated; }
.cxRow .cxTxt { display: flex; flex-direction: column; gap: 1px; }
.cxRow .cxTxt b { font-size: 12.5px; color: #efe4cb; }
.cxRow .cxTxt span { font-size: 11px; color: #a8946b; line-height: 1.32; }

/* ---- Dead-player in-game shop: the Marketplace overlay reused as a small,
   collapsible corner panel while you're out of the live round. It does NOT dim
   the arena (you keep spectating behind it), so `.overlay` fills/pointer-events
   are neutralized here and only the panel itself is interactive. ---- */
.overlay.deadmode {
  position: fixed; inset: auto auto 92px 12px;
  display: block; align-items: initial; justify-content: initial;
  background: none; padding: 0; z-index: 8; pointer-events: none;
  width: min(440px, 94vw); max-height: 64vh;
}
.overlay.deadmode .panel {
  pointer-events: auto; margin: 0; width: 100%; max-height: 64vh;
  padding: 12px 16px 12px; border-color: #5a3a1e;
  box-shadow: 0 12px 40px rgba(0,0,0,.7), 0 0 0 1px rgba(255,193,60,.25);
}
.overlay.deadmode .panel h1 { font-size: 1.05rem; margin: 2px 0 6px; }
.deadNote { font-size: 12px; color: #ffcf8a; margin: 0 0 8px; line-height: 1.35; }
#shopCollapse {
  width: auto; margin: 0 0 6px; padding: 8px 14px; font-size: 13px; font-weight: 700;
  border-radius: 10px; border: 1px solid #6a4a20; background: #241a10; color: #ffdf9a; cursor: pointer;
}
#shopCollapse:hover { background: #2e2214; }
/* Collapsed: only the toggle pill shows — the panel shrinks to a button. */
.overlay.deadmode.collapsed { max-height: none; width: auto; }
.overlay.deadmode.collapsed .panel { padding: 0; background: none; border: none; box-shadow: none; max-height: none; overflow: visible; }
.overlay.deadmode.collapsed .panel > *:not(#shopCollapse) { display: none !important; }

/* ---- Bounty: a coin badge beside the leading mage's name in the scoreboard. */
#scoreboard .bounty { color: #ffd35a; font-weight: 700; margin-left: 5px; font-size: 11px; white-space: nowrap; text-shadow: 0 0 6px rgba(255,193,60,.5); }

/* per-spell level pips + upgrade button inside each shop card */
.shopCard .lvlpips { font-size: 13px; letter-spacing: 1.5px; white-space: nowrap; }
.shopCard .maxed { color: #ffcf3f; }
.buyBtn.upBtn {
  background: linear-gradient(180deg, #7fe0ff, #38a9d8); color: #05202b; white-space: nowrap;
}
.buyBtn.upBtn:disabled { background: #3a2817; color: #7d6a4c; }
/* an AFFORDABLE level-up gently glows — the "spend me" cue inside the open panel */
.spellActRow .buyBtn.upBtn:not(:disabled) { animation: upGlow 1.4s ease-in-out infinite; }
@keyframes upGlow {
  0%, 100% { box-shadow: 0 0 3px rgba(127, 224, 255, .25); }
  50%      { box-shadow: 0 0 12px rgba(127, 224, 255, .8); }
}

#potionList, #runeList { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* potion size grid inside each Health/Mana group */
.potGroup { display: block; }
.potHead { display: flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 700; margin-bottom: 8px; }
.potHead .sIcon { font-size: 22px; }
.potHead .sDesc { font-weight: 400; }
.potSizes { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.potSize {
  display: flex; align-items: center; gap: 6px;
  background: #201808; border: 1px solid #3a2817; border-radius: 8px; padding: 6px 8px; font-size: 12px;
}
.potSize .psName { font-weight: 600; min-width: 46px; }
.potSize .psRestore { font-weight: 700; }
.potSize .psCount { margin-left: auto; color: #c7b596; }
.potSize .buyBtn { padding: 5px 9px; font-size: 12px; border-radius: 7px;
  background: linear-gradient(180deg, #a06bff, #6e3fd6); color: #fff; width: auto; margin: 0; }
.potSize .buyBtn:disabled { background: #3a2817; color: #7d6a4c; }
.potSize .owned { font-size: 12px; color: #5ee06a; font-weight: 700; margin-left: auto; }

/* ---- in-game potion bar (right of the spell bar so they never overlap) ---- */
#potionBar {
  position: absolute; left: 364px; bottom: 16px;
  display: flex; gap: 8px; pointer-events: auto; flex-wrap: wrap; max-width: 40vw;
}
.potion {
  position: relative; min-width: 56px; height: 44px; padding: 0 10px;
  display: flex; align-items: center; gap: 6px; cursor: pointer;
  background: rgba(10,7,16,.7); border: 1.5px solid #4a3320; border-radius: 9px;
  font-size: 15px; font-weight: 700; overflow: hidden;
}
.potion .pk { position: absolute; top: 1px; left: 4px; font-size: 9px; color: #ffcf3f; }
.potion .pcount { font-size: 13px; }
.potion .pcd {
  position: absolute; inset: 0; background: rgba(0,0,0,.62);
  display: flex; align-items: center; justify-content: center; font-size: 16px; color: #fff;
}

/* locked (unowned) spell slots: hide the spell icon entirely, show only a lock */
.slot.locked { opacity: .6; background: rgba(10,7,16,.5); }
.slot.locked .icon, .slot.locked .elbadge, .slot.locked .mana, .slot.locked .key { visibility: hidden; }
.slot.locked::after {
  content: "🔒"; position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center; font-size: 24px; opacity: .8;
}

/* ---- Buff chips over mages handled on canvas; HUD buff row ---- */
#banner {
  position: absolute; top: 42%; left: 50%; transform: translate(-50%,-50%);
  text-align: center; font-size: 46px; font-weight: 800;
  text-shadow: 0 4px 24px rgba(0,0,0,.8); pointer-events: none;
}
#banner .sub { font-size: 20px; font-weight: 500; color: #ffcf3f; margin-top: 6px; }

/* Dead/spectator overlay: "you're out — watching X" + a rotating gameplay tip */
#deathTips {
  position: absolute; bottom: 15%; left: 50%; transform: translateX(-50%);
  width: min(520px, 88vw); text-align: center; z-index: 9; pointer-events: none;
  background: rgba(10,7,16,.82); border: 1px solid #4a3320; border-radius: 12px;
  padding: 10px 16px; box-shadow: 0 6px 22px rgba(0,0,0,.6);
  animation: dtFade .4s ease both;
}
#deathTips .dtHeadRow { display: flex; align-items: center; justify-content: center; gap: 12px; }
#deathTips .dtHead {
  font-size: 18px; font-weight: 800; color: #ff6a6a;
  text-shadow: 0 2px 8px rgba(0,0,0,.8); letter-spacing: .3px;
}
/* ‹ › switch the death camera between survivors — the banner is pointer-events:none, so re-enable them here */
#deathTips .dtArrow {
  pointer-events: auto; cursor: pointer; flex: none;
  width: 38px; height: 38px; padding: 0; margin: 0; border-radius: 8px;
  border: 1px solid #6a4a2a; background: rgba(40,26,14,.9); color: #ffcf3f;
  font-size: 22px; font-weight: 800; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  transition: background .12s ease, transform .12s ease, border-color .12s ease;
}
#deathTips .dtArrow:hover { background: rgba(74,51,32,.98); border-color: #ffcf3f; transform: scale(1.08); }
#deathTips .dtArrow:active { transform: scale(.92); }
#deathTips .dtTip { margin-top: 6px; font-size: 13px; line-height: 1.4; color: #efe4cb; }
#deathTips .dtLabel { color: #ffcf3f; font-weight: 700; margin-right: 4px; }
#deathTips .dtHint { margin-top: 5px; font-size: 11px; color: #b39c74; letter-spacing: .3px; }

/* Live performance HUD (F3 / ?perf) — sits below the wallet pill (top-left). */
#perfHud {
  position: fixed; top: 46px; left: 8px; z-index: 40; pointer-events: none;
  font: 11px/1.5 ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  color: #b6f0c0; background: rgba(6,10,8,.82); border: 1px solid #1f6b3a;
  border-radius: 8px; padding: 7px 10px; white-space: pre; letter-spacing: .2px;
  text-shadow: 0 1px 2px #000; min-width: 168px;
}
#perfHud b { color: #eafff0; font-weight: 700; }
#perfHud .warn { color: #ffcf3f; }
#perfHud .bad { color: #ff6a6a; }
@keyframes dtFade { from { opacity: 0; transform: translateX(-50%) translateY(8px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
@media (max-height: 460px) { #deathTips { bottom: 8%; padding: 7px 12px; } #deathTips .dtHead { font-size: 15px; } #deathTips .dtTip { font-size: 12px; } }

/* mid-width screens: 2-column spell grid (3-up needs a roomy window) */
@media (max-width: 900px) {
  #shopList { grid-template-columns: 1fr 1fr; }
  .passCards { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  h1 { font-size: 26px; }
  h1.small { font-size: 21px; }
  .tag { font-size: 13px; margin-bottom: 14px; }
  .panel { padding: 18px 16px 16px; }
  /* 16px inputs stop iOS from auto-zooming the page on focus */
  input { font-size: 16px; }
  button { padding: 14px; font-size: 16px; }
  .createRow button { padding: 0 14px; }
  #phaseInfo { font-size: 12px; padding: 6px 9px; }
  #scoreboard { font-size: 11px; min-width: 108px; padding: 6px 9px; }
  #topbar { padding: 0 10px; }
  #banner { font-size: 30px; }
  #banner .sub { font-size: 15px; }
  /* stack shop/potion cards one-per-row so they're readable on a phone */
  #shopList, #potionList, #runeList, .passCards { grid-template-columns: 1fr; }
  /* the two-column layouts stack on narrow phones */
  #optionsBody { flex-direction: column; gap: 8px; }
  .lobbyBody { grid-template-columns: 1fr; }
  #lobbyList { max-height: 30vh; }
  .elCard { flex-basis: 78px; min-width: 78px; }
  #serverList { max-height: 42vh; }
  #lobbyInvite .qr { width: 156px; height: 156px; }
  #shopCountdown { font-size: 22px; }
  .stall .npc { font-size: 22px; }
}

/* short screens (landscape phones): tighten vertical space, drop extras */
@media (max-height: 520px) {
  .panel { padding: 14px 16px; }
  h1 { font-size: 22px; margin-bottom: 2px; }
  .tag { margin-bottom: 10px; }
  .controls { display: none; }        /* keyboard help isn't worth the height */
  #lobbyInvite .qr { width: 120px; height: 120px; }
  #lobbyInvite { padding: 10px; }
}

/* ---- Kill feed (recent knockouts, top-left under the phase pill) ---- */
#killFeed {
  position: absolute; top: 58px; left: 16px;
  display: flex; flex-direction: column; gap: 5px;
  max-width: 46vw; pointer-events: none;
}
#killFeed .kfRow {
  background: rgba(10,7,16,.66); border: 1px solid #4a3320; border-left: 3px solid #ff6a2f;
  border-radius: 8px; padding: 4px 10px; font-size: 13px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  animation: kfIn .18s ease-out; transition: opacity .8s ease;
}
#killFeed .kfRow.fade { opacity: 0; }
#killFeed .kfIc { margin-right: 6px; }
@keyframes kfIn { from { transform: translateX(-16px); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---- Text chat (Global / Session tabs, collapsible; bottom-left) ---- */
/* Body-level (not inside #hud) so it can layer ABOVE the ready-up lobby & shop
   overlays. z-index 15 sits over those (z-index 10) but under the pause menu
   (#escMenu, 30) and audio controls (40). */
#chatPanel {
  position: fixed; left: 12px; bottom: 12px; z-index: 15;
  width: min(340px, 42vw); pointer-events: auto;
  display: none; flex-direction: column;
  font-size: 13px; touch-action: auto;
}
/* Shown whenever we're in a room (the HUD is up) — lobby, shop and match alike —
   but hidden behind the full-screen modals that cover the arena. */
body:has(#hud:not(.hidden)) #chatPanel { display: flex; }
body:has(#escMenu:not(.hidden)) #chatPanel,
body:has(#options:not(.hidden)) #chatPanel,
body:has(#codex:not(.hidden)) #chatPanel,
body:has(#confirmModal:not(.hidden)) #chatPanel { display: none; }
#chatBar {
  display: flex; align-items: stretch;
  background: rgba(10,7,16,.82); border: 1px solid #4a3320; border-bottom: none;
  border-radius: 10px 10px 0 0; padding: 3px 4px 0;
  backdrop-filter: blur(2px);
}
#chatPanel.collapsed #chatBar { border-radius: 10px; border-bottom: 1px solid #4a3320; padding: 3px 4px; }
.chatTabs { display: flex; gap: 3px; flex: 1; }
.chatTab {
  width: auto; margin: 0; padding: 4px 13px; border: none; border-radius: 7px 7px 0 0;
  background: transparent; color: #b39c74; font-weight: 700; font-size: 12.5px;
  cursor: pointer; position: relative; line-height: 1.3;
}
.chatTab:hover { color: #ffcf3f; }
.chatTab.active { background: rgba(74,51,32,.55); color: #ffcf3f; }
#chatPanel.collapsed .chatTab.active { background: transparent; }
.chatTab .unread {
  position: absolute; top: -2px; right: -1px; min-width: 15px; height: 15px;
  padding: 0 4px; border-radius: 8px; background: #ff6a2f; color: #fff;
  font-size: 10px; line-height: 15px; text-align: center; font-weight: 800;
  box-shadow: 0 1px 3px rgba(0,0,0,.5); box-sizing: border-box;
}
#chatToggle {
  width: auto; margin: 0; padding: 0 9px; background: none; border: none;
  color: #b39c74; font-size: 13px; cursor: pointer; align-self: center;
}
#chatToggle:hover { color: #ffcf3f; }
#chatBody {
  background: rgba(10,7,16,.82); border: 1px solid #4a3320; border-top: none;
  border-radius: 0 0 10px 10px; display: flex; flex-direction: column;
  backdrop-filter: blur(2px);
}
#chatPanel.collapsed #chatBody { display: none; }
#chatLog {
  height: 168px; overflow-y: auto; overflow-x: hidden; padding: 6px 8px;
  display: flex; flex-direction: column; gap: 3px;
  overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: #4a3320 transparent;
}
#chatLog::-webkit-scrollbar { width: 7px; }
#chatLog::-webkit-scrollbar-thumb { background: #4a3320; border-radius: 4px; }
#chatLog::-webkit-scrollbar-track { background: transparent; }
.chatMsg { line-height: 1.35; overflow-wrap: anywhere; color: #efe4cb; }
.chatMsg .cn { font-weight: 700; margin-right: 5px; }
.chatMsg.mine { color: #fff; }
.chatSys { color: #9fe8ff; opacity: .72; font-style: italic; font-size: 12px; }
.chatEmpty { color: #7c6a4c; font-style: italic; text-align: center; padding: 8px 0; }
#chatInput {
  margin: 0; border: none; border-top: 1px solid #4a3320;
  border-radius: 0 0 10px 10px; background: rgba(0,0,0,.28);
  color: #fff; padding: 7px 9px; font-size: 13px; width: 100%; box-sizing: border-box;
}
#chatInput:focus { outline: none; background: rgba(0,0,0,.44); }
#chatInput::placeholder { color: #7c6a4c; }
/* Lift clear of the training controls (bottom-left) when they're on screen. */
body:has(#trainCtl:not(.hidden)) #chatPanel { bottom: 62px; }
@media (max-width: 680px), (max-height: 540px) {
  #chatPanel { width: min(260px, 62vw); font-size: 12px; }
  #chatLog { height: 118px; }
}

/* ================= Friends panel (right edge, collapsible) ================= */
/* Shown only for signed-in, non-guest accounts (JS toggles body.signedIn), and
   hidden behind the full-screen menus/modals that own the whole screen. Sits
   just below the top-right audio controls; layers over the menu and lobby
   (empty corner there) but is hidden during the shop/town/match and the Cash
   Shop so it never renders on top of the HUD or town — its z-index (16) sits
   above the in-game HUD (z5) and the .overlay backdrops (z10). */
#friendsPanel {
  position: fixed; top: 52px; right: 12px; z-index: 16;
  width: min(248px, 66vw); pointer-events: auto;
  display: none; flex-direction: column;
  font-size: 13px; touch-action: auto;
}
body.signedIn #friendsPanel { display: flex; }
body:has(#welcome:not(.hidden)) #friendsPanel,
body:has(#charEditor:not(.hidden)) #friendsPanel,
body:has(#options:not(.hidden)) #friendsPanel,
body:has(#codex:not(.hidden)) #friendsPanel,
body:has(#reportOverlay:not(.hidden)) #friendsPanel,
body:has(#escMenu:not(.hidden)) #friendsPanel,
body:has(#confirmModal:not(.hidden)) #friendsPanel,
body:has(#planModal:not(.hidden)) #friendsPanel,
body:has(#cashShop:not(.hidden)) #friendsPanel,
/* In-match: #hud is un-hidden for the whole session (town + shop + combat),
   #townHud/#shop cover the specific phases — hide friends over all of them so
   the panel never lands on top of the HUD or the walkable town. */
body:has(#hud:not(.hidden)) #friendsPanel,
body:has(#townHud:not(.hidden)) #friendsPanel,
body:has(#shop:not(.hidden)) #friendsPanel { display: none !important; }

#friendsBar {
  display: flex; align-items: stretch;
  background: rgba(10,7,16,.85); border: 1px solid #4a3320; border-bottom: none;
  border-radius: 10px 10px 0 0; padding: 2px 4px 0;
  backdrop-filter: blur(2px);
}
#friendsPanel.collapsed #friendsBar { border-radius: 10px; border-bottom: 1px solid #4a3320; padding: 3px 4px; }
#friendsToggleBtn {
  flex: 1; display: flex; align-items: center; gap: 6px; width: auto; margin: 0;
  padding: 5px 8px; border: none; background: transparent; color: #ffcf3f;
  font-weight: 800; font-size: 12.5px; cursor: pointer; position: relative; text-align: left;
}
#friendsToggleBtn:hover { color: #ffe08a; }
.fpIcon { font-size: 14px; }
.fpTitle { flex: 1; }
.fpBadge {
  min-width: 17px; height: 17px; padding: 0 5px; border-radius: 9px;
  background: #2c8a3e; color: #eaffe9; font-size: 10.5px; line-height: 17px;
  text-align: center; font-weight: 800; box-sizing: border-box;
  box-shadow: 0 0 0 1px rgba(0,0,0,.35);
}
.fpBadge.hidden { display: none; }
#friendsToggle {
  width: auto; margin: 0; padding: 0 9px; background: none; border: none;
  color: #b39c74; font-size: 13px; cursor: pointer; align-self: center;
}
#friendsToggle:hover { color: #ffcf3f; }

#friendsBody {
  background: rgba(10,7,16,.85); border: 1px solid #4a3320; border-top: none;
  border-radius: 0 0 10px 10px; display: flex; flex-direction: column;
  backdrop-filter: blur(2px); padding: 7px;
}
#friendsPanel.collapsed #friendsBody { display: none; }

.fpAddRow { display: flex; gap: 5px; }
#friendAddInput {
  flex: 1; min-width: 0; margin: 0; border: 1px solid #4a3320; border-radius: 7px;
  background: rgba(0,0,0,.3); color: #fff; padding: 6px 8px; font-size: 12.5px; box-sizing: border-box;
}
#friendAddInput:focus { outline: none; border-color: #7a5a30; background: rgba(0,0,0,.45); }
#friendAddInput::placeholder { color: #7c6a4c; }
#friendAddBtn {
  width: auto; margin: 0; padding: 6px 12px; border: none; border-radius: 7px;
  background: linear-gradient(#c8822e,#9a5a1e); color: #fff; font-weight: 800;
  font-size: 12.5px; cursor: pointer; flex: none;
}
#friendAddBtn:hover { filter: brightness(1.12); }
#friendAddBtn:disabled { opacity: .5; cursor: default; filter: none; }

.fpStatus { margin: 5px 1px 0; font-size: 11.5px; color: #b39c74; line-height: 1.3; }
.fpStatus:empty { display: none; }
.fpStatus.ok { color: #7fe08a; }
.fpStatus.err { color: #ff9a6a; }

#friendsScroll {
  margin-top: 6px; max-height: 46vh; overflow-y: auto; overflow-x: hidden;
  overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: #4a3320 transparent;
}
#friendsScroll::-webkit-scrollbar { width: 7px; }
#friendsScroll::-webkit-scrollbar-thumb { background: #4a3320; border-radius: 4px; }
#friendsScroll::-webkit-scrollbar-track { background: transparent; }

.fpSectionHd {
  color: #9a835e; font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em; padding: 4px 2px 3px;
}
.fpEmpty { color: #7c6a4c; font-style: italic; font-size: 12px; text-align: center; padding: 8px 4px; }

.friendRow { display: flex; align-items: center; gap: 7px; padding: 5px 6px; border-radius: 7px; }
.friendRow:hover { background: rgba(74,51,32,.32); }
.fpDot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: #5c5142; }
.friendRow.online .fpDot { background: #57d873; box-shadow: 0 0 6px #57d873; }
.fpName { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #d9cbaa; font-weight: 600; }
.friendRow.online .fpName { color: #f3ead2; }
.fpTag { font-size: 10.5px; color: #8a7856; flex: none; }

.fpBtns { display: flex; gap: 4px; flex: none; }
.fpMini {
  width: auto; margin: 0; padding: 3px 7px; border: none; border-radius: 6px;
  font-size: 11px; font-weight: 800; cursor: pointer; line-height: 1.2;
}
.fpAccept { background: #2c8a3e; color: #eaffe9; }
.fpAccept:hover { filter: brightness(1.15); }
.fpDecline, .fpRemove { background: rgba(74,51,32,.6); color: #c9b184; }
.fpDecline:hover, .fpRemove:hover { background: #7a3226; color: #ffd9c9; }
.fpRemove { opacity: 0; transition: opacity .12s; font-size: 12px; padding: 2px 7px; }
.friendRow:hover .fpRemove { opacity: 1; }

/* Glow pulse when a friend comes online (row), plus an attention flash on the
   collapsed bar so you notice even when the panel is folded. */
@keyframes fpOnlineGlow {
  0% { background: rgba(60,190,90,.42); box-shadow: inset 0 0 0 1px rgba(90,220,120,.7); }
  100% { background: transparent; box-shadow: none; }
}
.friendRow.justOnline { animation: fpOnlineGlow 2.4s ease-out; }
@keyframes fpBarFlash {
  0%,100% { box-shadow: 0 0 0 rgba(90,220,120,0); }
  50% { box-shadow: 0 0 12px 1px rgba(90,220,120,.85); }
}
#friendsPanel.flash #friendsBar { animation: fpBarFlash 1s ease-in-out 2; border-color: #57d873; }

@media (max-width: 680px), (max-height: 540px) {
  #friendsPanel { width: min(210px, 60vw); font-size: 12px; top: 48px; }
}

/* ---- End-of-match MVP card (center) ---- */
#mvp {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  z-index: 6; pointer-events: auto;
}
.mvpCard {
  background: rgba(16,11,6,.94); border: 1px solid #6a4a28; border-radius: 16px;
  padding: 18px 26px 20px; text-align: center; min-width: 300px;
  box-shadow: 0 18px 60px rgba(0,0,0,.6), 0 0 0 4px rgba(255,207,63,.08);
  animation: mvpIn .3s cubic-bezier(.2,1.3,.5,1);
}
@keyframes mvpIn { from { transform: scale(.8); opacity: 0; } to { transform: none; opacity: 1; } }
.mvpHead { font-size: 15px; font-weight: 700; color: #ffcf3f; letter-spacing: .5px; }
.mvpBody { display: flex; flex-direction: column; align-items: center; gap: 4px; margin: 10px 0 14px; }
.mvpAv { width: 76px; height: 76px; image-rendering: auto; filter: drop-shadow(0 6px 10px rgba(0,0,0,.5)); }
.mvpName { font-size: 22px; font-weight: 800; }
.mvpStats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.mvpStats > div { display: flex; flex-direction: column; gap: 2px; }
.mvpStats b { font-size: 20px; color: #fff; }
.mvpStats span { font-size: 10px; color: #c7b596; text-transform: uppercase; letter-spacing: .4px; }
.mvpBtns { display: flex; gap: 8px; justify-content: center; margin-top: 14px; }
.mvpBtns:empty { display: none; }
.mvpBtns button {
  pointer-events: auto; padding: 8px 14px; font-size: 13px; border-radius: 9px;
  border: 1px solid #6a4a28; background: rgba(48,34,18,.9); color: #eee; cursor: pointer;
}
.mvpBtns button:hover { background: rgba(64,46,22,.95); }
@media (max-width: 640px) {
  .mvpCard { min-width: 0; width: 88vw; padding: 14px 16px 16px; }
  .mvpStats { gap: 6px; }
  .mvpStats b { font-size: 16px; }
  #killFeed .kfRow { font-size: 11px; }
}

/* ---- Menu profile panel (lifetime stats + leaderboard) ---- */
#profilePanel {
  margin: 10px 0 2px; padding: 10px 12px;
  background: rgba(10,7,16,.5); border: 1px solid #3a2817; border-radius: 10px;
}
.ppMine { display: flex; flex-wrap: wrap; gap: 10px; align-items: baseline; justify-content: center; }
.ppMine .ppLvl { font-weight: 800; color: #ffcf3f; font-size: 15px; }
.ppMine .ppStat { font-size: 12px; color: #c7b596; }
.ppMine .ppStat b { color: #fff; font-size: 14px; margin-right: 3px; }
.ppBoardHead { margin: 10px 0 5px; font-size: 12px; font-weight: 700; color: #ffcf3f; text-align: center; }
.ppBoard { list-style: none; counter-reset: rank; margin: 0; padding: 0; }
.ppBoard li {
  counter-increment: rank; display: flex; justify-content: space-between; gap: 8px;
  padding: 3px 6px; border-radius: 6px; font-size: 13px;
}
.ppBoard li::before { content: counter(rank) "."; color: #8d7a58; margin-right: 6px; }
.ppBoard li.mine { background: rgba(255,207,63,.12); }
.ppBoard .ppName { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ppBoard .ppWins { color: #c7b596; white-space: nowrap; }

/* ---- Invite copy button + bot hint (lobby) ---- */
.copyInvite {
  margin-top: 10px; padding: 9px 14px; font-size: 14px; border-radius: 9px;
  border: 1px solid #6a4a28; background: rgba(48,34,18,.9); color: #eee; cursor: pointer;
}
.copyInvite:hover { background: rgba(64,46,22,.95); }
#botHint {
  margin: 8px 0 0; padding: 8px 12px; font-size: 13px; line-height: 1.35;
  color: #ffd9a8; background: rgba(60,40,16,.5); border: 1px dashed #7a5a30; border-radius: 9px;
}

/* ===================== Marketplace town (shop phase) =====================
   The between-rounds shop is a walkable canvas scene (src/town.js). The #shop
   overlay reappears as `.townpanel` — a centered stall panel over the dimmed
   town — and #townHud carries the gold/countdown/ready chrome. Dead-shop and
   Quick keep the classic overlay untouched. */
.overlay.townpanel { background: rgba(6, 4, 14, 0.45); }
.overlay.townpanel .panel {
  width: min(880px, 94vw); max-height: 92vh; max-height: 92svh; overflow-y: auto;
  border-color: #5a3a1e;
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.65), 0 0 0 1px rgba(255, 193, 60, 0.22);
}
/* the town replaces the tab strip + shop-phase chrome; #townHud owns them now */
.overlay.townpanel .panel > h1.small,
.overlay.townpanel .shopTop,
.overlay.townpanel #stalls,
.overlay.townpanel #spendHint,
.overlay.townpanel #shopReadyBtn,
.overlay.townpanel #shopStartBtn,
.overlay.townpanel #shopStatus { display: none !important; }

#townHud {
  position: fixed; top: 10px; left: 50%; transform: translateX(-50%);
  z-index: 7; display: flex; flex-direction: column; align-items: center; gap: 6px;
  pointer-events: none; max-width: 96vw;
}
#townHud .thRow { display: flex; align-items: center; gap: 8px; pointer-events: auto; flex-wrap: wrap; justify-content: center; }
#townHud .thChip {
  background: rgba(16, 10, 6, 0.85); border: 1px solid #5c4526; border-radius: 999px;
  padding: 6px 13px; font-size: 13px; color: var(--text); white-space: nowrap;
}
#townHud .thChip b { color: #ffcf3f; }
#townHud .thChip.xpChip { display: inline-flex; align-items: center; gap: 6px; }
#townHud .thChip.xpChip b { color: #ffd94a; }
#townHud #townCountdown { color: #ffcf3f; font-weight: 700; }
#townHud #townCountdown.urgent { color: #ff5a5a; animation: countPulse 0.6s ease-in-out infinite; }
#townHud button { /* beware the base button { width:100% } */
  width: auto; margin: 0; padding: 7px 16px; font-size: 14px; border-radius: 999px;
}
#townHud .hint { pointer-events: none; font-size: 12px; color: #d4c4a4; border-style: dashed; }

/* town mode: the match HUD stays for phase/scoreboard, but combat chrome goes */
body.townmode #spellbar,
body.townmode #selfBars,
body.townmode #statusBar,
body.townmode #killFeed { display: none !important; }

/* ---- Alchemist / Armory stall panels (town-only) ---- */
#alchBody, #armoryBody { text-align: left; }
.stallNote { font-size: 13px; color: #d4c4a4; margin: 2px 0 10px; line-height: 1.4; }
.stallNote.empty { color: #9d8b6c; font-style: italic; }
.stallRow {
  display: flex; align-items: center; gap: 10px; margin: 8px 0;
  background: rgba(24, 16, 8, 0.55); border: 1px solid #3a2a14; border-radius: 10px;
  padding: 9px 12px;
}
.stallRow .stallIc { font-size: 22px; flex: none; }
.stallRow .stallTxt { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.stallRow .stallTxt b { font-size: 14px; }
.stallRow .stallTxt span { font-size: 12px; color: #c4b190; }
.stallRow button { width: auto; margin: 0; padding: 8px 14px; font-size: 13px; flex: none; }
.stallRow .ghostBtn { background: transparent; border: 1px solid #5c4526; color: var(--text); }
.stallRow .ghostBtn:hover { background: #281b0e; }
.stallRow.saveRow { background: none; border-style: dashed; }
.stallRow .stallHintTxt { font-size: 13px; color: #c4b190; letter-spacing: 1px; }
/* dashed section rule between shop groups (generic; #outfitShop tweaks its margins) */
.stallDivide { border: none; border-top: 1px dashed #3a2a14; margin: 12px 0 8px; }
/* "Coming soon" WIP rows/panels: dimmed so they read as not-yet-buyable */
.stallRow.csRow { opacity: 0.6; }
.comingSoon {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 48px 20px; text-align: center; opacity: 0.85;
}
.comingSoon .csIcon { font-size: 46px; filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5)); }
.comingSoon p { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: 0.5px; color: #f5edd8; }
/* Saved-build shelf (armory): 2-up + vh-capped self-contained scroll, so six
   presets can't push the panel past the townpanel's 92vh (menus: no scrollbars
   on the panel itself). */
#armoryBody .presetList {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
  max-height: 24vh; overflow-y: auto;
}
#armoryBody .presetList .stallRow { margin: 0; }
@media (max-width: 900px) { #armoryBody .presetList { grid-template-columns: 1fr; } }
/* Short viewports (≈720p): tighten the stall panels so the armory (the tallest —
   purse + 2 outfit rows + presets + save row) still clears the 92vh cap. */
@media (max-height: 800px) {
  #armoryBody .presetList { max-height: 16vh; }
  #outfitShop .staffCard, #weaponsBody .staffCard { padding: 5px 8px; }
  #armoryBody .stallNote, #weaponsBody .stallNote { margin: 2px 0 6px; }
}

/* ---- Weaponsmith stall (weapon skins; own #weaponsBody panel, its own town rack) ---- */
#weaponsBody .staffGrid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; } /* 14 cards → 3 rows in the 1160px panel */
.staffCard { /* base button{width:100%} is fine inside a grid cell */
  display: flex; align-items: center; flex-wrap: wrap; row-gap: 3px; gap: 8px; margin: 0;
  background: rgba(24, 16, 8, 0.55); border: 1px solid #3a2a14; border-radius: 10px;
  padding: 7px 10px; font-size: 12px; cursor: pointer; text-align: left;
}
.staffCard:hover { border-color: var(--stc, #8a6a3a); }
.staffCard img { width: 58px; height: 19px; object-fit: contain; flex: none; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.5)); }
.staffCard .staffBranchIc { width: 58px; font-size: 18px; text-align: center; flex: none; }
.staffCard .staffName { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.staffCard .staffStat { flex-basis: 100%; font-size: 10px; line-height: 1.25; color: #a89a78; white-space: normal; }
.staffCard .staffState { flex: none; font-size: 11px; color: #c4b190; }
.staffCard .staffState.buy { color: #ffcf3f; font-weight: 700; }
.staffCard.equipped { border-color: #ffd94a; box-shadow: 0 0 9px rgba(255, 217, 74, 0.3) inset; }
.staffCard.equipped .staffState { color: #ffd94a; }
.staffCard.locked { opacity: 0.5; cursor: default; }
/* ---- Dual price tags: 🪙 gold (this game) vs 💵 cash (account-forever). The
   cash tag's treasure PNG grows with the price (cash1 bill → cash6 briefcase). */
.staffCard .staffState .priceTag {
  display: inline-flex; align-items: center; gap: 3px; margin-left: 5px;
  padding: 2px 7px; border-radius: 8px; font-size: 11px; font-weight: 700;
  background: rgba(40, 28, 12, 0.8); border: 1px solid #5a4420; color: #ffcf3f;
}
.staffCard .staffState .priceTag.cashTag { color: #8fe89a; border-color: #3f5a2a; }
.staffCard .staffState .priceTag:hover { border-color: #ffd94a; }
.staffCard .staffState .priceTag.cashTag:hover { border-color: #8fe89a; }
.staffCard .staffState .priceTag.broke { opacity: 0.45; }
.staffCard .staffState .priceTag img { width: 20px; height: 16px; object-fit: contain; object-position: center; filter: none; } /* fixed box: the treasure PNGs vary 1.03–1.85 aspect, so `contain` letterboxes each into the same footprint & centers it (beats the 58×19 staff-art rule) */
.stallNote.purse { font-size: 14px; margin-bottom: 6px; }
.stallNote.purse .goldBal { color: #ffd94a; font-weight: 700; }
.stallNote.purse .cashBal { color: #8fe89a; font-weight: 700; }
.stallNote.purse .purseHint { display: block; font-size: 11px; color: #9d8b6c; margin-top: 2px; }
@media (max-width: 900px) { #weaponsBody .staffGrid { grid-template-columns: repeat(2, 1fr); } }

/* ---- 💵 Cash Shop: treasure top-up packs (CraftPix Treasure-Shop art). Three
   tiers tuned for the DECOY EFFECT — the mid pack is priced just under the big
   one, so the highlighted BEST-VALUE pack (amber glow + ribbon + bonus starburst
   + struck promo price) reads as the obvious deal. ---- */
#cashShop .panel.wide { width: min(640px, 95vw); }
.csGrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-top: 14px; align-items: stretch; }
.csCard {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 14px 10px 12px; text-align: center;
  background: linear-gradient(#2a1e12, #1b130b);
  border: 2px solid #4a3418; border-radius: 12px;
  box-shadow: 0 4px 14px rgba(0,0,0,.35);
}
/* Best-value pack: amber glow + a slight lift so the eye lands here. */
.csCard.best {
  border-color: #ffb43a;
  background: linear-gradient(#3a2a12, #221708);
  box-shadow: 0 0 0 1px rgba(255,180,58,.5), 0 6px 22px rgba(255,150,40,.3);
  transform: translateY(-4px);
}
.csArt { height: 92px; display: flex; align-items: flex-end; justify-content: center; margin-top: 6px; }
.csArt img { max-height: 92px; max-width: 100%; object-fit: contain; filter: drop-shadow(0 3px 5px rgba(0,0,0,.5)); }
.csCard.best .csArt { height: 106px; }
.csCard.best .csArt img { max-height: 106px; }
.csAmount {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 18px; font-weight: 900; color: #ffe6a0; letter-spacing: .3px;
}
.csAmount .csCoin { width: 20px; height: 16px; object-fit: contain; }
.csCard.best .csAmount { font-size: 20px; color: #ffd66b; }
.csPrice { display: inline-flex; align-items: baseline; gap: 6px; font-size: 15px; font-weight: 800; color: #cbb98f; }
.csPrice b { color: #f5edd8; font-size: 16px; }
.csCard.best .csPrice b { color: #ffe08a; }
.csWas { color: #b46262; font-size: 12px; font-weight: 700; text-decoration: line-through; text-decoration-thickness: 2px; }
.csCard button.csBuy {
  width: 100%; margin-top: 8px; padding: 10px 8px;
  font-size: 15px; font-weight: 800; color: #12240f;
  background: linear-gradient(#8fe89a, #4bbf5f); border: 2px solid #2e7a3e; border-radius: 10px;
  box-shadow: 0 2px 0 #216030, 0 3px 6px rgba(0,0,0,.3);
  cursor: pointer; text-shadow: 0 1px 0 rgba(255,255,255,.3); transition: filter .1s, transform .06s;
}
.csCard button.csBuy:hover { filter: brightness(1.08); }
.csCard button.csBuy:active { transform: translateY(2px); box-shadow: 0 0 0 #216030, 0 1px 3px rgba(0,0,0,.3); }
/* "BEST VALUE" ribbon across the top of the winning card. */
.csRibbon {
  position: absolute; top: -11px; left: 50%; transform: translateX(-50%);
  padding: 3px 12px; font-size: 11px; font-weight: 900; letter-spacing: .6px; white-space: nowrap;
  color: #3a1e04; background: linear-gradient(#ffe07a, #ffab2e);
  border: 1.5px solid #b06a12; border-radius: 20px; box-shadow: 0 2px 6px rgba(0,0,0,.4);
}
/* "+40% BONUS" gold starburst badge (Badges.png) in the top-right corner. */
.csBonus {
  position: absolute; top: -14px; right: -12px; width: 58px; height: 58px; z-index: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1;
  background: url("assets/cashshop/bonus.png") center/contain no-repeat;
  transform: rotate(12deg); filter: drop-shadow(0 2px 3px rgba(0,0,0,.45));
  color: #5a2e00; text-shadow: 0 1px 0 rgba(255,255,255,.35);
}
.csBonus b { font-size: 15px; font-weight: 900; }
.csBonus small { font-size: 8px; font-weight: 800; letter-spacing: .5px; }
@media (max-width: 560px) {
  .csGrid { grid-template-columns: 1fr; gap: 18px; }
  .csCard.best { transform: none; }
  .csBonus { right: 4px; }
}
#renameModal .welcomeName { text-align: left; margin: 4px 0 2px; }
#renameModal #renameInput { width: 100%; }

/* 🧙 editor "Change Name" — premium action button, 🔒 badge when unaffordable. */
#charEdNameActions { margin-top: 8px; }
.premiumBtn { position: relative; display: inline-flex; align-items: center; gap: 6px; }
.premiumBtn.locked { opacity: .88; border-color: #7a5a2a; }
.premiumBtn .btnLock { font-size: 12px; line-height: 1; filter: drop-shadow(0 1px 1px #000); }

/* ---- Armory outfit rack (armor skins; #outfitShop sits between staves & presets) ---- */
#outfitShop .staffGrid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; } /* 12 cards (tunic + o1–o11) → 2 rows in the 1160px panel */
.staffCard img.outfitAv { width: 30px; height: 34px; object-fit: contain; image-rendering: pixelated; } /* upright portrait, not a lying staff */
#outfitShop .staffBranchIc { width: 30px; }
#outfitShop .stallDivide { border: none; border-top: 1px dashed #3a2a14; margin: 12px 0 8px; }
@media (max-width: 900px) { #outfitShop .staffGrid { grid-template-columns: repeat(2, 1fr); } }

/* ---- Fitting room (armory + weaponsmith): square live preview of YOUR mage
   (sticky, left of the rack) wearing the equipped staff + outfit; hovering a
   card tries it on. Same bronze-frame card as the spell diorama. Shared by both
   town stalls, so it's classed — only one stall panel is ever open at a time. -- */
.armoryWrap { display: flex; gap: 14px; align-items: flex-start; }
#armoryBody, #weaponsBody { flex: 1; min-width: 0; }
.armoryPreview {
  flex: none; width: 236px; position: sticky; top: 0;
  padding: 8px; border: 1px solid #4a3320; border-radius: 14px;
  background:
    radial-gradient(120% 90% at 50% 30%, rgba(120, 64, 28, .18), transparent 70%),
    linear-gradient(180deg, #17100a, #0b0710);
}
/* beats the global `canvas { position: fixed; inset: 0 }` for in-panel canvases */
.armoryPrevCv {
  position: static; inset: auto; display: block; width: 100%; aspect-ratio: 1; height: auto;
  cursor: default; border: 1px solid #3a2a14; border-radius: 10px;
  background: radial-gradient(90% 70% at 50% 78%, rgba(120, 84, 40, .22), transparent 65%), rgba(10, 6, 3, 0.55);
  image-rendering: pixelated;
}
.armoryPrevCap { margin-top: 7px; font-size: 12px; line-height: 1.45; color: #d4c4a4; text-align: center; }
.armoryPrevCap b { color: var(--text); }
.armoryPrevHint { margin: 5px 0 0; font-size: 10.5px; color: #9d8b6c; text-align: center; line-height: 1.35; }
.overlay.deadmode .armoryPreview { display: none; }
@media (max-width: 900px) {
  .armoryWrap { flex-direction: column; align-items: center; }
  .armoryPreview { position: static; width: 200px; }
  #armoryBody, #weaponsBody { width: 100%; }
}
