:root{
  --gold:#c8a24a; --goldhi:#f2d688; --golddim:#7a6430;
  --ink:#e8dfc8; --muted:#9d947c;
  --panel1:#3b3a30; --panel2:#191813; --edge:#5c5744;
  --hp:#18c018; --mana:#3a5fd9; --xp:#8a3fd0;
  --err:#ff5544;
}
/* System-bar insets as variables rather than raw env(). Two reasons: every layer then agrees
   on the same numbers, and tools/mobile.js can override them to simulate a status bar and a
   landscape navigation bar — which is exactly the case that shipped broken, because a headless
   viewport has neither. */
:root{
  --sat:env(safe-area-inset-top,0px);
  --sar:env(safe-area-inset-right,0px);
  --sab:env(safe-area-inset-bottom,0px);
  --sal:env(safe-area-inset-left,0px);
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
/* Android WebView inflates font sizes in blocks it judges to be wide body text ("font
   boosting"). It is a heuristic, not a user preference, and on a fixed-size game HUD it makes
   labels burst out of their buttons while desktop Chrome renders perfectly. Nothing here is
   reflowable prose, so it is switched off outright. */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#060504;color:var(--ink);
  font-family:Georgia,'Palatino Linotype',Palatino,serif;touch-action:none;overscroll-behavior:none;user-select:none;-webkit-user-select:none}
button{font:inherit;cursor:pointer}
#app{position:fixed;inset:0;overflow:hidden;background:#0b0f09}
#game{position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:none}

/* ---- gold-trimmed stone panel: the classic RTS frame language ---- */
.wcp{
  background:linear-gradient(180deg,var(--panel1),var(--panel2));
  border:2px solid var(--edge);
  outline:2px solid #0a0908;
  box-shadow:inset 0 0 0 1px rgba(242,214,136,.14), inset 0 14px 22px rgba(255,244,200,.04), 0 6px 20px rgba(0,0,0,.55);
  border-radius:4px;
}
.goldtrim{position:relative}
.goldtrim::before{content:"";position:absolute;inset:2px;border:1px solid rgba(200,162,74,.4);border-radius:2px;pointer-events:none}

/* ---- top resource bar ---- */
#topbar{
  position:absolute;top:max(5px,var(--sat));left:50%;transform:translateX(-50%);
  display:flex;align-items:center;gap:10px;padding:4px 12px;z-index:20;pointer-events:none;white-space:nowrap;
}
.vaultRes{min-width:218px;margin-left:4px;padding-left:9px;border-left:1px solid #5f5946}
.vaultRes b{font-size:12px;letter-spacing:.06em;color:#c6bfa6}.vaultRes small{font:800 11px Verdana,sans-serif;color:#efd894}
.res{display:flex;align-items:center;gap:6px;font-size:16px;font-weight:700;color:#efe6c8;text-shadow:0 1px 2px #000}
.res .ic{display:grid;place-items:center;width:22px;height:22px;font-size:16px;filter:drop-shadow(0 1px 1px #000)}
.res.gold b{color:#ffd75e;min-width:52px;display:inline-block}
.res.food b{color:#cfe0b8}
.res.timer b{color:#9fd3a5;font-variant-numeric:tabular-nums}
#clock{font-size:14px;color:#b9b09a;font-variant-numeric:tabular-nums}

/* ---- scoreboard ---- */
#scores{
  position:absolute;top:max(44px,calc(var(--sat) + 40px));right:max(6px,var(--sar));
  width:210px;padding:7px 9px;z-index:18;pointer-events:none;font-size:12px;transition:opacity .2s
}
#scores.dim{opacity:.28}
#scores h4{margin:0 0 3px;font-size:11px;letter-spacing:.14em;color:var(--gold);text-transform:uppercase;text-align:center}
.teamBlk{margin-top:5px;border-top:1px solid rgba(200,162,74,.22);padding-top:3px}
.teamHead{display:flex;justify-content:space-between;font-size:11px;color:#cfc6a9;font-weight:700;letter-spacing:.04em}
.teamHead .rax{color:#8fb586;letter-spacing:2px}
.teamBlk.gone{opacity:.4}
.teamBlk.gone .teamHead{text-decoration:line-through}
.pRow{display:grid;grid-template-columns:9px 15px 1fr 28px 24px;gap:5px;align-items:center;padding:2px 0;color:#ddd5ba}
.pRow .dot{width:9px;height:9px;border-radius:2px;border:1px solid #000}
.pRow .fac{font-size:10px;font-weight:900;color:#b8a468;text-align:center}
.pRow .nm{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pRow.you .nm{color:#ffe9a8;font-weight:700}
.pRow .lv{color:#cbb489;text-align:right}
.pRow .kk{color:#e0a49a;text-align:right}
.pRow.dead{opacity:.45}

/* ---- minimap ---- */
#mmWrap{
  position:absolute;left:max(10px,var(--sal));bottom:max(9px,var(--sab));
  padding:7px;z-index:24;box-shadow:0 0 0 3px #17150f,0 0 0 5px #665f4b,0 -7px 16px rgba(0,0,0,.7)
}
#minimap{width:166px;height:166px;display:block;border:2px solid #060505;background:#0d130c}
@media (max-height:520px), (max-width:900px){
  #minimap{width:104px;height:104px}
}

/* ---- announcer ---- */
#announce{
  position:absolute;top:16%;left:50%;transform:translateX(-50%);z-index:40;pointer-events:none;text-align:center;width:94%;
}
.annLine{
  font-size:30px;font-weight:900;letter-spacing:.05em;color:var(--goldhi);
  text-shadow:0 0 18px rgba(240,200,90,.45),0 2px 0 #000,0 3px 8px #000;
  animation:annIn .38s cubic-bezier(.2,1.6,.4,1) both, annOut .5s ease-in forwards;
}
.annLine.red{color:#ff7a66;text-shadow:0 0 18px rgba(255,90,60,.4),0 2px 0 #000,0 3px 8px #000}
.annLine.blue{color:#9cc6ff;text-shadow:0 0 18px rgba(90,140,255,.4),0 2px 0 #000,0 3px 8px #000}
.annSub{font-size:15px;color:#d8cfae;text-shadow:0 1px 2px #000;margin-top:4px;animation:annIn .4s .05s both, annOut .5s ease-in forwards}
@keyframes annIn{from{opacity:0;transform:scale(1.6)}to{opacity:1;transform:scale(1)}}
@keyframes annOut{to{opacity:0}}
@media (max-width:760px){.annLine{font-size:21px}}

/* ---- error / toast line ---- */
#errline{
  position:absolute;bottom:198px;left:50%;transform:translateX(-50%);z-index:30;pointer-events:none;
  font-size:16px;font-weight:700;color:var(--err);text-shadow:0 1px 2px #000;opacity:0;transition:opacity .25s;white-space:nowrap
}
#errline.on{opacity:1}
#errline.good{color:#cfe6a8}

/* army-wide orders: the missing RTS layer */
#armyBar{position:absolute;right:16px;bottom:190px;z-index:26;padding:0;pointer-events:auto}
#armyTab{display:flex;align-items:center;gap:7px;min-height:36px;padding:5px 11px;border:0;background:none;color:#d9cfaa;font:800 10px Verdana,sans-serif;letter-spacing:.05em;white-space:nowrap}
#armyTab i{font-style:normal;font-size:13px}
#armyCaret{color:#c39a52;font-size:12px;transition:transform .16s}
#armyBar.open #armyCaret{transform:rotate(-90deg)}
/* Pops LEFT over open battlefield rather than up: upward would run into the utility rail on
   short screens, and the audit is what caught that. bottom-aligned so muscle memory holds. */
#armyPop{display:none;position:absolute;right:calc(100% + 8px);bottom:0;grid-template-columns:repeat(2,minmax(96px,1fr));gap:6px;padding:7px}
#armyBar.open{z-index:44}
#armyBar.open #armyPop{display:grid}
#armyPop .armyBtn{width:100%;height:40px}
#armyPop #racialBtn{grid-column:1/-1;width:100%}
#armyMode{font:800 11px Verdana,sans-serif;color:#d9cfaa;letter-spacing:.04em}
.armyBtn{position:relative;width:56px;height:34px;border:1px solid #655e48;outline:1px solid #080705;background:linear-gradient(#302c20,#15120b);color:#e8dfc1;font:900 11px Verdana,sans-serif;text-shadow:0 1px #000}
.armyBtn:hover{border-color:#d2ad57;filter:brightness(1.16)}.armyBtn.active{border-color:#ffe18c;box-shadow:inset 0 0 8px rgba(255,211,94,.26),0 0 7px rgba(220,167,54,.3);color:#fff1b5}
.armyBtn .hk{position:absolute;left:3px;top:1px;color:#f4d875;font-size:10px}.armyBtn .mcost{position:absolute;right:3px;bottom:1px;color:#ffd75e;font-size:10px}
#racialBtn{width:74px;color:#ffcf8a}
#rosterBar{position:absolute;left:max(10px,var(--sal));top:max(44px,calc(var(--sat) + 40px));z-index:24;display:flex;gap:4px;padding:5px;pointer-events:auto}
.facBtn{position:relative;width:62px;height:44px;padding:6px 3px 3px;border:1px solid #5d5743;background:linear-gradient(#241e19,#120f0d);color:#9d947a;font:900 10px/1.2 Verdana,sans-serif;text-align:center}
.facBtn b{display:block;color:#e6d9ba;font-size:11px}.facBtn small{display:block;font-size:9px;color:#998c76;letter-spacing:.03em}
.facBtn:hover:not(.locked){border-color:#d8a12c}
.facBtn.active{border-color:#ffb648;box-shadow:inset 0 0 9px rgba(170,130,240,.28)}
.facBtn.active b{color:#fff0cf}
.facBtn.locked{opacity:.42;cursor:default}
.rosterSep{width:1px;align-self:stretch;margin:0 3px;background:linear-gradient(180deg,transparent,#6a6250,transparent)}
.rosterBtn{position:relative;width:102px;height:44px;padding:6px 5px 3px;border:1px solid #5d5743;background:linear-gradient(#2c291e,#13110b);color:#9d947a;font:900 10px/1.2 Verdana,sans-serif;text-align:left}.rosterBtn b{display:block;color:#d7cda9;font-size:11px}.rosterBtn small{display:block;font-size:9px;color:#948a6f}.rosterBtn.active{border-color:#ffe087;box-shadow:inset 0 0 9px rgba(247,204,81,.25),0 0 7px rgba(0,0,0,.6)}.rosterBtn.active::after{content:"✓";position:absolute;right:4px;top:2px;color:#9dff86;font-size:12px}
#squadBar{position:absolute;left:50%;bottom:190px;transform:translateX(-50%);z-index:25;display:none;align-items:center;gap:4px;padding:5px 6px;pointer-events:auto}
#squadBar.on{display:flex}#squadCount{min-width:112px;padding:0 8px;color:#dff2c9;font:800 11px Verdana,sans-serif;letter-spacing:.04em}
.squadBtn{height:34px;min-width:56px;border:1px solid #665f49;outline:1px solid #070604;background:linear-gradient(#332e20,#15120b);color:#e9dfbd;font:900 11px Verdana,sans-serif;position:relative}.squadBtn:hover,.squadBtn.armed{border-color:#ffe18a;box-shadow:inset 0 0 8px rgba(255,215,90,.25)}
.squadBtn .hk{position:absolute;left:3px;top:1px;color:#f4d875;font-size:10px}#formationBtn{min-width:86px;color:#ffd9a0}

/* ---- bottom HUD ---- */
#hud{
  position:absolute;left:0;right:0;bottom:0;height:184px;z-index:21;pointer-events:none;box-sizing:border-box;
  display:flex;align-items:center;justify-content:flex-start;gap:11px;
  padding:20px 12px calc(max(9px,var(--sab))) 198px;
}
#hud::before{content:"";position:absolute;inset:0;z-index:-2;
  background:
    radial-gradient(ellipse at 14% 18%,rgba(126,117,91,.24),transparent 23%),
    radial-gradient(ellipse at 72% 80%,rgba(111,101,76,.17),transparent 27%),
    repeating-linear-gradient(100deg,rgba(255,255,255,.018) 0 2px,transparent 2px 12px),
    linear-gradient(180deg,#49483e 0,#2c2b25 9%,#171712 21%,#10100d 100%);
  border-top:5px solid #0b0b09;box-shadow:inset 0 2px 0 #7d7761,inset 0 7px 0 #34332c,0 -7px 18px rgba(0,0,0,.68)}
#hud::after{content:"";position:absolute;left:190px;right:8px;top:9px;height:5px;z-index:-1;
  background:linear-gradient(90deg,#15140f,#8d815f 12%,#3b382c 48%,#8d815f 88%,#15140f);border:1px solid #080806;box-shadow:0 2px 0 #0b0a08}
#hud > *{pointer-events:auto}

#heroPanel{width:346px;min-height:132px;box-sizing:border-box;padding:11px 11px 9px;display:grid;grid-template-columns:94px 1fr;gap:11px;align-items:start}
#heroPanel{position:relative}#talentDock{position:absolute;right:5px;top:5px;display:none;min-width:64px;height:23px;border:1px solid #ffe083;background:linear-gradient(#715b1e,#211805);color:#fff0a5;font:900 10px Verdana,sans-serif;letter-spacing:.05em;box-shadow:0 0 10px rgba(255,205,68,.55);animation:skillPulse 1.1s infinite}#talentDock.on{display:block}
#portrait{
  width:94px;height:94px;border:3px solid var(--gold);outline:3px solid #090807;background:
  radial-gradient(circle at 42% 32%,#4c5648 0,#232a22 58%,#0d110d 100%);
  display:grid;place-items:center;font-size:34px;text-shadow:0 2px 3px #000;position:relative;color:#f0e6c4;
  background-repeat:no-repeat;background-size:cover;background-position:center;box-shadow:inset 0 0 14px #000,0 0 8px rgba(210,170,70,.24);
}
#portrait small{position:absolute;right:3px;bottom:2px;font-size:15px;font-weight:900;color:#ffd75e;text-shadow:0 1px 1px #000}
#portrait.dead{filter:grayscale(1) brightness(.6)}
#portrait.unspent{box-shadow:inset 0 0 14px #000,0 0 14px rgba(255,213,74,.9);border-color:#ffe47f}
#heroName{font-size:17px;font-weight:700;color:#f2e8c6;letter-spacing:.02em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#talentDock.on ~ div #heroName{padding-right:68px}
#heroSub{font-size:12px;color:#a9a087;margin:3px 0 5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bar{position:relative;height:16px;border:1px solid #070605;background:#171510;margin-top:4px;overflow:hidden}
.bar i{position:absolute;inset:0;transform-origin:left;transition:transform .1s linear}
.bar span{position:absolute;inset:0;display:grid;place-items:center;font-size:11px;font-weight:800;color:#fff;text-shadow:0 1px 2px #000,0 0 3px #000;font-style:normal;font-family:Verdana,sans-serif}
#hpBar i{background:linear-gradient(180deg,#37e337,#0e8a0e)}
#mpBar i{background:linear-gradient(180deg,#5f83f0,#2743a8)}
#xpBar{height:9px}
#xpBar i{background:linear-gradient(180deg,#b070f0,#5c2f96)}
#heroStats{display:flex;justify-content:space-between;gap:6px;margin-top:7px;font-size:12px;color:#d5cbad;white-space:nowrap}
#heroStats b{color:#ffe1a0}

/* useful ultrawide center: live army and objective intelligence */
#battlePanel{align-self:stretch;min-width:250px;flex:1;padding:10px;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;box-sizing:border-box;overflow:hidden}
.battleIntel{position:relative;min-width:0;padding:8px 9px;border:1px solid #474332;background:linear-gradient(145deg,rgba(46,42,28,.72),rgba(13,12,8,.82));box-shadow:inset 0 0 10px rgba(0,0,0,.32)}
.battleIntel small{display:block;margin-bottom:7px;color:#a89c78;font:800 10px Verdana,sans-serif;letter-spacing:.13em;text-transform:uppercase;white-space:nowrap}
.battleIntel b{display:block;color:#f1e4bc;font:700 15px Georgia,serif;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.battleIntel span{display:block;margin-top:5px;color:#b8ad8e;font:11px/1.35 Verdana,sans-serif}
.battleIntel em{display:block;position:absolute;left:9px;right:9px;bottom:8px;height:4px;border:1px solid #090806;background:#17140c;font-style:normal;overflow:hidden}
.battleIntel em i{display:block;height:100%;transform-origin:left;background:linear-gradient(90deg,#82671f,#e3bb54);transition:transform .15s linear}
#bpVault.held{color:#81ddb2}#bpVault.contested{color:#ffd06b}#bpVault.enemy{color:#ef8b79}

/* inventory */
#invPanel{padding:9px;display:grid;grid-template-columns:repeat(3,58px);grid-auto-rows:58px;gap:6px}
.slot{
  position:relative;border:1px solid #6a6450;outline:1px solid #0a0908;background:linear-gradient(#242219,#131109);
  display:grid;place-items:center;font-size:20px;color:#efe4c0;padding:0;background-repeat:no-repeat;background-size:cover;background-position:center;
  box-shadow:inset 0 0 7px rgba(0,0,0,.8)
}
.slot:active{filter:brightness(1.3)}
.slot.empty{color:#3c382c;font-size:11px}
.slot small{position:absolute;right:2px;bottom:0;font-size:12px;font-weight:900;color:#ffd75e;font-family:Verdana,sans-serif;text-shadow:0 1px 1px #000}
.slot .slotKey{position:absolute;left:3px;top:1px;font:900 10px Verdana,sans-serif;color:#f2e7bd;text-shadow:0 1px 2px #000;opacity:.8}
.slot:not(.empty){cursor:grab}.slot.dragging{opacity:.38;filter:grayscale(.45)}.slot.dropTarget,.slot.movePicked{border-color:#ffe08a;box-shadow:inset 0 0 9px rgba(255,220,120,.35),0 0 8px rgba(255,205,70,.45)}

/* command card */
#cmdCard{padding:9px;display:grid;grid-template-columns:repeat(4,62px);grid-auto-rows:62px;gap:6px}
.cmd{
  position:relative;border:2px solid #6a6450;outline:2px solid #0a0908;border-radius:3px;
  background:linear-gradient(#2c2a20,#15130c);display:grid;place-items:center;font-size:27px;color:#f0e6c4;
  text-shadow:0 1px 2px #000;padding:0;overflow:hidden;
}
.cmd.artSprite{background-size:cover;background-position:center;background-repeat:no-repeat;box-shadow:inset 0 0 9px rgba(0,0,0,.72)}
.cmd.upgradeArt{background-size:cover;background-position:center;box-shadow:inset 0 0 9px rgba(0,0,0,.78)}
.cmd.artSprite:hover{box-shadow:inset 0 0 7px rgba(255,224,128,.18),0 0 9px rgba(210,162,62,.3)}
.cmd:not(:disabled):hover{border-color:#c8a24a;filter:brightness(1.2)}
.cmd:active{transform:translateY(1px)}
.cmd .hk{position:absolute;left:3px;top:1px;font-size:13px;font-weight:900;color:#ffe9a0;font-family:Verdana,sans-serif;text-shadow:0 1px 1px #000}
.cmd .cost{position:absolute;right:3px;bottom:1px;font-size:12px;font-weight:800;color:#ffd75e;font-family:Verdana,sans-serif;text-shadow:0 1px 1px #000}
.cmd .lvl{position:absolute;left:3px;bottom:0;font-size:10px;color:#b0e6a8;font-family:Verdana,sans-serif}
.cmd .skillPlus{position:absolute;right:2px;top:2px;width:19px;height:19px;display:none;place-items:center;border:1px solid #ffe18a;border-radius:2px;background:linear-gradient(#6b5a24,#261d08);color:#fff4b7;font:900 15px/1 Verdana,sans-serif;box-shadow:0 0 8px rgba(255,211,77,.72);z-index:4;animation:skillPulse 1.1s ease-in-out infinite}
.cmd.canLearn .skillPlus{display:grid}.cmd.unlearned{filter:grayscale(.5) brightness(.7)}.cmd.canLearn{filter:none}
@keyframes skillPulse{50%{filter:brightness(1.42);transform:scale(1.08)}}
/* The sweep and the number are separate layers on purpose. They used to be one element, so
   the countdown shrank with the sweep and was squeezed to an unreadable sliver in the last
   second — exactly when you are watching it. The sweep wipes; the number never moves. */
.cmd .cd{position:absolute;left:0;right:0;bottom:0;background:rgba(6,8,14,.72);pointer-events:none}
.cmd .cdNum{position:absolute;inset:0;display:none;place-items:center;pointer-events:none;
  font:900 24px/1 Verdana,sans-serif;color:#fff;font-variant-numeric:tabular-nums;
  text-shadow:0 0 3px #000,0 2px 4px #000,0 0 12px rgba(120,170,255,.75)}
.cmd.onCd .cdNum{display:grid}
.cmd .cdNum.wide{font-size:19px}   /* "104" and "0.1" overflow the cell at full size */
.cmd.locked{color:#4a4638}
.cmd.nomana{color:#6a7db0}
.cmd.upg{font-size:25px}
.cmd:disabled{opacity:.55;cursor:default}
.cmd.flashbuy{animation:buyFlash .4s}
@keyframes buyFlash{0%{box-shadow:0 0 0 3px #ffd75e}100%{box-shadow:0 0 0 3px transparent}}

@media (min-width:1101px) and (max-width:1500px){
  #heroPanel{width:270px;grid-template-columns:82px 1fr}
  #portrait{width:82px;height:82px}
  #invPanel{padding:8px;grid-template-columns:repeat(3,52px);grid-auto-rows:52px;gap:5px}
  #cmdCard{padding:8px;grid-template-columns:repeat(4,55px);grid-auto-rows:55px;gap:5px}
  .cmd{font-size:24px}.cmd.upg{font-size:22px}.cmd .cdNum{font-size:21px}
  /* min-width here forced the whole HUD row past the right edge — 134px over at 1150.
     The intel blocks are minmax(0,1fr), so the panel can give ground instead. */
  #battlePanel{grid-template-columns:repeat(2,minmax(0,1fr));min-width:0}
  #battlePanel .battleIntel:nth-child(3){display:none}
}

@media (max-width:1100px){
  #hud{height:164px;padding-left:174px;gap:7px}
  #hud::after{left:166px}
  #minimap{width:142px;height:142px}
  #heroPanel{width:292px;min-height:124px;grid-template-columns:78px 1fr;gap:8px;padding:9px}
  #portrait{width:78px;height:78px}
  #heroName{font-size:15px}#heroSub{font-size:11px}.bar{height:14px}.bar span{font-size:10px}#heroStats{gap:8px;font-size:11px}
  #invPanel{padding:7px;grid-template-columns:repeat(3,50px);grid-auto-rows:50px;gap:5px}
  #cmdCard{padding:7px;grid-template-columns:repeat(4,56px);grid-auto-rows:56px;gap:5px}
  .cmd{font-size:24px}.cmd.upg{font-size:22px}.cmd .cdNum{font-size:21px}
  #errline{bottom:174px}
  #battlePanel{display:none}
  #armyBar{right:8px;bottom:170px;transform:scale(.9);transform-origin:right bottom}
  #squadBar{bottom:170px;transform:translateX(-50%) scale(.86)}
}
@media (max-width:900px){
  .setupGrid{grid-template-columns:1fr;gap:2px}
  .vaultRes{display:none}
  #hud{height:138px;padding:15px 4px max(5px,var(--sab)) 118px;gap:4px}
  #hud::after{left:112px;top:7px;height:3px}
  #mmWrap{left:6px;bottom:6px;padding:4px;box-shadow:0 0 0 2px #17150f,0 0 0 3px #665f4b}
  #minimap{width:104px;height:104px;border-width:1px}
  #heroPanel{width:244px;min-height:105px;grid-template-columns:58px 1fr;gap:6px;padding:6px}
  #portrait{width:58px;height:58px;border-width:2px;outline-width:2px}
  #heroName{font-size:13px}#heroSub{font-size:10px;margin-bottom:2px}.bar{height:13px;margin-top:3px}.bar span{font-size:10px}
  #xpBar{height:6px}#heroStats{gap:6px;margin-top:4px;font-size:10px}
  #invPanel{padding:5px;grid-template-columns:repeat(3,38px);grid-auto-rows:38px;gap:3px}
  #cmdCard{padding:5px;grid-template-columns:repeat(4,47px);grid-auto-rows:47px;gap:3px}
  .cmd{font-size:20px}.cmd.upg{font-size:18px}.cmd .cdNum{font-size:18px}
  .cmd .hk{font-size:11px}.cmd .cost{font-size:10px}.cmd .lvl{font-size:9px}
  #errline{bottom:146px}
  #armyBar{right:4px;bottom:142px;transform:scale(.72);transform-origin:right bottom}
  #squadBar{left:50%;bottom:142px;transform:translateX(-50%) scale(.7)}

  #rosterBar{top:38px;transform:scale(.78);transform-origin:left top}.rosterBtn{width:88px}
  #scores{width:178px;font-size:11px}#killFeed{width:50vw;top:88px}
}
@media (max-width:680px) and (orientation:landscape){
  #hud{height:122px;padding:10px 3px max(4px,var(--sab)) 94px;gap:3px}
  #hud::after{left:90px}
  #mmWrap{left:4px;bottom:5px;padding:3px}#minimap{width:80px;height:80px}
  #heroPanel{width:172px;min-height:92px;grid-template-columns:45px 1fr;padding:5px;gap:5px}#portrait{width:45px;height:45px}
  #heroSub{display:none}#heroStats{font-size:9px;gap:5px}.bar{height:12px}.bar span{font-size:9px}
  #invPanel{padding:4px;grid-template-columns:repeat(3,30px);grid-auto-rows:30px;gap:2px}
  #cmdCard{padding:4px;grid-template-columns:repeat(4,38px);grid-auto-rows:38px;gap:2px}
  .cmd{font-size:16px}.cmd.upg{font-size:14px}.cmd .cdNum{font-size:15px}
  #armyBar{bottom:125px;transform:scale(.62)}#errline{bottom:129px;font-size:13px}
  #squadBar{bottom:125px;transform:translateX(-50%) scale(.62)}
  #rosterBar{top:31px;transform:scale(.58)}
}

/* Four teams of three stacked in one column runs about 310px tall. On a short viewport that
   ran straight past the army bar and under the HUD, hiding the bottom two teams entirely.
   Two columns halves the height and costs nothing in legibility — the alternative was
   shrinking the text back down, which is the thing this pass exists to stop. */
@media (max-height:660px){
  #scores{width:min(330px,46vw)}
  #scoreRows{display:grid;grid-template-columns:1fr 1fr;column-gap:12px}
  .teamBlk{margin-top:4px}
  /* halving the width halves what the name gets, so the fixed columns give ground first */
  .pRow{padding:1px 0;grid-template-columns:8px 13px 1fr 19px 17px;gap:3px}
}

#rotateHint{position:absolute;inset:0;z-index:90;display:none;place-items:center;padding:24px;text-align:center;background:radial-gradient(circle at 50% 35%,rgba(48,58,38,.97),rgba(5,7,5,.99))}
#rotateHint .rotateCard{max-width:310px;padding:24px 20px}#rotateHint strong{display:block;font-size:25px;color:#f0d77f;letter-spacing:.08em}#rotateHint span{display:block;margin-top:8px;color:#b9ae8c;font:12px/1.45 Verdana,sans-serif}
#rotateHint .phone{display:block;margin:0 auto 14px;width:42px;height:70px;border:4px solid #d8c27d;border-radius:7px;animation:turnPhone 1.8s ease-in-out infinite}
@keyframes turnPhone{0%,25%{transform:rotate(0)}65%,100%{transform:rotate(90deg)}}
@media (max-width:600px) and (orientation:portrait){#app.inMatch #rotateHint{display:grid}}

/* 8bit Death Pit: icons are live CSS geometry unless artStyle() supplies a bitmap.
   It switches the shape layers off through --shape-bg / --shape-core / --glyph-display
   rather than a class, because callers only ever receive a style string. */
.artSprite,.shapeSprite{position:relative;background-image:none!important;background-color:#11151a!important;isolation:isolate;overflow:hidden}
.artSprite::before,.shapeSprite::before{content:"";position:absolute;inset:15%;z-index:0;pointer-events:none;background:var(--shape-bg,linear-gradient(135deg,#fff3e0,#ff9a3c));clip-path:var(--shape-clip,circle(50%));transform:rotate(var(--shape-rot,0deg));filter:drop-shadow(0 2px 2px #000) drop-shadow(0 0 5px var(--shape-glow,#ff9a3c));transition:transform .16s ease,filter .16s ease}
.artSprite::after,.shapeSprite::after{content:"";position:absolute;inset:31%;z-index:0;pointer-events:none;background:var(--shape-core,#10151c);clip-path:var(--shape-clip,circle(50%));transform:rotate(var(--shape-rot,0deg));opacity:.74}
.artSprite:hover::before{transform:rotate(var(--shape-rot,0deg)) scale(1.09);filter:drop-shadow(0 2px 2px #000) drop-shadow(0 0 9px var(--shape-glow,#ff9a3c))}
.artSprite>*{position:relative;z-index:1}
#portrait.shapeSprite{background-position:initial;background-size:initial}
#portrait.shapeSprite::before{inset:12%}#portrait.shapeSprite::after{inset:34%}
/* glyph layer: the shape says WHOSE it is, the glyph says WHAT it does */
.icGlyph{display:var(--glyph-display,inline);position:relative;z-index:2;font-style:normal;line-height:1;pointer-events:none;text-shadow:0 2px 3px #000,0 0 6px rgba(0,0,0,.55)}
#portGlyph{display:var(--glyph-display,inline);position:relative;z-index:2;text-shadow:0 2px 4px #000}
.sellSlot{display:grid;place-items:center;font-size:20px}
.hCard .hSkills i{display:grid;place-items:center}.hSkills .icGlyph{font-size:14px}

/* joystick (touch) */
#joy{
  position:absolute;left:max(14px,var(--sal));bottom:190px;width:118px;height:118px;border-radius:50%;
  border:2px solid rgba(200,162,74,.4);background:radial-gradient(circle,rgba(30,28,20,.5),rgba(10,9,6,.6));
  z-index:23;display:none;touch-action:none
}
#joyStick{
  position:absolute;left:50%;top:50%;width:52px;height:52px;margin:-26px;border-radius:50%;
  border:2px solid var(--gold);background:radial-gradient(circle at 38% 30%,#6a6144,#26221a 70%);
  box-shadow:0 4px 10px rgba(0,0,0,.5)
}
body.touch #joy{display:block}
@media (max-width:900px){#joy{bottom:150px;width:104px;height:104px}}

/* utility buttons */
#util{position:absolute;right:max(6px,var(--sar));top:max(44px,calc(var(--sat) + 40px));display:flex;flex-direction:column;gap:5px;z-index:46}
#scores + #util{top:auto}
.ubtn{width:34px;height:34px;border:2px solid #5c5744;outline:1px solid #0a0908;border-radius:4px;
  background:linear-gradient(#33301f,#171509);color:#e6dcbb;font-size:15px;padding:0}
.ubtn:hover{border-color:var(--gold)}
.ubtn.off{opacity:.45}
.ubtn:focus-visible,.modalBtn:focus-visible,.segBtn:focus-visible{outline:2px solid #ffe07b;outline-offset:2px}
.cSkills{display:flex;gap:5px;justify-content:center;margin-top:6px}
@media (max-height:520px){
  body.touch #choosePanel{padding:10px 12px}
  body.touch #choosePanel h3{font-size:17px}
  body.touch #choosePanel>p{margin-bottom:7px}
  body.touch .chooseCard{padding:6px 5px}
  body.touch .cSkills{gap:4px;margin-top:4px}
  body.touch .cSkills i{width:30px;height:30px;font-size:13px}
}
.cSkills i{width:30px;height:30px;border:1px solid #5c5540;background:#17130c;background-size:cover;background-position:center;display:grid;place-items:center;font-style:normal;font-size:14px;color:#efe4c0;image-rendering:pixelated}
body.touch .cSkills i{width:34px;height:34px}
/* Sits to the LEFT of the utility rail, never over it. At right:46px with a 340px width it
   covered the whole rail, and being one z-index above meant the "?" that opened it was the
   one button you could no longer press — the panel had no exit at all. */
#combatLegend{position:absolute;right:calc(max(6px,var(--sar)) + 58px);top:max(44px,calc(var(--sat) + 40px));z-index:47;display:none;
  width:min(340px,calc(100vw - var(--sar) - var(--sal) - 76px));max-height:calc(100vh - var(--sat) - var(--sab) - 56px);overflow:auto;touch-action:pan-y;padding:11px}
#combatLegend.open{display:block}
.legendHead{display:flex;align-items:center;gap:8px;margin-bottom:7px}
.legendHead h4{flex:1 1 auto;margin:0}
#combatLegend h4{margin:0 0 7px;color:#f0d77f;font-size:13px;letter-spacing:.12em;text-align:center}#combatLegend table{width:100%;border-collapse:collapse;font:11px Verdana,sans-serif;text-align:center}#combatLegend th{color:#a89c7d}#combatLegend td,#combatLegend th{padding:4px;border:1px solid #484231}#combatLegend .strong{color:#8eef8c;background:rgba(64,120,48,.18)}#combatLegend .weak{color:#a9a397;background:rgba(40,38,33,.5)}#combatLegend p{margin:7px 0 0;color:#a99e80;font:10px/1.4 Verdana,sans-serif}
#killFeed{position:absolute;left:max(12px,var(--sal));top:max(104px,calc(var(--sat) + 90px));z-index:30;width:min(380px,44vw);display:flex;flex-direction:column;gap:4px;pointer-events:none}
.killLine{align-self:flex-start;max-width:100%;padding:6px 11px;border-left:3px solid var(--kc,#d4ad45);background:linear-gradient(90deg,rgba(7,8,7,.9),rgba(7,8,7,.52));box-shadow:0 2px 10px #0008;color:#ded4b9;font:700 13px Georgia;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;animation:killIn .18s ease-out}
.killLine strong{color:#fff1b0}.killLine.objective{border-color:#ffb23d;color:#ffe2a2}
@keyframes killIn{from{opacity:0;transform:translateX(-18px)}to{opacity:1;transform:none}}
#dangerVignette{position:absolute;inset:0;z-index:18;pointer-events:none;opacity:0;background:radial-gradient(ellipse at center,transparent 42%,rgba(110,0,0,.22) 73%,rgba(120,0,0,.82) 100%);mix-blend-mode:screen;transition:opacity .12s}
#app.ordering #game{cursor:crosshair}
#eventBar{position:absolute;z-index:31;left:50%;top:max(43px,calc(var(--sat) + 39px));transform:translate(-50%,-8px);min-width:238px;padding:5px 12px 6px;opacity:0;pointer-events:none;text-align:center;transition:.2s;background:linear-gradient(180deg,rgba(46,32,17,.95),rgba(12,10,7,.94));border:1px solid #9f7530;box-shadow:inset 0 0 0 2px #151009,0 3px 14px #0009}
#eventBar.on{opacity:1;transform:translate(-50%,0)}
#eventName{display:block;color:#ffd978;font:900 13px Cinzel,Georgia;letter-spacing:.15em;text-shadow:0 1px #000}
#eventMeta{display:flex;justify-content:center;gap:10px;margin-top:3px;color:#b5a884;font:800 11px Verdana,sans-serif}
#eventTime{color:#fff0b0}

/* ---- shop ---- */
/* Inset padding on the wrapper and a % width on the card. 94vw ignores the nav strip
   entirely, so on a 568px phone with a 48px three-button bar the close button and the last
   tab sat underneath it. This is the same vw trap the modals section warns about. */
/* Inset padding on the wrapper and a % width on the card. 94vw ignores the nav strip
   entirely, so on a 568px phone with a 48px three-button bar the close button and the last
   tab sat underneath it. Same vw trap the modals section warns about.
   safe center rather than place-items:center, so an over-tall card is reachable from the top
   instead of being centred above the scrollport. */
#shopWrap{position:absolute;inset:0;z-index:50;display:none;justify-items:center;align-content:safe center;overflow:auto;touch-action:pan-y;
  padding:max(4px,var(--sat)) max(4px,var(--sar)) max(4px,var(--sab)) max(4px,var(--sal));
  background:rgba(4,3,2,.6);backdrop-filter:blur(2px)}
#shopWrap.open{display:grid}
/* A DEFINITE max-height. As a percentage it resolved against a content-sized grid row and so
   clamped nothing at all, and the whole panel spilled out of the wrapper on a tablet. */
#shop{width:min(560px,100%);max-height:calc(100vh - var(--sat) - var(--sab) - 10px);
  display:flex;flex-direction:column;padding:12px}
#shopHead{display:flex;justify-content:space-between;align-items:center;margin-bottom:2px}
#shopHead h3{margin:0;font-size:17px;color:var(--goldhi);letter-spacing:.06em}
#shopHead p{margin:3px 0 0;font-size:12px;color:var(--muted)}
#shopGold{font-size:15px;color:#ffd75e;font-weight:800;white-space:nowrap}
#shopClose{border:2px solid #5c5744;background:linear-gradient(#3a3626,#181509);color:#f0e6c4;width:30px;height:30px;border-radius:4px;font-size:14px}
/* flex:1 and min-height:0 are what make overflow-y:auto mean anything here. Without them a
   flex child sizes to its content, so the grid grew to fit all 22 cards, #shop clamped at
   max-height, and the overflow painted straight over the sell slots and out of the panel.
   That is the "items colliding" bug — it was never a grid-gap problem. */
/* Two fixes in one rule.
   flex:1 + min-height:0 are what make overflow-y:auto mean anything: without them a flex child
   sizes to its content, so the grid grew to fit all 22 cards, #shop clamped at its max-height,
   and the overflow painted over the sell slots and out of the panel.
   FLEX rather than grid for the cards themselves. As a grid, every row resolved to exactly the
   56px min-height and never grew — the worst card needs 115px at a 175px column — so the price
   line rendered outside its own card and onto the one below. A flex item sizes its cross axis
   from its resolved width, which is what wrapped text needs. */
#shopGrid{margin-top:9px;flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;touch-action:pan-y;-webkit-overflow-scrolling:touch;
  display:flex;flex-wrap:wrap;align-content:flex-start;align-items:flex-start;gap:6px;padding-right:2px}
#shopGrid .sItem{flex:1 1 158px;max-width:100%}
#shopTabs{display:flex;flex-wrap:wrap;gap:5px;margin-top:9px}.shopTab{flex:1;min-width:76px;min-height:28px;border:1px solid #514b39;background:linear-gradient(#282419,#121008);color:#a99f80;font:800 9px Verdana,sans-serif}.shopTab.active{border-color:#e2bc5d;color:#ffe8a3;box-shadow:inset 0 0 8px rgba(226,188,93,.2)}
.sItem .badge{display:inline-block;margin-left:5px;padding:1px 4px;border:1px solid #5e5742;color:#9f9475;font:700 7px Verdana,sans-serif;text-transform:uppercase}.sItem.recipe{border-color:#7a4a1c}.sItem.recipe .pr{color:#ffc47a}
.sItem{display:grid;grid-template-columns:38px 1fr;gap:7px;align-items:start;padding:6px;border:1px solid #514c3a;outline:1px solid #0a0908;
  background:linear-gradient(#232013,#12100a);border-radius:3px;text-align:left;color:var(--ink)}
.sItem:not(:disabled):hover{border-color:var(--gold);filter:brightness(1.15)}
.sItem:disabled{opacity:.5}
.sItem .ic{width:38px;height:38px;border:1px solid #6a6450;background:#1c1a10;display:grid;place-items:center;font-size:20px}
.sItem .ic.artSprite{background-size:cover;background-position:center;background-repeat:no-repeat;box-shadow:inset 0 0 7px rgba(0,0,0,.8)}
.itemArt.uncommon{border-color:#4ea85c!important}.itemArt.rare{border-color:#4388d8!important}.itemArt.epic{border-color:#9b5dd8!important}.itemArt.legendary{border-color:#dc9d34!important;box-shadow:inset 0 0 7px rgba(0,0,0,.75),0 0 7px rgba(220,157,52,.28)}
.sItem b{display:block;font-size:13px;color:#f2e8c6}
.sItem em{display:block;font-style:normal;font-size:11px;color:#a9a087;margin-top:2px;line-height:1.3}
.sItem .pr{font-size:12px;color:#ffd75e;font-weight:800}
#shopHint{margin-top:9px;font-size:12px;color:#b3a985;text-align:center}
#talentWrap{position:absolute;inset:0;z-index:58;display:none;place-items:center;background:rgba(3,2,1,.7);backdrop-filter:blur(2px)}#talentWrap.open{display:grid}
#talentPanel{width:min(620px,94vw);padding:18px}#talentPanel h3{margin:0;text-align:center;color:#f0d77f;letter-spacing:.12em}#talentPanel>p{text-align:center;color:#a99f82;font:10px Verdana,sans-serif}
#talentChoices{display:grid;grid-template-columns:1fr 1fr;gap:10px}.talentChoice{min-height:118px;padding:14px;border:2px solid #5c5540;background:linear-gradient(145deg,#302b1d,#111009);color:#e9dfbd;text-align:left}.talentChoice:hover{border-color:#f0cb69;filter:brightness(1.12)}.talentChoice b{display:block;color:#ffe7a2;font-size:17px}.talentChoice em{display:block;margin:3px 0 8px;color:#a79d7d;font:italic 10px Verdana,sans-serif}.talentChoice span{font:11px/1.45 Verdana,sans-serif;color:#d2c9ac}.talentChoice small{display:block;margin-top:8px;color:#7fb4e9;font:9px Verdana,sans-serif}
@media(max-width:680px){#talentPanel{padding:10px}#talentChoices{gap:5px}.talentChoice{min-height:92px;padding:8px}.talentChoice b{font-size:13px}.talentChoice span{font-size:9px}}
#sellHead{display:flex;align-items:end;justify-content:space-between;margin-top:10px;padding-top:8px;border-top:1px solid #514c3a;color:var(--gold);font-size:12px;letter-spacing:.16em;text-transform:uppercase}
#sellHead small{color:#9b9171;font-size:10px;letter-spacing:0;text-transform:none}
#sellGrid{display:grid;grid-template-columns:repeat(6,52px);gap:6px;margin-top:6px;justify-content:center}
.sellSlot{position:relative;width:52px;height:52px;border:1px solid #635c47;outline:1px solid #090806;background:#14120c;padding:0;background-size:cover;background-position:center}
.sellSlot:hover:not(.empty){border-color:#e3bd5e;filter:brightness(1.12)}.sellSlot.empty{opacity:.3;cursor:default}
.sellSlot .refund{position:absolute;left:2px;right:2px;bottom:1px;padding:1px 0;background:rgba(5,4,2,.78);font:800 8px Verdana,sans-serif;color:#ffd75e;text-align:center;text-shadow:0 1px #000}
.sellSlot .charges{position:absolute;right:2px;top:1px;font:900 9px Verdana,sans-serif;color:#fff;text-shadow:0 1px 2px #000}

/* ---- modal screens (title / end) ---- */
#veil{position:absolute;inset:0;z-index:60;display:grid;justify-items:center;align-content:safe center;overflow-y:auto;
  touch-action:pan-y;-webkit-overflow-scrolling:touch;background:radial-gradient(120% 90% at 50% 8%,#233022 0,#101710 42%,#050705 100%)}
#veil.hidden{display:none}
#titleCard{width:min(1500px,100%);margin:clamp(4px,2vh,18px) auto;padding:clamp(8px,1.3vw,18px) clamp(10px,2vw,28px);text-align:center}
#gameLogo{font-size:clamp(38px,5vw,68px);font-weight:900;letter-spacing:.045em;line-height:.95;margin:0;
  background:linear-gradient(180deg,#fbe9a6 15%,#d3a94e 55%,#8a6423 78%,#f5dd94 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 3px 0 #1a1206) drop-shadow(0 6px 14px rgba(0,0,0,.8));
}
#gameLogo small{display:block;font-size:clamp(11px,2vw,14px);letter-spacing:.5em;color:#b8ab84;-webkit-text-fill-color:#b8ab84;filter:none;margin-bottom:2px}
#tagline{font-size:clamp(11px,1.1vw,14px);color:#a89e7f;margin:4px 0 7px}
.secTitle{font-size:clamp(10px,1vw,13px);letter-spacing:.22em;color:var(--gold);text-transform:uppercase;margin:6px 0 4px}
#heroGrid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:clamp(5px,.7vw,9px)}
.hCard{position:relative;padding:8px 8px 7px;border:2px solid #4c4736;outline:1px solid #0a0908;border-radius:4px;
  background:linear-gradient(#26231733,#12100a);text-align:left;color:var(--ink)}
.hCard:hover{border-color:#9c8348}
.hCard.sel{border-color:var(--goldhi);box-shadow:0 0 0 1px var(--goldhi),0 0 16px rgba(240,214,136,.25);background:linear-gradient(#3a341f55,#171408)}
.hCard .hIc{float:left;width:54px;height:54px;margin-right:8px;border:1px solid #82744e;background:#1c1a10;display:grid;place-items:center;font-size:19px;color:#f0e6c4;background-repeat:no-repeat;background-size:cover;background-position:center;box-shadow:inset 0 0 9px #000}
.hCard b{display:block;font-size:14px;color:#f2e8c6}
.hCard i{display:block;font-style:normal;font-size:11px;color:#c2ae6f;margin:2px 0 3px}
.hCard em{display:block;font-style:normal;font-size:11px;color:#a9a087;line-height:1.35;margin-top:3px;min-height:26px}
.hSkills{display:grid;grid-template-columns:repeat(4,25px);gap:3px;clear:both;padding-top:7px}
.hCard .hSkills i{width:25px;height:25px;margin:0;border:1px solid #544c37;background-repeat:no-repeat;background-size:cover;background-position:center;box-shadow:inset 0 0 5px #000}
.hCard.sel .hIc{border-color:#e8c76a;box-shadow:inset 0 0 8px #000,0 0 9px rgba(232,199,106,.4)}
.heroNew{position:absolute;right:4px;top:3px;padding:1px 4px;border:1px solid #8f6c2f;background:#241a0c;color:#ffd56a;font:900 6px Verdana,sans-serif;letter-spacing:.08em}
@media (max-width:900px){#heroGrid{grid-template-columns:repeat(4,minmax(0,1fr))}}
#factionGrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(5px,.7vw,9px)}
.fCard{position:relative;min-height:70px;padding:8px 8px 7px 64px;border:2px solid #4c4736;outline:1px solid #0a0908;border-radius:4px;
  background:linear-gradient(#26231755,#12100a);text-align:left;color:var(--ink)}
.fCard:hover{border-color:#9c8348}.fCard.sel{border-color:var(--goldhi);box-shadow:0 0 0 1px var(--goldhi),0 0 15px rgba(240,214,136,.22)}
.fCard .fArt{position:absolute;left:7px;top:7px;width:48px;height:48px;border:1px solid #746848;background-repeat:no-repeat;background-size:cover;background-position:center;box-shadow:inset 0 0 8px #000}
.fCard b{display:block;color:#f2e8c6;font-size:14px}.fCard em{display:block;color:#c2ae6f;font-size:11px;font-style:normal;margin-top:2px}
.fCard small{display:block;color:#9b9171;font-size:10px;line-height:1.25;margin-top:4px}
@media (max-width:760px){#factionGrid{grid-template-columns:repeat(2,1fr)}}
@media (max-height:820px) and (min-width:901px){
  #titleCard{padding:7px 18px;margin:5px auto}#gameLogo{font-size:44px}#gameLogo small{font-size:10px}#tagline{margin:2px 0 5px}
  .secTitle{margin:5px 0 3px}.hCard{padding:5px}.hCard .hIc{width:46px;height:46px;margin-right:6px}.hCard em{min-height:16px}.hSkills{padding-top:4px}.hCard .hSkills i{width:23px;height:23px}
  .fCard{min-height:58px;padding:6px 6px 5px 54px}.fCard .fArt{width:42px;height:42px;left:6px;top:6px}.setupBtn{min-height:33px;padding:4px}.diffBtn{padding:5px 16px}#startBtn{margin-top:6px;padding:7px 8px}#howTo{margin-top:5px}
}
.diffRow{display:flex;justify-content:center;gap:6px}
.setupGrid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:2px}
.setupGrid .secTitle{margin-top:4px}
/* Equal columns that always fit, rather than a centred flex row. A flex row that overflows
   with justify-content:center spills over BOTH edges, and the left spill is then clipped by
   the panel — which is how Solo and Duos vanished on device while every headless width said
   the row was fine. Larger system text was enough to trigger it. minmax(0,1fr) cannot
   overflow, so the failure mode does not exist any more. */
.setupRow{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:5px}
.setupBtn{overflow:hidden}
.setupBtn{flex:1;min-width:0;min-height:38px;padding:6px 5px;border:1px solid #5e5743;outline:1px solid #090806;background:linear-gradient(#28251a,#121009);color:#d6cdb0;font:800 clamp(10px,1vw,13px) Georgia,serif}
.setupBtn small{display:block;margin-top:3px;color:#948b70;font:10px Verdana,sans-serif}.setupBtn:hover{border-color:#b99a52}.setupBtn.sel{border-color:#e0b95b;color:#ffe7a2;box-shadow:inset 0 0 8px rgba(224,185,91,.18)}
#matchSummary{margin-top:8px;font:800 12px Verdana,sans-serif;color:#c2b691;letter-spacing:.06em}
.lobbyUtility{display:flex;justify-content:center;margin-top:7px}.lobbyUtility button{padding:6px 14px;border:1px solid #6b5c31;background:linear-gradient(#292418,#121009);color:#d9c680;font:800 9px Verdana,sans-serif;letter-spacing:.08em}.lobbyUtility button:hover{border-color:#d8b34d;color:#ffe89b}
.diffBtn{min-height:38px;padding:6px 18px;border:2px solid #4c4736;border-radius:4px;background:linear-gradient(#262317,#12100a);color:#cfc6a9;font-size:clamp(11px,1vw,14px)}
.diffBtn.sel{border-color:var(--goldhi);color:#ffe9a8}
#startBtn{display:block;width:min(720px,100%);margin:9px auto 0;padding:10px 18px;font-size:clamp(14px,1.6vw,21px);font-weight:800;letter-spacing:.08em;color:#1c1204;
  border:2px solid #f5dd94;border-radius:5px;background:linear-gradient(180deg,#f5dd94,#c8973c 60%,#9c6f22);
  box-shadow:0 0 22px rgba(240,200,90,.3),0 4px 0 #4a3210,0 8px 18px rgba(0,0,0,.6);text-shadow:0 1px 0 rgba(255,255,255,.4)}
#startBtn:hover{filter:brightness(1.08)}
#startBtn:active{transform:translateY(2px);box-shadow:0 0 22px rgba(240,200,90,.3),0 2px 0 #4a3210}
#howTo{margin-top:5px;font-size:12px;color:#9b9171;line-height:1.35}
#howTo b{color:#c4b98f}
@media (min-width:901px) and (min-height:800px){
  .hCard{padding:10px}.hCard .hIc{width:66px;height:66px;margin-right:10px}.hCard b{font-size:15px}.hCard em{font-size:10px;min-height:28px}
  .hSkills{grid-template-columns:repeat(4,31px);gap:4px;padding-top:9px}.hCard .hSkills i{width:31px;height:31px}
  .fCard{min-height:88px;padding:11px 10px 9px 80px}.fCard .fArt{width:62px;height:62px;left:9px;top:9px}.fCard b{font-size:15px}.fCard em{font-size:10px}.fCard small{font-size:9px}
  .setupBtn{min-height:46px}.setupBtn small{font-size:8px}.diffBtn{min-height:44px}
  #matchSummary{font-size:10px;margin-top:9px}#howTo{font-size:11px;margin-top:7px}
}
@media (min-width:1400px) and (min-height:850px){
  .hCard{padding:12px}.hCard .hIc{width:78px;height:78px}.hCard b{font-size:17px}.hCard em{font-size:11px}
  .hSkills{grid-template-columns:repeat(4,36px);gap:5px}.hCard .hSkills i{width:36px;height:36px}
  .fCard{min-height:100px;padding-left:92px}.fCard .fArt{width:72px;height:72px}.fCard b{font-size:17px}.fCard em{font-size:11px}.fCard small{font-size:10px}
}
@media (max-width:600px){
  #titleCard{width:100%;margin:5px auto;padding:8px}
  #gameLogo{font-size:clamp(30px,10.5vw,43px);letter-spacing:.02em}#gameLogo small{font-size:10px;letter-spacing:.28em}
  #tagline{font-size:9px;line-height:1.25;margin-bottom:5px}.secTitle{font-size:9px;margin:5px 0 3px}
  #heroGrid{grid-template-columns:repeat(2,minmax(0,1fr));gap:5px}
  .hCard{padding:5px}.hCard .hIc{width:42px;height:42px;margin-right:5px}.hCard b{font-size:10px}.hCard em{font-size:7px;min-height:18px;margin-top:1px}
  .hSkills{grid-template-columns:repeat(4,21px);gap:2px;padding-top:4px}.hCard .hSkills i{width:21px;height:21px}
  #factionGrid{gap:5px}.fCard{min-height:58px;padding:6px 5px 5px 50px}.fCard .fArt{width:38px;height:38px;left:5px;top:5px}.fCard b{font-size:10px}.fCard em{font-size:7px}.fCard small{font-size:6.5px;margin-top:2px}
  .setupGrid{grid-template-columns:1fr;gap:1px}.setupBtn{min-height:44px;font-size:11px}.setupBtn small{font-size:7px}
  .diffBtn{min-width:88px;min-height:44px;padding:7px 10px}
  #matchSummary{font-size:7.5px;line-height:1.3;margin-top:5px}#startBtn{min-height:48px;margin-top:6px;font-size:13px;padding:8px 5px}
  #howTo{font-size:7.5px;line-height:1.25;margin-top:5px}
  #shop{padding:8px}#shopGrid{gap:4px}#shopGrid .sItem{flex-basis:calc(50% - 2px)}.sItem{grid-template-columns:34px 1fr;padding:4px}.sItem .ic{width:34px;height:34px}
  #sellGrid{grid-template-columns:repeat(6,44px);gap:3px}.sellSlot{width:44px;height:44px}
}
#endStats{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:7px;margin:14px 0 4px}
@media (max-height:560px){
  body.touch #endCard{width:min(640px,100%);padding:12px 14px 12px}
  body.touch #endTitle{font-size:24px}
  body.touch #endStats{grid-template-columns:repeat(auto-fit,minmax(84px,1fr));gap:5px;margin:8px 0 3px}
  body.touch #endStats>div{padding:5px 4px}
  body.touch #endStats b{font-size:15px}
  body.touch #againBtn{margin-top:8px;padding:8px 24px}
}
.stCell{padding:9px 6px;border:1px solid #514c3a;background:#14120a;border-radius:3px}
.stCell b{display:block;font-size:19px;color:#ffe1a0}
.stCell span{font-size:9px;color:var(--muted);letter-spacing:.08em;text-transform:uppercase}

/* pause */
#pauseVeil{position:absolute;inset:0;z-index:45;display:none;place-items:center;
  background:radial-gradient(circle at 50% 122%,rgba(140,47,6,.18),rgba(4,3,2,.82) 52%);backdrop-filter:blur(3px)}
#pauseVeil.on{display:grid}
#pauseVeil h2{font-size:34px;letter-spacing:.3em;color:var(--dp-bone);
  text-shadow:0 2px 0 #000,0 0 10px rgba(255,122,42,.5),0 0 30px rgba(179,36,28,.4)}
.pauseCard{min-width:340px;max-width:440px;padding:24px 28px 20px;text-align:center}
.pauseCard h2{margin:0 0 16px}
.pauseCard p{margin:10px 0 0;color:var(--muted);font-size:12px;line-height:1.45}
#resumeBtn{min-height:50px;padding:12px 24px;border:2px solid #ffd76a;border-radius:3px;
  background:linear-gradient(180deg,#ffdc84,#e0a234 55%,#a4650f);color:#1a1002;
  font-weight:900;font-size:14px;letter-spacing:.1em;
  box-shadow:0 3px 0 #4a3210,0 0 22px rgba(255,140,40,.28),0 8px 16px rgba(0,0,0,.6)}
#resumeBtn:hover{filter:brightness(1.07);border-color:#fff0b6}
#resumeBtn:active{transform:translateY(2px);box-shadow:0 1px 0 #4a3210}
.pauseActions{display:grid;grid-template-columns:1fr;gap:8px;margin-top:13px}
.pauseActions.two{grid-template-columns:1fr 1fr;margin-top:8px}
/* Restart and Change Setup both throw away the match in progress, but only one of them was
   marked as destructive, and both sat in the same grid as Resume. Anything that ends the
   match now lives in its own labelled block, below a rule, so the row you reach for by
   reflex is the harmless one. */
.pauseHint{margin-top:9px !important;font-size:11px !important;color:#8b8271 !important}
.dangerZone{margin-top:14px;padding-top:12px;border-top:1px solid rgba(179,36,28,.32)}
.dangerLabel{display:block;color:#b08a80;font:700 10px Verdana,sans-serif;letter-spacing:.09em;text-transform:uppercase}

.modalBtn{min-height:42px;padding:0 14px;border:1px solid var(--stone-hi);border-radius:3px;
  background:linear-gradient(180deg,#332b25,#15110e);color:var(--ink);
  font:700 12px Georgia,serif;letter-spacing:.08em;cursor:pointer;
  box-shadow:inset 0 1px 0 rgba(226,208,180,.14),inset 0 -2px 0 rgba(0,0,0,.5);
  transition:border-color .12s,filter .12s}
.modalBtn:hover{filter:brightness(1.22);border-color:var(--gold);color:#ffe9b0}
.modalBtn:active{transform:translateY(1px)}
.modalBtn.danger{color:#d7a79c;border-color:rgba(179,36,28,.55);
  background:linear-gradient(180deg,#2b1b18,#150c0a)}
.modalBtn.danger:hover{border-color:var(--blood);color:#ffcfc4;
  background:linear-gradient(180deg,#4a1c17,#1d0c09);filter:none}
#settingsWrap{position:absolute;inset:0;z-index:80;display:none;align-items:center;justify-content:center;background:#020302c9;backdrop-filter:blur(5px);padding:14px}
#settingsWrap.open{display:flex}
#settingsPanel{width:min(520px,100%);max-height:min(720px,calc(100dvh - 28px));overflow:auto;touch-action:pan-y;-webkit-overflow-scrolling:touch;padding:19px}
.settingsHead{display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #655426;padding-bottom:10px;margin-bottom:8px}
.settingsHead h2{margin:0;font-size:23px;color:#edcd70;letter-spacing:2px}
#settingsClose{width:36px;height:36px;font-size:17px}
.settingsRow{display:grid;grid-template-columns:minmax(120px,1fr) 1.8fr;gap:14px;align-items:center;padding:10px 2px;border-bottom:1px solid #3b3422}
.settingName{font-weight:700;font-size:12px;color:#d9c98f}.settingHint{display:block;margin-top:3px;color:#766e59;font:9px Arial}
.seg{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:4px}
.segBtn{min-height:34px;padding:4px 7px;border:1px solid #514628;background:#11110d;color:#8e856b;font:700 10px Georgia;cursor:pointer}
.segBtn:hover{color:#e5ce84;border-color:#8d7734}.segBtn.on{color:#fff0ad;border-color:#d3a936;background:linear-gradient(#3a311b,#18150d);box-shadow:inset 0 0 9px #d5a92722}
.settingsFoot{margin:12px 0 0;color:#776e59;font:10px Georgia;text-align:center}
.reducedMotion *{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
.highContrast #hud,.highContrast #topbar,.highContrast .wcp{filter:contrast(1.14) saturate(1.08)}
.highContrast .killLine{background:#020302f2}
#planningVeil{position:absolute;left:50%;top:15%;transform:translateX(-50%);z-index:44;display:none;pointer-events:none;text-align:center}
#planningVeil.on{display:block}
.planCard{min-width:330px;padding:11px 22px 12px;background:linear-gradient(180deg,rgba(38,35,25,.96),rgba(13,12,8,.94));box-shadow:0 8px 26px rgba(0,0,0,.62)}
.planCard>small{display:block;font-size:11px;letter-spacing:.28em;text-transform:uppercase;color:#b8a468}
#planCount{display:block;font:900 50px/1 Georgia,serif;color:#ffe49a;text-shadow:0 0 16px rgba(255,205,82,.42),0 3px 0 #000;margin:2px 0}
#planArmy{display:block;font-size:15px;color:#f2e8c6}#planUnit{color:#d8bd6f}
.planCard p{margin:6px 0 8px;font-size:11px;color:#b3a889;letter-spacing:.03em}
#planSkip{pointer-events:auto;padding:7px 20px;border:1px solid #8c7948;background:linear-gradient(#3a3422,#17130b);color:#ead9a5;font-size:12px;font-weight:800;letter-spacing:.08em}
#planningVeil.fight #planCount{color:#9dff86;font-size:43px}#planningVeil.fight .planCard{box-shadow:0 0 30px rgba(100,255,90,.25),0 8px 26px #000}
@media (max-width:760px){#planningVeil{top:11%}.planCard{min-width:270px;padding:8px 14px}#planCount{font-size:38px}}
@media (max-width:680px){
  #killFeed{top:79px;width:56vw}.killLine{font-size:11px;padding:5px 8px}
  #eventBar{top:38px;min-width:210px;padding:5px 9px}#eventName{font-size:11px}#eventMeta{font-size:9px}
  .settingsRow{grid-template-columns:1fr;gap:7px;padding:8px 2px}.settingsHead h2{font-size:19px}
  .pauseActions{grid-template-columns:1fr}.pauseActions .modalBtn:first-child{grid-column:auto}
}

/* end screen */
#endVeil{position:absolute;inset:0;z-index:62;display:none;justify-items:center;align-content:safe center;overflow:auto;
  padding:max(4px,var(--sat)) max(4px,var(--sar)) max(4px,var(--sab)) max(4px,var(--sal));background:rgba(3,2,1,.66)}
#endVeil.on{display:grid}
#endCard{width:min(440px,100%);max-height:100%;overflow:auto;padding:22px 24px 20px;text-align:center;animation:annIn .45s cubic-bezier(.2,1.5,.4,1) both}
#endTitle{font-size:36px;font-weight:900;letter-spacing:.14em;margin-bottom:4px}
#endTitle.win{color:var(--goldhi);text-shadow:0 0 26px rgba(240,200,90,.5),0 2px 0 #000}
#endTitle.lose{color:#e05540;text-shadow:0 0 26px rgba(220,60,40,.4),0 2px 0 #000}
#endSub{font-size:12px;color:#cabfa0}
#againBtn{margin-top:12px;padding:9px 34px;font-size:14px;font-weight:800;letter-spacing:.08em;color:#1c1204;
  border:2px solid #f5dd94;border-radius:5px;background:linear-gradient(180deg,#f5dd94,#c8973c 60%,#9c6f22);
  box-shadow:0 3px 0 #4a3210,0 7px 14px rgba(0,0,0,.6)}
#againBtn:active{transform:translateY(2px);box-shadow:0 1px 0 #4a3210}
#replayBtn{margin-top:10px;padding:7px 18px;border:1px solid #6d644a;background:linear-gradient(#302b1e,#15120b);color:#cfc39d;font:800 9px Verdana,sans-serif;letter-spacing:.08em}
#rematchBtn{margin-top:12px;padding:9px 20px;font-size:12px;font-weight:900;color:#1c1204;border:2px solid #f5dd94;border-radius:5px;background:linear-gradient(180deg,#f5dd94,#c8973c 60%,#9c6f22)}

/* tooltip */
#tip{position:absolute;z-index:70;max-width:290px;padding:9px 11px;font-size:12px;line-height:1.45;color:#e8e0c4;
  background:linear-gradient(#26231a,#100e08);border:1px solid var(--gold);border-radius:3px;pointer-events:none;display:none;
  box-shadow:0 6px 16px rgba(0,0,0,.6)}
#tip b{color:#ffe9a8;display:block;font-size:14px;margin-bottom:2px}
#tip i{color:#c39a52;font-style:normal;display:block;margin-top:3px}

/* ================= loading screen =================
   Shown until the art is decoded, so the lobby never pops in half-painted.
   Uses the same gold-on-stone language as .wcp rather than a second style. */
#loadVeil{position:fixed;inset:0;z-index:120;display:grid;place-items:center;
  background:radial-gradient(circle at 50% 42%,#171309 0%,#0a0806 58%,#050403 100%);
  transition:opacity .5s ease}
#loadVeil.done{opacity:0;pointer-events:none}
#loadCard{width:min(540px,88vw);text-align:center;padding:0 18px}
#loadLogo{margin:0 0 24px;font-size:clamp(26px,6vw,46px);font-weight:400;letter-spacing:.10em;
  color:#c8a24a;background:linear-gradient(180deg,#f9ecc0,#c8a24a 52%,#7a6430);
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;
  filter:drop-shadow(0 3px 10px rgba(0,0,0,.75))}
#loadBar{height:15px;border:2px solid var(--edge);outline:2px solid #0a0908;border-radius:3px;
  background:linear-gradient(180deg,#14120d,#0a0908);overflow:hidden;
  box-shadow:inset 0 0 0 1px rgba(242,214,136,.14),0 4px 14px rgba(0,0,0,.5)}
#loadBar i{display:block;height:100%;width:0;
  background:linear-gradient(180deg,#f2d688,#c8a24a 58%,#7a6430);
  box-shadow:0 0 10px rgba(242,214,136,.45);transition:width .2s ease}
#loadStatus{margin-top:12px;font:800 10px Verdana,sans-serif;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted)}
#loadStatus b{margin-left:9px;color:var(--goldhi);font-variant-numeric:tabular-nums}
#loadTip{margin:22px auto 0;max-width:46ch;font-size:12.5px;line-height:1.65;color:#8d856f;font-style:italic}

/* Army order buttons were a hard 47px wide, which clipped FOLLOW / DEFEND /
   ASSAULT / MASTERY. Size them to their label instead, with padding that clears
   the absolutely-positioned hotkey (top-left) and cost (bottom-right) badges. */
.armyBtn{width:auto;min-width:47px;padding:0 8px 0 12px}
#racialBtn{width:auto;min-width:62px}

/* ---- hero card layout ----
   The portrait used float:left, so any name too wide to sit beside it ("Swordmaster",
   "Demon Hunter", "Pyromancer") wrapped underneath and that card no longer matched
   its row. An explicit grid pins the portrait, text and skill row in place. */
.hCard{display:grid;grid-template-columns:auto minmax(0,1fr);
  grid-template-areas:"ic name" "ic role" "sk sk";column-gap:8px;align-content:start}
.hCard .hIc{grid-area:ic;float:none;margin:0}
.hCard b{grid-area:name;align-self:end}
.hCard em{grid-area:role;align-self:start}
.hCard .hSkills{grid-area:sk}

/* ================= 8BIT DEATH PIT theme =================
   A generated pixel display face, embedded locally so the build stays offline.
   Native glyph size is 32px, so it is used at 16/32/48/64 where it stays crisp —
   body copy keeps the serif, because a 32px pixel face at 10px is unreadable. */
@font-face{
  font-family:"DeathPit";
  src:url("art/font/deathpit.ttf") format("truetype");
  font-display:block;
}
.pixelType{font-family:"DeathPit",Verdana,sans-serif;letter-spacing:.04em;
  -webkit-font-smoothing:none;font-smooth:never}

/* ---- intro ---- */
#loadVeil{background:radial-gradient(ellipse at 50% 118%,#2a1408 0%,#0b0705 42%,#040303 100%)}
#pitGlow{position:absolute;left:50%;bottom:-32vh;width:120vw;height:70vh;transform:translateX(-50%);
  background:radial-gradient(ellipse at 50% 50%,rgba(214,122,38,.20),rgba(140,60,16,.07) 45%,transparent 70%);
  pointer-events:none;animation:pitBreathe 5.5s ease-in-out infinite}
@keyframes pitBreathe{0%,100%{opacity:.55}50%{opacity:1}}
#loadCard{position:relative}
#loadCrest{display:block;margin:0 auto 14px;width:104px;height:104px;image-rendering:pixelated;
  filter:drop-shadow(0 6px 14px rgba(0,0,0,.8)) drop-shadow(0 0 18px rgba(226,138,44,.35));
  animation:crestDrop .5s steps(6) both}
@keyframes crestDrop{from{opacity:0;transform:translateY(-26px) scale(.82)}to{opacity:1;transform:none}}
#loadLogo{font-family:"DeathPit",Verdana,sans-serif;margin:0;line-height:1;
  -webkit-text-fill-color:currentColor;background:none;filter:none;color:#f2d688}
#loadLogo .lg1{display:block;font-size:clamp(13px,2.4vw,19px);letter-spacing:.62em;
  color:#9d7f3f;margin-bottom:9px;animation:lgIn .4s steps(5) both .18s}
#loadLogo .lg2{display:block;font-size:clamp(30px,7.4vw,62px);letter-spacing:.06em;
  color:#f6e3a6;text-shadow:0 3px 0 #6b4a12,0 6px 0 #2b1d07,0 0 26px rgba(226,138,44,.4);
  animation:lgSlam .34s steps(5) both .3s}
@keyframes lgIn{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
@keyframes lgSlam{from{opacity:0;transform:scale(1.5)}to{opacity:1;transform:scale(1)}}
#loadRule{width:min(430px,74vw);height:3px;margin:18px auto 16px;
  background:linear-gradient(90deg,transparent,#c8a24a 18%,#f2d688 50%,#c8a24a 82%,transparent);
  animation:ruleWipe .45s steps(7) both .58s}
@keyframes ruleWipe{from{transform:scaleX(0)}to{transform:scaleX(1)}}
#loadBar,#loadStatus,#loadTip{animation:fadeUp .4s steps(5) both .72s}
@keyframes fadeUp{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}
#loadStatus{font-family:"DeathPit",Verdana,sans-serif;font-size:11px;letter-spacing:.2em}

/* ---- menu + panel headings take the pixel face ---- */
#gameLogo{font-family:"DeathPit",Verdana,sans-serif;letter-spacing:.05em}
.logoCrest{display:block;margin:0 auto 6px;width:54px;height:54px;image-rendering:pixelated;
  filter:drop-shadow(0 3px 7px rgba(0,0,0,.75))}
.secTitle{font-family:"DeathPit",Verdana,sans-serif;letter-spacing:.18em}
#startBtn,.modalBtn,#againBtn,#rematchBtn{font-family:"DeathPit",Verdana,sans-serif;letter-spacing:.08em}
#endTitle,.pauseCard h2,#talentPanel h3,#settingsTitle{font-family:"DeathPit",Verdana,sans-serif;letter-spacing:.09em}
#planCount{font-family:"DeathPit",Verdana,sans-serif}
#eventName,#announce .annLine{font-family:"DeathPit",Verdana,sans-serif;letter-spacing:.09em}

/* The display face is 32px native, so it only stays crisp at 16/32/48/64. Anything
   smaller turns to mush — those places keep the sans. */
#gameLogo small{font-family:Verdana,sans-serif;letter-spacing:.5em}
.secTitle{font-size:16px;letter-spacing:.16em}
@media (max-width:900px),(max-height:640px){
  .secTitle{font-family:Verdana,sans-serif;font-size:10px;letter-spacing:.22em}
}
#loadStatus{font-size:12px}

/* Hero names are single long words ("Swordmaster", "Sharpshooter") in a six-column
   grid, so a fixed size overflows the card. Scale with the viewport instead. */
.hCard b{font-size:clamp(11px,1.08vw,16px);line-height:1.15}

/* ---- in-match chooser (hero at muster, warband at first tier) ---- */
#chooseWrap{position:absolute;inset:0;z-index:62;display:none;justify-items:center;align-content:safe center;touch-action:pan-y;
  padding:max(4px,var(--sat)) max(4px,var(--sar)) max(4px,var(--sab)) max(4px,var(--sal));overflow:auto;
  background:rgba(3,2,1,.76);backdrop-filter:blur(2px)}
#chooseWrap.open{display:grid}
#choosePanel{width:min(940px,100%);max-height:100%;overflow:auto;touch-action:pan-y;-webkit-overflow-scrolling:touch;padding:18px}
#choosePanel h3{margin:0 0 2px;text-align:center;color:#f0d77f;letter-spacing:.12em;
  font-family:"DeathPit",Verdana,sans-serif;font-size:22px}
#choosePanel>p{margin:0 0 12px;text-align:center;color:#a99f82;font:10px Verdana,sans-serif;letter-spacing:.08em}
#chooseGrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
#chooseGrid.heroes{grid-template-columns:repeat(6,minmax(0,1fr))}
.chooseCard{position:relative;padding:9px;border:2px solid #4c4736;outline:1px solid #0a0908;border-radius:4px;
  background:linear-gradient(#26231733,#12100a);text-align:left;color:var(--ink);cursor:pointer}
.chooseCard:hover{border-color:var(--goldhi);box-shadow:0 0 0 1px var(--goldhi),0 0 16px rgba(240,214,136,.22)}
.chooseCard .cIc{display:block;width:58px;height:58px;margin:0 auto 6px;border:1px solid #82744e;background:#1c1a10;
  background-repeat:no-repeat;background-size:cover;background-position:center;box-shadow:inset 0 0 9px #000;
  image-rendering:pixelated}
.chooseCard b{display:block;text-align:center;font-size:12px;color:#f2e8c6;line-height:1.15}
.chooseCard em{display:block;text-align:center;font-style:normal;font-size:9px;color:var(--muted);margin-top:2px}
.chooseCard small{display:block;text-align:center;font-size:8.5px;color:#8d856f;margin-top:4px;line-height:1.35}
@media(max-width:760px){
  #chooseGrid.heroes{grid-template-columns:repeat(4,minmax(0,1fr))}
  #chooseGrid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .chooseCard .cIc{width:46px;height:46px}
}

/* ---- 8BIT DEATH PIT wordmark ----
   "8BIT" is a character shorter than the old kicker, so it needs wider tracking and
   flanking rules to still span properly beneath the crest instead of reading thin. */
#loadCrest{width:120px;height:120px}
#loadLogo .lg1{
  font-size:clamp(14px,2.6vw,21px);letter-spacing:.98em;text-indent:.98em;
  color:#c9a659;display:flex;align-items:center;justify-content:center;gap:14px}
#loadLogo .lg1::before,#loadLogo .lg1::after{
  content:"";height:2px;width:clamp(26px,7vw,74px);
  background:linear-gradient(90deg,transparent,#8a6f33);flex:none}
#loadLogo .lg1::after{background:linear-gradient(90deg,#8a6f33,transparent)}
#loadLogo .lg2{
  letter-spacing:.05em;
  text-shadow:0 3px 0 #6b4a12,0 6px 0 #2b1d07,0 8px 0 #171004,0 0 30px rgba(226,138,44,.45)}
/* lobby wordmark: same kicker treatment, smaller */
#gameLogo{letter-spacing:.04em}
.logoCrest{width:62px;height:62px;margin-bottom:4px}

/* the lobby now explains the unsworn opening instead of listing heroes */
#lobbyNote{max-width:70ch;margin:2px auto 10px;text-align:center;font-size:11.5px;
  line-height:1.55;color:#9d947c;font-style:italic}
#loadLogo .lg1{color:#e2c078}

/* ---- roster bar ----
   Unsworn: four warband buttons. Sworn: a compact badge plus that warband's troop
   lines, one of which is active. Either state is a single row that fits. */
.facBadge{position:relative;display:flex;flex-direction:column;justify-content:center;
  min-width:58px;height:38px;padding:4px 8px;border:1px solid #6b6349;border-radius:3px;
  background:linear-gradient(#2b2519,#14100a);text-align:center;pointer-events:auto}
.facBadge b{display:block;color:#f2e2b0;font:900 10px/1.15 Verdana,sans-serif}
.facBadge small{display:block;font:900 6px Verdana,sans-serif;color:#8d8569;letter-spacing:.12em}
.facBtn small{color:#9a8e78}
.rosterBtn.active{border-color:#ffe18c;box-shadow:inset 0 0 9px rgba(255,211,94,.26)}

/* ---- roster bar relocated into the HUD ----
   It used to float over the battlefield top-left. Now it is the first row of the
   battle panel, with the three intel blocks compressed underneath to make room. */
#battlePanel{grid-template-rows:auto minmax(0,1fr);row-gap:7px}
#rosterBar{position:static;grid-column:1 / -1;display:flex;flex-wrap:nowrap;gap:4px;
  padding:0;background:none;border:0;outline:0;box-shadow:none;transform:none;
  pointer-events:auto;overflow:hidden}
.facBtn{width:auto;min-width:52px;height:36px;padding:3px 8px}
.facBtn b{font-size:11px}.facBtn small{font-size:9px}
.facBadge{min-width:58px;height:36px;padding:3px 9px}
.facBadge b{font-size:12px}
.rosterBtn{width:auto;min-width:82px;flex:1 1 0;height:36px;padding:4px 7px 3px}
.rosterBtn b{font-size:11px}
.rosterBtn small{font-size:9px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ============================================================================
   APP-ICON RE-SKIN — 8-BIT DEATH PIT
   The icon is now the art direction of record: a mortared cool-grey stone frame
   lit by torches, four warband banners at the corners, and a spiked lava pit at
   the centre. The wordmark is three inks, never one — gold "8-BIT", blood-red
   "DEATH", bone "PIT" — each with a hard dark outline and a coloured drop face.
   Re-pointing the original tokens here means every earlier rule inherits the new
   palette without having to be rewritten.
   ========================================================================== */
:root{
  /* Stone — charred iron and ash. This was a cool purple-grey taken from the app icon's
     frame, and it read as generic fantasy-magic rather than a pit: lavender panels do not
     say "arena floor you bleed on". Warm char keeps the icon's *value* structure (dark
     frame, bright inks) while the hue now agrees with the fire and blood everything else
     is made of. */
  --stone-hi:#6d6055; --stone:#463c33; --stone-lo:#251f1a; --mortar:#130f0c;
  /* the pit's own light: embers below, soot above */
  --ember:#ff7a2a; --ember-lo:#8c2f06; --ash:#1a1512; --char:#0b0806;
  --blood:#b3241c; --blood-lo:#5d100c;
  /* the three wordmark inks and the outline they share */
  --dp-gold:#ffc21c; --dp-gold-lo:#a86408;
  --dp-red:#e8342a;  --dp-red-lo:#8b150f;
  --dp-bone:#dad3c3; --dp-bone-lo:#6f6a5d;
  --dp-out:#150d06;
  /* the pit */
  --lava-hi:#ff9a1f; --lava:#e8410c; --lava-lo:#7a1604; --flame:#ffb32c;
  /* warband banners, reading clockwise from the icon's top-left */
  --fac-human:#3f74d8; --fac-orc:#5fa32e; --fac-elf:#2f9160; --fac-undead:#8d4ec9;
  /* existing tokens, re-aimed at the icon */
  --gold:#d8a12c; --goldhi:#ffd54a; --golddim:#7f5a16;
  --ink:#e9e0cb; --muted:#9a8e78;
  --panel1:#3b322b; --panel2:#171310; --edge:#6a5d51;
}
html,body{background:#080605}
#app{background:#080605}

/* ---- panels take the icon's mortared stone ----
   A warm inset highlight on top and a cold one underneath give the block the
   same bevel the icon's frame has. */
/* Iron plate lit from underneath. The ember wash sits at the BOTTOM of the panel because
   the light source in this game is the pit — a top-lit panel reads as daylight and fought
   the whole premise. Soot gathers at the top edge instead. */
.wcp{
  background:
    radial-gradient(120% 80% at 50% 118%, rgba(255,122,42,.13), transparent 62%),
    linear-gradient(180deg, var(--ash) 0%, #181310 40%, var(--char) 100%);
  border:2px solid var(--stone-hi);
  outline:2px solid var(--char);
  box-shadow:
    inset 0 2px 0 rgba(214,196,168,.16),
    inset 0 -3px 0 rgba(0,0,0,.6),
    inset 0 -14px 26px rgba(255,110,30,.06),
    inset 0 0 0 1px rgba(255,180,90,.09),
    /* blood hairline under the top lip — done as a shadow, not a pseudo-element, because
       #titleCard already owns ::after for the warband corner glows */
    inset 0 4px 0 -3px rgba(179,36,28,.5),
    0 10px 30px rgba(0,0,0,.72);
}
.goldtrim::before{border-color:rgba(216,161,44,.34)}

/* ---- the wordmark ----
   Built to match the icon's lockup rather than merely borrow its colours:
     · the three words stack tight enough to almost touch, as one block
     · 8-BIT and DEATH are near the same size; PIT is smaller and tightly set
     · a skull sits over the I of PIT
     · every letter carries a thick dark outline, a coloured drop face, and a
       lighter bevel across its top half
   The outline is eight offset shadows rather than -webkit-text-stroke, which
   centres itself and would eat into the weight of a pixel face. The bevel is a
   duplicate of the word (from data-t) filled with a gradient clipped to the text
   and laid exactly over the original — a gradient on the original itself would
   need a transparent fill, and the outline shadows would then show straight
   through the letters. */
/* The face carries a lot of internal leading, so even line-height:.86 left the three
   words floating apart. The icon sets them as one tight block. */
.dpLogo{font-family:"DeathPit",Verdana,sans-serif;line-height:.66;margin:0;text-align:center}
.dpLogo span{display:block;position:relative;-webkit-text-fill-color:currentColor;background:none;filter:none}
/* Offsets are in em so the outline and the extrusion stay in proportion as the lockup
   scales from a phone lobby up to a full-bleed intro.

   The extrusion is a STACK of copies at small steps, not one copy at the final depth.
   A single copy leaves the span between the outline and the face unpainted, and at
   hero size that gap opens into a visible band — the drop faces read as slabs floating
   loose under the letters. Each step must be smaller than the gap it fills, and the
   first must start inside the outline, or the seam reappears. */
.dp1,.dp2,.dp3{
  text-shadow:
    /* outline */
    -.042em 0 0 var(--dp-out), .042em 0 0 var(--dp-out),
    0 -.042em 0 var(--dp-out), 0 .042em 0 var(--dp-out),
    -.042em -.042em 0 var(--dp-out), .042em -.042em 0 var(--dp-out),
    -.042em .042em 0 var(--dp-out), .042em .042em 0 var(--dp-out),
    /* solid extrusion */
    0 .04em 0 var(--face), 0 .06em 0 var(--face), 0 .08em 0 var(--face),
    0 .10em 0 var(--face), 0 .12em 0 var(--face), 0 .14em 0 var(--face),
    0 .16em 0 var(--face),
    /* dark bottom edge, then ambient */
    0 .185em 0 var(--dp-out), 0 .205em 0 var(--dp-out),
    0 .28em .3em rgba(0,0,0,.8);
}
/* the lit top half of each letter */
.dp1::after,.dp2::after,.dp3::after{
  content:attr(data-t);position:absolute;inset:0;z-index:1;pointer-events:none;
  letter-spacing:inherit;text-indent:inherit;
  /* the lit face is most of the letter, with only the lower band left in the base
     tone — split at the midpoint the letters read as two stacked pieces */
  background:linear-gradient(180deg,var(--lit) 0 64%,transparent 64%);
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;text-shadow:none;
}
/* The face's cap height is roughly half its em, so the words need pulling together
   past what line-height alone can do — but not past the extrusion, which now hangs
   .205em below each glyph. At -.16em the word above drove its drop face down through
   the word below. */
.dp2,.dp3{margin-top:-.04em}
.dp1{--face:var(--dp-gold-lo);--lit:#ffd856;color:var(--dp-gold);letter-spacing:.01em}
.dp2{--face:var(--dp-red-lo);--lit:#f7503f;color:var(--dp-red);letter-spacing:.01em}
.dp3{--face:var(--dp-bone-lo);--lit:#ece5d7;color:var(--dp-bone);letter-spacing:.06em;text-indent:.06em}
/* the skull rides over the I, the way the icon sets it, while the I stays in flow
   so the bevel overlay above still lines up character for character */
.dpSkull{position:relative;z-index:2;font-style:normal}
.dpSkull::before{
  /* sized against the face's cap height, not the em — the em is far taller here,
     and a skull scaled to it buries the P and the T */
  content:"";position:absolute;left:50%;top:47%;width:.46em;height:.46em;
  transform:translate(-50%,-50%);
  background:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' shape-rendering='crispEdges'><rect x='2' y='1' width='12' height='11' fill='%23150d06'/><rect x='3' y='11' width='10' height='4' fill='%23150d06'/><rect x='3' y='2' width='10' height='9' fill='%23dad3c3'/><rect x='4' y='11' width='8' height='3' fill='%23dad3c3'/><rect x='3' y='2' width='10' height='3' fill='%23f4efe4'/><rect x='5' y='5' width='2' height='3' fill='%23150d06'/><rect x='9' y='5' width='2' height='3' fill='%23150d06'/><rect x='7' y='8' width='2' height='2' fill='%23150d06'/><rect x='6' y='12' width='1' height='2' fill='%23150d06'/><rect x='9' y='12' width='1' height='2' fill='%23150d06'/></svg>") center/contain no-repeat;
  filter:drop-shadow(0 3px 0 rgba(21,13,6,.9));
}

/* ---- loading screen: you are looking down into the pit ---- */
#loadVeil{
  background:
    radial-gradient(ellipse 80% 46% at 50% 104%, rgba(232,65,12,.34) 0%, rgba(122,22,4,.14) 40%, transparent 72%),
    radial-gradient(ellipse at 50% 30%, #221c2e 0%, #100c18 46%, #06040a 100%);
}
/* the icon's stone surround, pulled around the whole viewport.
   Four repeating gradients — one per edge — lay courses of block and mortar, so
   the frame reads as masonry rather than as a flat coloured border. */
#loadFrame{
  --bw:clamp(14px,2.1vw,26px);
  position:absolute;inset:0;pointer-events:none;z-index:5;
  background:
    /* bevel per edge, lit from outside, sitting over the courses below */
    linear-gradient(180deg,rgba(180,170,205,.20),rgba(0,0,0,.45)) top/100% var(--bw) no-repeat,
    linear-gradient(0deg,  rgba(150,140,175,.13),rgba(0,0,0,.5))  bottom/100% var(--bw) no-repeat,
    linear-gradient(90deg, rgba(180,170,205,.16),rgba(0,0,0,.45)) left/var(--bw) 100% no-repeat,
    linear-gradient(270deg,rgba(180,170,205,.16),rgba(0,0,0,.45)) right/var(--bw) 100% no-repeat,
    repeating-linear-gradient(90deg,var(--stone-lo) 0 42px,var(--mortar) 42px 47px) top/100% var(--bw) repeat-x,
    repeating-linear-gradient(90deg,var(--stone-lo) 0 42px,var(--mortar) 42px 47px) bottom/100% var(--bw) repeat-x,
    repeating-linear-gradient(0deg, var(--stone-lo) 0 42px,var(--mortar) 42px 47px) left/var(--bw) 100% repeat-y,
    repeating-linear-gradient(0deg, var(--stone-lo) 0 42px,var(--mortar) 42px 47px) right/var(--bw) 100% repeat-y;
}
/* bevel: a lit outer lip, a dark inner shadow, and a vignette into the pit */
#loadFrame::before{
  content:"";position:absolute;inset:0;
  box-shadow:
    inset 0 0 0 2px rgba(160,150,190,.34),
    inset 0 0 0 var(--bw) rgba(0,0,0,.001),
    inset 0 0 0 calc(var(--bw) + 2px) rgba(0,0,0,.55),
    inset 0 0 70px 22px rgba(0,0,0,.6);
}
/* the four warband banners, one to a corner, as the icon arranges them */
#loadVeil::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  background:
    radial-gradient(circle at 3% 4%,   rgba(63,116,216,.16), transparent 26%),
    radial-gradient(circle at 97% 4%,  rgba(95,163,46,.16),  transparent 26%),
    radial-gradient(circle at 3% 96%,  rgba(47,145,96,.16),  transparent 26%),
    radial-gradient(circle at 97% 96%, rgba(141,78,201,.16), transparent 26%);
}
#pitGlow{
  background:radial-gradient(ellipse at 50% 50%,rgba(255,154,31,.26),rgba(232,65,12,.10) 44%,transparent 70%);
}
/* torch pair in the top corners — the icon's light source */
.torch{position:absolute;top:0;width:34vw;height:46vh;pointer-events:none;z-index:1;
  background:radial-gradient(ellipse at 50% 0%,rgba(255,179,44,.20),rgba(255,106,16,.07) 40%,transparent 68%);
  animation:torchFlicker 2.7s steps(4) infinite}
#torchL{left:-6vw}
#torchR{right:-6vw;animation-delay:-1.35s}
@keyframes torchFlicker{0%,100%{opacity:.72}35%{opacity:1}60%{opacity:.62}80%{opacity:.92}}
/* the near rim of the pit: a row of bone spikes, drawn as an inline SVG tile so
   the points stay geometrically exact at any width */
#pitSpikes{
  --bw:clamp(14px,2.1vw,26px);
  position:absolute;left:var(--bw);right:var(--bw);bottom:var(--bw);
  height:clamp(20px,3.4vh,32px);z-index:4;pointer-events:none;
  background:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='28' viewBox='0 0 20 28'><polygon points='10,0 16,28 4,28' fill='%23b8b0a0'/><polygon points='10,0 16,28 10,28' fill='%236e685c'/></svg>") repeat-x bottom/20px 100%;
  filter:drop-shadow(0 -3px 7px rgba(0,0,0,.75));
  animation:fadeUp .5s steps(5) both .5s;
}
/* the real app icon, when present, is the centrepiece and the wordmark stands down */
#logoArt{display:block;width:min(300px,62vw);margin:0 auto 18px;image-rendering:pixelated;
  border-radius:clamp(8px,1.6vw,18px);
  box-shadow:0 10px 34px rgba(0,0,0,.8),0 0 44px rgba(232,65,12,.22);
  animation:crestDrop .5s steps(6) both}
#loadCard:has(#logoArt) #loadCrest,
#loadCard:has(#logoArt) #loadLogo{display:none}
#loadCard{z-index:4}

/* ---- crest demoted to a watermark ----
   Sitting above the title at 104px it read as a second focal point competing with
   the wordmark. Behind it, large and faint, it still brands the screen without
   taking the eye. It leaves the flow entirely so the title owns the centre. */
#loadCrest{
  position:absolute;left:50%;top:50%;width:min(78vw,58vh);height:auto;
  transform:translate(-50%,-52%);
  /* Blurred on purpose. The emblem is a ram skull in a ring, and left sharp its horns
     and stonework cut hard-edged shapes straight through the letters — behind a hero
     title it has to read as depth, not as a second picture. */
  opacity:.09;z-index:0;pointer-events:none;
  filter:blur(5px) drop-shadow(0 0 40px rgba(255,154,31,.45));
  /* NOT crestDrop — that one ends on opacity:1 / transform:none, and with
     fill-mode:both those final values win over the rule above, which would leave
     the crest fully opaque and knocked off centre */
  animation:crestWatermark .6s steps(6) both;
}
@keyframes crestWatermark{
  from{opacity:0;transform:translate(-50%,-58%) scale(.86)}
  to{opacity:.075;transform:translate(-50%,-52%) scale(1)}
}
#loadLogo{color:var(--dp-bone);position:relative;z-index:1}
/* ---- the title is the hero of both screens ----
   Sized so the three words read as one big block, not as a caption over a crest.
   8-BIT is set larger than DEATH so the two come out the same WIDTH: the face is
   near-monospaced, and "8-BIT" spends one of its five slots on a hyphen, so equal
   font-sizes would leave it visibly short. PIT is smaller again, as in the icon.
   Each size is capped on vh as well as vw, or a short landscape window would push
   the progress bar and the tips off the bottom of the screen. */
#loadLogo .dp1{font-size:min(21.9vw,25vh)}
#loadLogo .dp2{font-size:min(19vw,21.7vh)}
#loadLogo .dp3{font-size:min(16.2vw,18.5vh)}
/* Clear the bottom rim — the frame is up to 26px and the spikes stand up to 32px
   inside it. Padding alone cannot guarantee this: the card is centred in a grid, so
   growing it only lifts the content by half the padding. On a landscape phone, where
   there is genuinely no room, the tip line drops instead of colliding with the teeth. */
#loadCard{padding-bottom:clamp(34px,7vh,66px)}
@media (max-height:600px){#loadTip{display:none}}
#loadRule{margin:clamp(8px,1.6vh,18px) auto clamp(8px,1.4vh,16px)}
#loadRule{height:4px;background:linear-gradient(90deg,transparent,var(--dp-gold-lo) 12%,var(--dp-gold) 50%,var(--dp-gold-lo) 88%,transparent);
  box-shadow:0 0 12px rgba(255,194,28,.35)}
/* The display face is 32px native and turns to mush below 16px — at 12px its
   digits read as letters ("100%" came out "IOOT"), so the status line keeps the sans. */
#loadStatus{font-family:Verdana,sans-serif;font-size:10px;letter-spacing:.18em}
#loadBar{border-color:var(--stone-hi);outline-color:var(--mortar);
  background:linear-gradient(180deg,#120f1a,#08060c)}
#loadBar i{background:linear-gradient(180deg,var(--lava-hi),var(--lava) 58%,var(--lava-lo));
  box-shadow:0 0 12px rgba(255,154,31,.55)}
#loadStatus b{color:var(--dp-gold)}

/* ---- lobby ---- */
#veil{background:
  radial-gradient(ellipse 70% 40% at 50% 100%, rgba(232,65,12,.16) 0%, transparent 68%),
  radial-gradient(120% 90% at 50% 6%, #262032 0%, #14101c 44%, #07050b 100%)}
/* the lobby carries a full setup form underneath, so the same lockup is capped
   harder on height — still the hero, but it cannot crowd out the controls */
#gameLogo .dp1{font-size:min(15vw,17.3vh)}
#gameLogo .dp2{font-size:min(13vw,15vh)}
#gameLogo .dp3{font-size:min(11.1vw,12.8vh)}
#gameLogo{position:relative}
#gameLogo small{position:relative;z-index:1;color:#a2957c;-webkit-text-fill-color:#a2957c}
/* same demotion in the lobby — behind the words, not stacked above them */
.logoCrest{
  position:absolute;left:50%;top:54%;width:min(42vw,34vh);height:auto;
  transform:translate(-50%,-50%);
  /* fainter than the intro's: in the lobby the tagline runs directly beneath the
     title, and at .09 the crest's ring showed through and tinted those words */
  margin:0;opacity:.07;z-index:0;pointer-events:none;
  filter:blur(4px) drop-shadow(0 0 30px rgba(255,154,31,.4));
}
#gameLogo{margin-bottom:clamp(6px,1.4vh,16px)}

/* the four warband inks, so the lobby carries the icon's corner banners */
#titleCard::after{
  content:"";position:absolute;inset:0;pointer-events:none;border-radius:4px;
  background:
    radial-gradient(circle at 0% 0%,    rgba(63,116,216,.16), transparent 30%),
    radial-gradient(circle at 100% 0%,  rgba(95,163,46,.16),  transparent 30%),
    radial-gradient(circle at 0% 100%,  rgba(47,145,96,.16),  transparent 30%),
    radial-gradient(circle at 100% 100%,rgba(141,78,201,.16), transparent 30%);
}

/* ---- barracks tier ladder ----
   The roster bar used to be three buttons you chose between. There is no choice any
   more — a warband's five tiers are fixed, so the bar is a read-only ladder showing
   what you have bought, what you are training, and what is still ahead. Steps are
   deliberately not buttons: nothing here is clickable, and it should not invite a click. */
/* Five steps plus the warband badge have to share one HUD row, so the steps shrink
   rather than wrap — at the old min-width the last two fell off the end of the bar. */
.tierStep{cursor:default;pointer-events:auto;min-width:0;flex:1 1 0;overflow:hidden;text-align:center}
.tierStep.active{flex:4.2 1 0;text-align:left;padding-right:16px}
.tierStep b,.tierStep small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
.tierStep.locked{opacity:.4}
.tierStep.locked b{color:#9a8e78}
.tierStep.owned{opacity:.72;border-color:#4a4038}
.tierStep.owned::after{content:"·";position:absolute;right:4px;top:1px;color:#8a7d68;font-size:11px}
.tierStep.active{border-color:var(--dp-gold);box-shadow:inset 0 0 10px rgba(255,194,28,.24)}
.tierStep.active b{color:#ffe9a8}

/* ---- controls ----
   Secondary controls become carved stone; START stays the one gold object on the
   screen, matched to the icon's title gold so it reads as the same material. */
.setupBtn,.diffBtn,.lobbyUtility button,.stCell{
  background:linear-gradient(180deg,var(--stone-lo),var(--mortar));
  border-color:var(--stone-hi);color:#dbcfb4;
}
.setupBtn small{color:#998c76}
.setupBtn:hover,.diffBtn:hover,.lobbyUtility button:hover{border-color:var(--dp-gold)}
.setupBtn.sel,.diffBtn.sel{
  border-color:var(--dp-gold);color:#ffe9a8;
  background:linear-gradient(180deg,#4a3d22,#1d1710);
  box-shadow:inset 0 0 12px rgba(255,194,28,.22);
}
.lobbyUtility button{color:var(--dp-gold)}
.stCell b{color:var(--dp-gold)}
.modalBtn,#againBtn,#rematchBtn,#replayBtn{
  background:linear-gradient(180deg,var(--stone-lo),var(--mortar));
  border-color:var(--stone-hi);color:var(--goldhi);
}
.modalBtn:hover,#againBtn:hover,#rematchBtn:hover,#replayBtn:hover{border-color:var(--goldhi)}
#startBtn,#resumeBtn{
  border-color:#ffd54a;
  background:linear-gradient(180deg,#ffd54a,var(--dp-gold) 52%,var(--dp-gold-lo));
  box-shadow:0 0 26px rgba(255,194,28,.34),0 4px 0 #4a2c06,0 8px 20px rgba(0,0,0,.65);
  color:#241505;
}
/* the one destructive action wears the wordmark's blood red */
.modalBtn.danger{color:#f0a79c;border-color:var(--dp-red-lo)}
.modalBtn.danger:hover{border-color:var(--dp-red);color:#ffd0c6}
.rosterBtn.active::after{top:1px;right:3px;font-size:9px}
.rosterSep{margin:0 2px}

/* the three intel blocks give up some height for the row above */
.battleIntel{padding:7px 9px 15px}
.battleIntel small{margin-bottom:5px;font-size:10px;letter-spacing:.1em}
.battleIntel b{font-size:14px}
.battleIntel span{margin-top:4px;font-size:10.5px;line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.battleIntel em{bottom:6px}

/* Below 1100px the intel blocks were already hidden, leaving the panel as a host for nothing
   but the roster row. Giving it a min-width so the roster fit pushed the command card ~97px
   off the right edge of a 1000px viewport; leaving it to flex-shrink squeezed it to ~99px and
   clipped the roster anyway. The panel is hidden outright instead. Nothing is lost that is
   not shown elsewhere — the standings panel already names every player warband, and your own
   is on the barracks upgrade tooltip.
   The cutoff is 1180, not 1100: between those the panel is squeezed under ~200px and every
   line in it truncates to an ellipsis. Showing fewer things legibly beats showing all of them
   illegibly, which is the whole point of this pass. */
@media (max-width:1180px){#battlePanel{display:none}}
@media (min-width:1101px) and (max-width:1500px){
  #battlePanel .battleIntel:nth-child(4){display:none}
}

/* Adding the roster row shifted the intel blocks from children 1-3 to 2-4, so the
   old mid-width rule that hid "nth-child(3)" was hiding the middle block instead of
   the last one. Restore it and hide the correct one. */
@media (min-width:1101px) and (max-width:1500px){
  #battlePanel .battleIntel:nth-child(3){display:block}
  #battlePanel .battleIntel:nth-child(4){display:none}
  #battlePanel{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* Must sit AFTER the block above, which re-shows nth-child(3) — at equal specificity
   source order decides. Between 1180 and 1400 the panel exists but only has room for one intel block at a legible
   width, so it shows the one you read most and drops the other. */
@media (min-width:1181px) and (max-width:1400px){
  #battlePanel{grid-template-columns:1fr}
  #battlePanel .battleIntel:nth-child(3){display:none}
}

/* ============================================================================
   LOBBY — setup on the left, what you are about to play on the right
   The old menu was one long column of option rows with a wall of control text at
   the bottom. Setup now sits beside a live preview of the actual battlefield, and
   the instructions moved into a tabbed guide so they can be thorough without
   burying the thing you came here to press.
   ========================================================================== */
#lobbyMain{
  display:grid;grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);
  gap:clamp(10px,1.6vw,22px);align-items:start;margin-top:6px;
}
#lobbySetup .secTitle:first-child{margin-top:0}
#lobbyBrief{
  border:1px solid var(--stone-hi);border-radius:4px;
  background:linear-gradient(180deg,rgba(40,36,52,.55),rgba(16,14,22,.55));
  padding:8px 10px 10px;
}
#lobbyBrief .secTitle{margin-top:0}

/* the preview is square and never wider than its column */
#mapPreviewWrap{position:relative}
#mapPreview{
  display:block;width:100%;height:auto;aspect-ratio:1;
  image-rendering:pixelated;border:1px solid var(--stone-hi);border-radius:3px;
  background:#12101a;box-shadow:inset 0 0 22px rgba(0,0,0,.7);
}
#mapLegend{
  display:flex;gap:10px;justify-content:center;flex-wrap:wrap;
  margin-top:6px;font:700 10px Verdana,sans-serif;color:#a99c83;letter-spacing:.06em;
}
#mapLegend span{display:flex;align-items:center;gap:4px}
#mapLegend i{width:10px;height:10px;display:block;border:1px solid rgba(0,0,0,.6)}
#mapLegend .lgBase{background:#e8534a}
#mapLegend .lgLane{background:rgba(150,142,180,.5)}
#mapLegend .lgVault{background:var(--dp-gold);border-radius:50%}
#mapBlurb{
  margin-top:8px;font-size:12px;line-height:1.55;color:#a89e84;
}
#mapBlurb b{color:#dbcfb4}

/* ---- how to play ---- */
#guide{margin-top:10px;text-align:left}
#guideTabs{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:6px}
.gTab{
  flex:1 1 0;min-width:78px;padding:5px 6px;
  border:1px solid var(--stone-hi);border-radius:3px;
  background:linear-gradient(180deg,var(--stone-lo),var(--mortar));
  color:#a89e84;font:900 10px Verdana,sans-serif;letter-spacing:.08em;
}
.gTab:hover{border-color:var(--dp-gold);color:#dbcfb4}
.gTab.sel{border-color:var(--dp-gold);color:#ffe9a8;
  background:linear-gradient(180deg,#4a3d22,#1d1710);box-shadow:inset 0 0 10px rgba(255,194,28,.2)}
#guideBody{
  border:1px solid var(--stone-hi);border-radius:3px;
  background:linear-gradient(180deg,rgba(40,36,52,.5),rgba(16,14,22,.5));
  padding:9px 12px;min-height:118px;
  font-size:11.5px;line-height:1.62;color:#b3a68e;
}
#guideBody p{margin:0 0 7px}
#guideBody p:last-child{margin-bottom:0}
#guideBody b{color:#e9e0cb}
#guideBody i{font-style:normal;color:#9a8e78}
.gTable{width:100%;border-collapse:collapse;margin:3px 0 9px;font-size:12px}
.gTable th{
  text-align:left;padding:3px 6px;color:var(--dp-gold);
  font:900 10px Verdana,sans-serif;letter-spacing:.1em;text-transform:uppercase;
  border-bottom:1px solid var(--stone-hi);
}
.gTable td{padding:4px 6px;border-bottom:1px solid rgba(110,103,128,.22);vertical-align:top;color:#b3a68e}
.gTable td b{display:block;color:#e9e0cb}
.gTable td i{display:block;font-style:normal;font-size:11px;color:#a4977f;margin-top:2px}

/* one column once there is no room for two */
@media (max-width:860px){
  #lobbyMain{grid-template-columns:minmax(0,1fr)}
  #lobbyBrief{order:1}   /* real owner of this is the last media block; see there */
  #mapPreview{max-width:280px;margin:0 auto}
  .gTab{font-size:9.5px;min-width:70px}
  #guideBody{font-size:11px}
}

/* The lobby wordmark is a menu header, not the title card — the intro already gives the
   logo a full screen. At intro scale it pushed START and the guide below the fold. */
#gameLogo .dp1{font-size:min(7.6vw,9vh)}
#gameLogo .dp2{font-size:min(6.6vw,7.8vh)}
#gameLogo .dp3{font-size:min(5.6vw,6.6vh)}
#gameLogo{margin-bottom:2px}
#gameLogo small{font-size:10px;letter-spacing:.4em}
.logoCrest{width:min(26vw,20vh)}
#titleCard{padding-top:6px}
#tagline{margin:2px 0 4px}
#lobbyMain{margin-top:2px}
.secTitle{margin:5px 0 3px}
#matchSummary{margin-top:5px}
.lobbyUtility{margin-top:5px}
#startBtn{margin-top:8px}

/* Cap the preview: at full column width it was ~430px tall and pushed START and the guide
   off the bottom of a 709px viewport. 290px still reads clearly at a glance. */
#mapPreview{max-width:290px;margin:0 auto}
#lobbyMain{grid-template-columns:minmax(0,1.7fr) minmax(0,1fr)}
#guideBody{min-height:0}
#guide{margin-top:8px}

/* Bound the guide so the page height is fixed regardless of which tab is open — the
   Warbands table is much taller than the Controls one, and an unbounded panel pushed
   itself off the bottom of the viewport. It scrolls internally instead. */
#guideBody{max-height:clamp(110px,20vh,190px);overflow-y:auto;overscroll-behavior:contain}
#guideBody::-webkit-scrollbar{width:8px}
#guideBody::-webkit-scrollbar-track{background:rgba(0,0,0,.3)}
#guideBody::-webkit-scrollbar-thumb{background:var(--stone-hi);border-radius:4px}

/* Final fit pass. The real viewport in testing is ~709px tall, not the 860 the window is
   opened at, so the whole menu is budgeted against that: header small, preview capped,
   guide bounded. Everything below stays reachable without scrolling the page. */
#gameLogo .dp1{font-size:min(5.6vw,6.4vh)}
#gameLogo .dp2{font-size:min(4.9vw,5.6vh)}
#gameLogo .dp3{font-size:min(4.2vw,4.8vh)}
.logoCrest{width:min(18vw,13vh)}
#titleCard{padding-top:4px;padding-bottom:8px}
#tagline{font-size:11px;margin:1px 0 3px}
#mapPreview{max-width:236px}
#lobbyBrief{padding:6px 8px 8px}
#mapLegend{margin-top:4px}
#mapBlurb{margin-top:5px;font-size:11.5px;line-height:1.5}
.secTitle{margin:4px 0 2px}
.setupBtn{min-height:33px}
#matchSummary{margin-top:4px}
.lobbyUtility{margin-top:4px}
#startBtn{margin-top:6px;padding:8px 18px}
#guide{margin-top:6px}
#guideBody{max-height:clamp(96px,15vh,150px);padding:7px 10px}


/* ============================================================================
   DEATH PIT THEME PASS
   Placed last on purpose (ahead of the phone query, which still has to stay at the
   very bottom): these are re-skins of components declared far earlier, and at equal
   specificity source order is what decides.

   The old skin was cool purple-grey stone lifted from the app icon's frame. It read
   as generic fantasy-magic — lavender panels do not say "arena floor you bleed on".
   Everything below keeps the icon's value structure (dark frame, bright inks) and
   swaps the hue to char, iron, ember and blood.
   ========================================================================== */

/* ---- selection: the single biggest legibility win in the lobby ----
   A chosen option used to differ from an unchosen one by a slightly warmer border and
   a faint inner glow, which is nearly invisible at a glance across a grid of eight.
   Now it is filled, ember-lit, bar-marked down the left edge and ticked. */
.setupBtn, .diffBtn{
  position:relative;
  background:linear-gradient(180deg,#2a231d,#141010);
  border:1px solid #4e443a;
  color:#b9ad96;
  transition:border-color .12s, color .12s, background .12s;
}
.setupBtn:hover:not(.sel), .diffBtn:hover:not(.sel){
  border-color:var(--gold);color:#e9dcbd;background:linear-gradient(180deg,#332a22,#171210);
}
.setupBtn.sel, .diffBtn.sel{
  border-color:#ffb648;
  color:#fff0c8;
  background:linear-gradient(180deg,#5a3a12,#2a1a08);
  box-shadow:inset 0 0 14px rgba(255,150,50,.28), 0 0 12px rgba(255,130,40,.2);
}
.setupBtn.sel::before, .diffBtn.sel::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:linear-gradient(180deg,var(--ember),var(--blood));
}
.setupBtn.sel small{color:#e8c489}
.setupBtn.sel::after{
  content:"";position:absolute;right:6px;top:6px;width:6px;height:6px;border-radius:50%;
  background:var(--ember);box-shadow:0 0 7px var(--ember);
}

/* ---- section labels: chiselled, with an ember rule running off to the right ---- */
.secTitle{
  color:#c39a52;display:flex;align-items:center;gap:9px;
}
.secTitle::after{
  content:"";flex:1;height:1px;
  background:linear-gradient(90deg,rgba(196,120,40,.5),transparent);
}

/* ---- the call to action ---- */
#startBtn{
  border:2px solid #ffcf62;
  background:linear-gradient(180deg,#ffdd88,#e2a231 52%,#9c5c0c);
  color:#1a1002;
  box-shadow:0 4px 0 #45290a, 0 0 30px rgba(255,140,40,.3), 0 10px 24px rgba(0,0,0,.6);
}
#startBtn:hover{filter:brightness(1.07);border-color:#fff1bd}
#randomBtn{
  border:1px solid #4e443a;background:linear-gradient(180deg,#2a231d,#141010);color:#b9ad96;
}
#randomBtn:hover{border-color:var(--gold);color:#e9dcbd}

/* ---- guide tabs read as a row of iron plates; the open one is lit ---- */
.gTab{
  background:linear-gradient(180deg,#241e19,#120f0d);
  border:1px solid #463c33;color:#9b8f79;
}
.gTab:hover{border-color:var(--gold);color:#dbcaa6}
.gTab.sel{
  border-color:#ffb648;color:#ffe6ac;
  background:linear-gradient(180deg,#4a3010,#1e1408);
  box-shadow:inset 0 0 12px rgba(255,150,50,.22);
}
#guideBody{border-color:#3d342c}
#guideBody i{color:#9a8e78}
.gTable th{color:#c39a52}
.gTable td{border-bottom-color:rgba(120,100,78,.22);color:#b3a68e}
.gTable td i{color:#93876f}

/* ---- the briefing column ---- */
#lobbyBrief{border-color:#463c33}
#mapPreview{border-color:#5b4f43;background:#100c0a}
#mapLegend{color:#9a8e78}
#mapBlurb{color:#a99c83}
#mapBlurb b{color:#dbcfb4}
#matchSummary{color:#c0b393}
#howTo{color:#94886f}
#howTo b{color:#c7ba99}

/* ---- warband and hero cards ---- */
.fCard, .hCard{
  background:linear-gradient(180deg,#241e19,#120f0d);
  border:1px solid #463c33;
}
.fCard:hover, .hCard:hover{border-color:var(--gold)}
.fCard b, .hCard b{color:#f0e4c4}
.fCard em, .hCard i{color:#c39a52}
.fCard small, .hCard em{color:#9a8e78}

/* ---- in-battle furniture, so the HUD agrees with the menus ---- */
.armyBtn, .squadBtn, .facBtn, .rosterBtn, .cmd, .slot, .ubtn{
  background:linear-gradient(180deg,#2b241e,#141010);
  border-color:#544539;
}
.armyBtn.active, .squadBtn.armed{
  border-color:#ffb648;color:#ffe6ac;
  box-shadow:inset 0 0 10px rgba(255,150,50,.26);
}
.rosterBtn.active{
  border-color:#ffb648;
  box-shadow:inset 0 0 10px rgba(255,150,50,.24),0 0 7px rgba(0,0,0,.6);
}
.killLine{border-left-color:var(--kc,#c07a2a)}
#errline{color:#ff7b52}

/* ---- the pit glows under the whole menu ---- */
/* The lobby root is #veil. Light rises from the bottom of the screen because that is
   where the pit is; a top-lit menu contradicted the whole premise. */
#veil{
  background:
    radial-gradient(ellipse 130% 62% at 50% 112%, rgba(206,72,10,.26), transparent 62%),
    radial-gradient(ellipse 90% 55% at 50% -12%, rgba(52,36,28,.55), transparent 62%),
    #080605 !important;
}
/* the icon corner banners were mauve-heavy; warm them to the two inks that matter */
#titleCard::after{
  background:
    radial-gradient(circle at 0% 0%,    rgba(255,150,40,.12), transparent 32%),
    radial-gradient(circle at 100% 0%,  rgba(179,36,28,.14),  transparent 32%),
    radial-gradient(circle at 0% 100%,  rgba(179,36,28,.14),  transparent 32%),
    radial-gradient(circle at 100% 100%,rgba(255,150,40,.12), transparent 32%) !important;
}


/* ============================================================================
   LEGIBILITY CORRECTION — read this before putting the display font back on a
   small label.

   `DeathPit` is a pixel typeface. Below roughly 16px its stems land on fractional
   pixels and anti-alias to partial coverage, so the glyph's *effective* luminance
   collapses even though the declared colour never changes. That is why a contrast
   audit reported these labels passing AA at 10:1 while they were genuinely hard to
   read on screen: the ratio is computed from the declared colour, and the screen was
   painting something much dimmer.

   The rule now: DeathPit is for display sizes only — the wordmark, modal headings,
   the announcer, the big countdown, the primary call to action. Anything a player
   reads as information rather than as a title is set in Verdana, which was designed
   for exactly this size and hints cleanly.
   ========================================================================== */
.secTitle,
.modalBtn,
#loadStatus{
  font-family:Verdana,'DejaVu Sans',sans-serif;
}
.secTitle{letter-spacing:.16em;font-weight:900}
#loadStatus{letter-spacing:.16em;font-weight:700}

/* Button labels: bigger, heavier, and light enough to hold their own on iron. */
.modalBtn{
  font-size:13px;font-weight:700;letter-spacing:.06em;color:#f4ecd8;
}
.modalBtn.danger{color:#ffb8a8}
.modalBtn.danger:hover{color:#ffe0d6}
#settingsClose{font-size:17px}

/* The primary action keeps the display face — it is large and heavy enough for it —
   but the plate lightens so the dark label clears AA against the darkest stop. */
#startBtn, #resumeBtn{
  background:linear-gradient(180deg,#ffe6a2,#f0b544 48%,#d08a1e);
  color:#241503;
}

/* Body copy inside modals was mid-grey on charcoal. */
.pauseCard p{color:#c8bda3;font-size:13px}
.pauseHint{color:#a89c84 !important;font-size:12px !important}
.dangerLabel{color:#d3a396;font-size:11px}
.settingsFoot{color:#a89c84}

/* A pixel headline does not need a 30px bloom behind it — the glow eats the gaps
   between stems, which is the opposite of legible. Keep a tight dark outline for
   definition and let the ember read as a hint rather than a haze. */
#pauseVeil h2, #endTitle, #talentPanel h3, #settingsTitle{
  text-shadow:0 2px 0 #000, 0 0 6px rgba(255,122,42,.35);
}

/* Inventory slot numbers were placeholder-dim at 1.6:1 — they are hotkeys, so they
   have to be readable when the slot is empty. */
.slot.empty{color:#8a8068}
/* the player-count line above the wordmark sat at 1.8:1 against the title card */
#modeLabel{color:#cbbf9f}


/* ============================================================================
   TOUCH TARGETS — phones and tablets
   Measured with `node tools/mobile.js`, which reports every control under 44px at
   real Android landscape viewports. Before this pass a 640x360 handset had 25 of
   them: the utility rail at 34px, army-order buttons 21px TALL, and item slots at
   30px. A thumb contact patch is about 9mm; a mis-tap here issues a real order.

   Space is the whole difficulty. A 360dp-tall screen cannot simply have every
   control inflated to 48dp — six stacked 34px utility buttons already run 234px
   down a 360px screen, which is exactly why the settings button was landing on top
   of the mastery button. So the phone layout drops what a phone does not need
   rather than shrinking what it does.
   ========================================================================== */
body.touch{}
@media (max-width:1100px){

  /* Sound and zoom come off the rail: sound has a settings row, and zoom is pinch.
     What remains goes two-across so the rail is 2 rows tall instead of 6, which is
     what clears the army bar underneath it. */
  #soundBtn, #zoomBtn{display:none}
  #util{
    display:grid;grid-template-columns:repeat(2,46px);gap:7px;
    top:max(40px,calc(var(--sat) + 36px));
  }
  .ubtn{width:46px;height:46px;font-size:19px;border-radius:5px}

  /* Army orders: 21px tall was the worst offender on the whole screen. */
  .armyBtn{height:44px;min-width:56px;font-size:11px}
  .armyBtn .hk{font-size:10px;top:2px;left:3px}
  .armyBtn .mcost{font-size:10px}
  #racialBtn{min-width:66px}
  #armyBar{gap:6px;padding:6px 7px}
  .squadBtn{height:44px;min-width:56px;font-size:11px}

  /* Item slots and ability buttons are the two things tapped most in a fight. */
  #invPanel{padding:6px;grid-template-columns:repeat(3,44px);grid-auto-rows:44px;gap:5px}
  .slot{font-size:22px}
  .slot .slotKey{font-size:11px}
  #cmdCard{padding:6px;grid-template-columns:repeat(4,48px);grid-auto-rows:48px;gap:5px}
  .cmd{font-size:22px}.cmd.upg{font-size:20px}.cmd .cdNum{font-size:20px}

  /* Reclaim the width those cost: a smaller minimap and a portrait-free hero panel.
     The portrait is decoration; the bars and the name are the information. */
  #mmWrap{padding:4px}
  #minimap{width:92px;height:92px}
  #hud{padding-left:108px;gap:6px;height:150px}
  #hud::after{left:104px}
  #heroPanel{width:186px;grid-template-columns:1fr;gap:4px;padding:7px 8px}
  #portrait{display:none}
  #heroName{font-size:14px}
  #heroSub{display:none}
  #talentDock{height:20px;min-width:52px;font-size:9px}
  #joy{bottom:162px}
  /* Earlier breakpoints scale the whole bar down, which silently undid the 44px height
     above — a scaled 44px button is a 32px touch target. */
  #armyBar{transform:none;right:8px;bottom:calc(150px + max(6px,var(--sab)))}
  #squadBar{transform:translateX(-50%);bottom:calc(150px + max(6px,var(--sab)))}
  #errline{bottom:calc(158px + max(6px,var(--sab)))}
}

/* Small handsets: the same layout, with the guide and standings giving up room. */
@media (max-width:700px){
  #scores{width:150px;font-size:10.5px}
  .pRow{grid-template-columns:8px 12px 1fr 17px 15px;gap:3px}
  #killFeed{width:46vw}
  #hud{padding-left:104px}
  #heroPanel{width:168px}
  #invPanel{grid-template-columns:repeat(3,44px)}
  #armyBar{transform:none}
}


/* Touch size floors, keyed to the input device rather than the viewport. A 915px phone is
   still a phone and a 1024px tablet is still a thumb; both fell outside the width-based
   breakpoints and kept 38-40px lobby buttons. Layout stays width-driven above; only the
   minimum target size is capability-driven. */
body.touch .setupBtn,
body.touch .diffBtn,
body.touch .gTab,
body.touch #randomBtn,
body.touch .modalBtn,
body.touch .segBtn,
body.touch .hCard,
body.touch .fCard,
body.touch #startBtn,
body.touch #planSkip{min-height:46px}
body.touch .gTab{padding:13px 8px}
body.touch #randomBtn{padding:12px 18px}
body.touch #planSkip{padding:12px 24px}
/* The army bar sits behind the planning veil and, on a 360px-tall screen, READY NOW lands
   right on top of it — both live, so a tap in the overlap is a coin flip. Nudging positions
   only moved which button it collided with. There are no troops during the muster, so army
   orders mean nothing yet: the bar is simply not interactive until the fighting starts.
   The army bar sits BEFORE the veil in the markup, so no sibling selector reaches it; the
   game mirrors the veil state onto body.planning for exactly this. */
body.planning #armyBar,
body.planning #squadBar{pointer-events:none;opacity:.45}
body.touch .setupBtn{padding:8px 6px}
/* Touch sizing for the in-match furniture, keyed to the input device rather than the
   viewport. These lived inside "@media (max-width:1100px)", so a 1280px tablet — still a
   touchscreen, still a thumb — fell out of the query and reverted to 34px buttons. Fourteen
   of the twenty-three problems the matrix sweep found were this single mistake. */
body.touch .ubtn{width:46px;height:46px;font-size:19px;border-radius:5px}
body.touch #soundBtn, body.touch #zoomBtn{display:none}
body.touch #util{display:grid;grid-template-columns:repeat(2,46px);gap:7px}
body.touch .armyBtn{height:44px;min-width:56px;font-size:11px}
body.touch .squadBtn{height:44px;min-width:56px;font-size:11px}
body.touch #racialBtn{min-width:66px}
body.touch .facBtn{min-height:44px}
body.touch .rosterBtn{min-height:44px}
body.touch .slot{min-width:44px;min-height:44px}
body.touch .cmd{min-width:46px;min-height:46px}
body.touch #shopClose,
body.touch #settingsClose{width:46px;height:46px}
body.touch .sItem{min-height:56px}
/* 28px tabs and 42px sell slots were both under the 44px floor the rest of the game holds to. */
body.touch .shopTab{min-height:44px;font-size:10px}
/* "Consumables" is the longest label and overran its 78px tab on the smallest handset. */
@media (max-width:620px){body.touch .shopTab{font-size:9px;padding:0 2px;letter-spacing:0}}
body.touch .sellSlot{width:46px;height:46px}
body.touch #sellGrid{grid-template-columns:repeat(6,46px)}
body.touch #shopClose{min-width:44px;min-height:44px}
/* The head, hint and sell block are fixed furniture; on a short screen they were taking more
   of the panel than the stock was. */
@media (max-height:460px){
  body.touch #shop{padding:7px 9px}
  body.touch #shopHead h3{font-size:14px}
  body.touch #shopHead p{display:none}
  body.touch #shopHint{display:none}
  body.touch #sellHead{margin-top:6px;padding-top:5px;font-size:10px}
  body.touch #sellGrid{grid-template-columns:repeat(6,44px);gap:4px;margin-top:4px}
  body.touch .sellSlot{width:44px;height:44px}
}
body.touch .hk,
body.touch .slotKey{display:none}
body.touch #armyTab{min-height:46px}
body.touch #armyPop .armyBtn{height:46px;min-width:104px}
/* the tab is compact, but its popup opens leftward — keep the tab out of the rail column */
body.touch #armyPop{grid-template-columns:repeat(2,minmax(104px,1fr))}

/* ---- sponsor splash ----
   Above every other layer including the load veil, so the handoff is splash -> lobby with
   no flash of the game title behind it. Removed from the DOM once it has faded. */
#sponsorSplash{
  position:fixed;inset:0;width:100%;height:100%;border:0;margin:0;padding:0;
  z-index:200;background:#0b0b0f;display:block;
}

/* START follows the thumb. The lobby scrolls on a phone, and the primary action must never
   be the thing you have to go looking for. */
/* START is NOT sticky on touch. A sticky footer necessarily covers whatever scrolls under
   it, and on a 412px-tall phone that was permanently the Game Mode row — the button meant to
   help was hiding an option. It now sits inline directly after the setup grid, which is both
   the natural reading order and impossible to overlap. The lobby leads with setup, so it is a
   short scroll rather than a hunt. */
body.touch #startBtn{position:static;margin:10px auto 4px}
body.touch #veil{padding-bottom:calc(16px + var(--sab))}

@media (max-height:460px){
  body.touch #titleCard{padding:6px 10px;margin:4px auto}
  body.touch #gameLogo{font-size:30px}
  body.touch #tagline{font-size:10px;margin:2px 0 4px}
  body.touch #mapPreview{max-width:150px}
  body.touch #guideBody{max-height:22vh}
}

/* ---- phone information budget ----
   A 393px-tall screen is mostly battlefield or it is nothing. The chrome that earns its
   place during a fight is the command card, the army orders and the minimap; everything
   else gets smaller, collapsed or moved out of the way. */
/* Collapsed by default on a phone and opened with the list button. A 393px-tall screen
   cannot spare the top-right corner for a panel you glance at a few times a match, and
   leaving it up put it underneath the utility rail and the army bar. */
body.touch #scores{display:none;opacity:1}
body.touch #scores.shown{display:block}
body.touch #killFeed{width:min(240px,34vw);gap:2px}
body.touch .killLine{font-size:11px;padding:4px 7px}
body.touch #killFeed .killLine:nth-child(n+4){display:none}   /* three lines is plenty */
body.touch .annLine{font-size:19px}
body.touch .annSub{font-size:12px}
body.touch #eventBar{min-width:0;padding:4px 9px}
body.touch #eventName{font-size:11px}
body.touch #eventMeta{font-size:9px;gap:7px}
/* the rail sits under the topbar on the right, clear of the standings toggle target */
body.touch #util{top:max(52px,calc(var(--sat) + 48px))}
body.touch #scores{top:max(52px,calc(var(--sat) + 48px));right:112px}


/* ---- system bars ----
   In landscape the navigation bar is a strip down one SIDE, not the bottom, and the status
   bar overlays the top. The app draws edge to edge, so every UI layer has to hold itself
   inside the insets or it ends up underneath them — which is what happened on device: the
   army bar ran under the nav strip and the utility rail sat beneath the status icons.
   Anchored layers are re-based on the variables here, in one place, rather than each rule
   remembering to do it. */
#topbar{top:calc(max(5px,var(--sat)) + 2px)}
/* "#scores + #util{top:auto}" carries two IDs, so it outranks every single-ID rule and was
   pinning the utility rail to y=0 — directly under the status bar on device. Matching its
   specificity is the only way to take it back. */
#scores + #util{top:calc(max(40px,var(--sat)) + 46px)}
body.touch #scores + #util{top:calc(max(40px,var(--sat)) + 48px)}
#util{top:calc(max(40px,var(--sat)) + 46px);right:calc(max(6px,var(--sar)) + 4px)}
#scores{top:calc(max(40px,var(--sat)) + 46px);right:calc(max(6px,var(--sar)) + 4px)}
/* Hangs off the BOTTOM of the topbar, which itself moves with the status-bar inset. The old
   rule anchored it 6px under the inset alone, so with sat=31 it sat ON the topbar. */
#eventBar{top:calc(max(5px,var(--sat)) + 50px)}
#killFeed{left:calc(max(12px,var(--sal)) + 2px)}
/* The utility rail is a two-wide grid pinned to the right edge; the army bar is pinned to the
   same edge and tall enough to run into it, which left MASTERY physically unpressable behind
   the "?" button on device. Hold the bar clear of the rail instead of hoping they miss. */
#armyBar{right:calc(8px + var(--sar))}
body.touch #armyBar{right:calc(var(--sar) + 112px)}
/* The rail is a 2x46px grid on touch, so 58px of clearance is not enough — same 112px the
   army bar uses, and the width formula has to give the same space back. */
body.touch #combatLegend{right:calc(var(--sar) + 112px);
  width:min(340px,calc(100vw - var(--sar) - var(--sal) - 130px))}
body.touch #legendClose{width:46px;height:46px;padding:0}
#squadBar{bottom:calc(150px + max(6px,var(--sab)))}
#mmWrap{left:calc(max(6px,var(--sal)) + 2px)}
/* This single rule used to set padding-left too, at top level and late in the file, which
   silently flattened the base 198px AND every responsive step below it. 108px was the value the
   TOUCH layout wants; on desktop the minimap is 166px inside a 7px-padded wrapper at a 10px
   offset — 194px of it — so the hero portrait spent this whole time hidden behind the minimap.
   Touch was unaffected because body.touch rules outrank a bare #hud, which is exactly why it
   only ever showed up on desktop.
   The left padding is restored as a ladder below; each step clears its own minimap size. */
#hud{padding-right:calc(12px + var(--sar))}
#hud{padding-left:calc(198px + var(--sal))}
@media (max-width:1100px){#hud{padding-left:calc(174px + var(--sal))}}
@media (max-width:900px){#hud{padding-left:calc(122px + var(--sal))}}
@media (max-width:680px) and (orientation:landscape){#hud{padding-left:calc(94px + var(--sal))}}
/* Touch keeps the value the mobile matrix was tuned against; the narrower touch tiers further
   down override it again and still win, being both more specific and later. */
body.touch #hud{padding-left:calc(108px + var(--sal))}
#joy{left:calc(max(14px,var(--sal)) + 2px)}
/* the pit rail on the right of the lobby, and the sticky action, also clear the nav strip */
#veil{padding:max(4px,var(--sat)) max(4px,var(--sar)) max(4px,var(--sab)) max(4px,var(--sal))}
#veil{transition:opacity .42s ease,transform .42s ease}
#veil.closing{opacity:0;transform:scale(1.045);pointer-events:none}

/* ---- the resource bar is a readout, not a control ----
   It was sized like a control — 16px numerals, 22px icons, a 218px Archvault block — and took
   a strip of battlefield across the top. Nothing in it is tappable, so it can be as small as
   it is legible. Every colour is unchanged, so the contrast audit still passes. */
body.touch #topbar{gap:7px;padding:2px 8px}
body.touch .res{font-size:12px;gap:4px}
body.touch .res .ic{width:15px;height:15px;font-size:12px}
body.touch .res.gold b{min-width:34px}
body.touch #clock{font-size:11px}
body.touch .vaultRes{min-width:0;margin-left:2px;padding-left:6px}
body.touch .vaultRes b{font-size:11px}
body.touch .vaultRes small{font-size:9px}
/* The rail and the event bar hang off the topbar's bottom edge, so they follow it up. The
   two-ID selector has to be matched again here for the same reason it did originally. */
body.touch #util,
body.touch #scores{top:calc(max(28px,var(--sat)) + 30px)}
body.touch #scores + #util{top:calc(max(28px,var(--sat)) + 30px)}
body.touch #eventBar{top:calc(max(5px,var(--sat)) + 32px)}

/* ---- the army tab shrinks to a glyph plus the live order ----
   Expanded it was ~180px of battlefield for a label whose first word repeated what the sword
   glyph already says. */
/* 44px is the touch floor and the audit enforces it, so the height stays; the saving is in
   width — the label lost its verb and the popup is no longer permanently open. */
body.touch #armyTab{min-height:44px;padding:2px 8px;gap:5px}
body.touch #armyTab>i{font-size:12px}
body.touch #armyMode{font-size:9px;letter-spacing:.02em}
body.touch #armyCaret{font-size:10px}

/* ---- match loading ----
   Below the boot veil (120) so the two never fight, above the lobby (60) and the hero
   chooser (62) — the chooser opens underneath it and is revealed by the fade. */
#matchLoad{position:fixed;inset:0;z-index:115;display:none;place-items:center;
  padding:var(--sat) var(--sar) var(--sab) var(--sal);
  background:radial-gradient(ellipse 120% 80% at 50% 108%,rgba(206,72,10,.26),#070504 62%);
  opacity:0;transition:opacity .3s ease}
#matchLoad.on{display:grid;opacity:1}
#matchLoad.out{opacity:0}
.mlInner{text-align:center;padding:0 24px;max-width:520px}
.mlTitle{font-family:"DeathPit",Verdana,sans-serif;font-size:15px;letter-spacing:.16em;color:#f0d77f;
  text-shadow:0 2px 0 #000,0 0 10px rgba(255,122,42,.45);margin-top:16px}
.mlTip{margin-top:10px;color:#a89c84;font:12px/1.45 Verdana,sans-serif;min-height:34px}
.mlBar{width:min(320px,70vw);height:5px;margin:14px auto 0;border:1px solid #2b211a;background:#120d0a;overflow:hidden}
.mlBar i{display:block;height:100%;width:34%;
  background:linear-gradient(90deg,transparent,#ff9a3c,#ffd88a,#ff9a3c,transparent);
  animation:mlSweep 1.05s linear infinite}
@keyframes mlSweep{from{transform:translateX(-110%)}to{transform:translateX(400%)}}
/* Three rings, CSS-animated. A canvas spinner would freeze with everything else while the
   terrain bakes; compositor-driven transforms keep moving through it. */
.mlRing{position:relative;width:74px;height:74px;margin:0 auto}
.mlRing i{position:absolute;inset:0;border:2px solid transparent;border-top-color:#ff8a2a;border-radius:50%;
  animation:mlSpin 1.2s cubic-bezier(.5,.1,.5,.9) infinite}
.mlRing i:nth-child(2){inset:9px;border-top-color:#ffc247;animation-duration:1.6s;animation-direction:reverse}
.mlRing i:nth-child(3){inset:18px;border-top-color:#b3241c;animation-duration:2s}
@keyframes mlSpin{to{transform:rotate(360deg)}}
@media (max-height:460px){
  .mlRing{width:52px;height:52px}
  .mlTitle{font-size:13px;margin-top:9px}
  .mlTip{font-size:11px;margin-top:6px;min-height:0}
  .mlBar{margin-top:9px}
}

/* ---- chooser preview ---- */
.chooseCard.previewing{border-color:#ffb648;box-shadow:0 0 0 1px #ffb648,0 0 18px rgba(255,150,50,.32)}
#chooseDetail{margin-top:10px;padding:10px 12px;border:1px solid #5c5540;border-radius:4px;
  background:linear-gradient(180deg,rgba(58,44,24,.5),rgba(14,11,8,.75))}
.cdHead{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;margin-bottom:8px}
.cdHead b{font-size:16px;color:#ffe7a2}
.cdHead em{font-style:normal;font-size:11px;color:#b3a68e}
.cdSkills{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:8px}
.cdSkill{display:flex;gap:8px;align-items:flex-start;text-align:left}
/* A troop thumbnail is a sprite on a dark plate, not a cropped fill, so it opts out of the
   cover sizing the painted skill icons want. */
.cdSkill>i.troopThumb{background-color:#141009}
.cdSkill>i{flex:0 0 auto;width:34px;height:34px;border:1px solid #5c5540;background:#17130c;background-size:cover;
  background-position:center;display:grid;place-items:center;font-style:normal;font-size:15px;image-rendering:pixelated}
.cdSkill b{display:block;font-size:12px;color:#f2e8c6}
.cdSkill span{display:block;font:11px/1.35 Verdana,sans-serif;color:#a99f88;margin-top:2px}
.cdSkill span:empty{display:none}
.cdSkill small{display:block;font:10px Verdana,sans-serif;color:#c39a52;margin-top:2px}
.cdBlurb{margin:0 0 9px;font:11px/1.45 Verdana,sans-serif;color:#b0a48a}
.cdBlurb b{color:#dcc38a;font-weight:700}
.cdConfirm{display:block;width:100%;min-height:46px;margin-top:10px;border:2px solid #ffcf62;border-radius:3px;
  background:linear-gradient(180deg,#ffe6a2,#f0b544 52%,#d08a1e);color:#241503;cursor:pointer;
  font:900 13px "DeathPit",Verdana,sans-serif;letter-spacing:.1em}
.cdConfirm:active{transform:translateY(1px)}
/* ---- landscape phone: roster left, preview right ----
   Stacked, the panel pushed the grid off the top of the scrollport and you lost sight of the
   card you had just pressed. A landscape phone is wide and short, so the two go side by side
   and the roster loses its per-card skill strip — the panel now shows those same four icons
   at four times the size, with the text. */
@media (max-height:620px){
  /* The panel stays content-sized until it hits max-height:100%, at which point the 1fr row
     is squeezed and the two columns scroll inside it. Forcing height:100% instead would work
     but leaves a tablet staring at half a panel of empty space. */
  #choosePanel.previewOpen{display:grid;align-content:start;gap:0 12px;overflow:hidden;
    grid-template-columns:minmax(0,1fr) minmax(238px,41%);
    grid-template-rows:auto auto minmax(0,1fr);
    grid-template-areas:"head head" "sub sub" "grid detail"}
  #choosePanel.previewOpen #chooseGrid{overflow:auto;min-height:0;touch-action:pan-y}
  /* The ability list is the only part allowed to scroll; the name and the confirm stay put,
     so the action is never something you have to go looking for. */
  /* min-WIDTH:0 as well as min-height. A grid item defaults to a min-content automatic
     minimum, so without it the detail track ignored its 34% cap and grew to fit the longest
     ability name — which quietly stole width from the roster. */
  #choosePanel.previewOpen #chooseDetail{display:flex;flex-direction:column;min-height:0;min-width:0;overflow:hidden}
  #choosePanel.previewOpen .cdSkills{flex:1 1 auto;min-height:0;overflow:auto;touch-action:pan-y;align-content:start;gap:4px}
  /* The last cooldown line was landing one row past the fold; four abilities have to fit a
     412px phone without scrolling, so the rows give up a few pixels each. */
  #choosePanel.previewOpen .cdSkill{gap:7px}
  #choosePanel.previewOpen .cdSkill>i{width:24px;height:24px;font-size:12px}
  #choosePanel.previewOpen .cdSkill span{line-height:1.3;margin-top:1px}
  #choosePanel.previewOpen .cdSkill small{margin-top:1px}
  #choosePanel.previewOpen .cdHead,
  #choosePanel.previewOpen .cdBack,
  #choosePanel.previewOpen .cdConfirm{flex:0 0 auto}
  #choosePanel.previewOpen h3{grid-area:head}
  #choosePanel.previewOpen>p{grid-area:sub;margin-bottom:8px}
  #choosePanel.previewOpen #chooseGrid{grid-area:grid;align-content:start}
  /* Twelve heroes take four columns; four warbands in the same narrow column would be four
     slivers, so the default grid halves instead. */
  #choosePanel.previewOpen #chooseGrid{grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}
  /* Four warbands need far less grid than twelve heroes, so the ladder gets the difference
     and wraps over fewer lines. Keyed off the grid NOT being the hero variant. */
  /* Four warband cards need about a third of the width; the ladder gets the rest so its five
     tiers keep their meta line on one row and fit without scrolling. */
  #choosePanel.previewOpen.wideDetail{grid-template-columns:minmax(0,1fr) minmax(280px,60%)}
  #choosePanel.previewOpen.wideDetail .cdSkills{gap:3px}
  #choosePanel.previewOpen.wideDetail .cdSkill{gap:6px}
  #choosePanel.previewOpen.wideDetail .cdSkill>i{width:34px;height:30px}
  #choosePanel.previewOpen.wideDetail .cdSkill b{font-size:11px}
  #choosePanel.previewOpen .cdBlurb{font-size:10px;line-height:1.4;margin-bottom:6px}
  #choosePanel.previewOpen #chooseGrid.heroes{grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}
  #choosePanel.previewOpen #chooseDetail{grid-area:detail;margin-top:0}
  #choosePanel.previewOpen .cSkills{display:none}
  #choosePanel.previewOpen .chooseCard{padding:5px 4px}
  #choosePanel.previewOpen .chooseCard .cIc{width:40px;height:40px;margin-bottom:4px}
  #choosePanel.previewOpen .chooseCard small{display:none}
  #choosePanel.previewOpen .cdSkills{grid-template-columns:minmax(0,1fr);gap:4px}
  #choosePanel.previewOpen .cdSkill>i{width:26px;height:26px;font-size:12px}
  #choosePanel.previewOpen .cdSkill span{font-size:10px;line-height:1.3}
  #choosePanel.previewOpen .cdSkill small{font-size:9px}
}
/* Under 780px the roster column would be ~55px per card and the names overflowed into each
   other. Too narrow to sit beside anything, so the preview becomes a full-panel view with a
   way back — master/detail rather than two columns. */
@media (max-height:620px) and (max-width:779px){
  #choosePanel.previewOpen{display:block}
  #choosePanel.previewOpen #chooseGrid{display:none}
  #choosePanel.previewOpen>h3,
  #choosePanel.previewOpen>p{display:none}
  #choosePanel.previewOpen .cdSkills{grid-template-columns:repeat(auto-fit,minmax(178px,1fr))}
  #choosePanel.previewOpen .cdSkill>i{width:28px;height:28px;font-size:13px}
  #choosePanel.previewOpen .cdBack{display:inline-block}
}
.cdBack{display:none;width:auto;min-height:38px;padding:0 14px;margin-bottom:8px;border:1px solid #5c5540;border-radius:3px;
  background:#1b1610;color:#c9bd9c;cursor:pointer;font:800 11px Verdana,sans-serif;letter-spacing:.08em}
@media (max-height:520px){
  #chooseDetail{margin-top:7px;padding:7px 9px}
  .cdHead{margin-bottom:5px}
  .cdHead b{font-size:14px}
  .cdSkills{grid-template-columns:repeat(auto-fit,minmax(178px,1fr));gap:5px}
  .cdSkill>i{width:28px;height:28px;font-size:13px}
  .cdSkill span{font-size:10px}
  .cdConfirm{min-height:44px;margin-top:7px}
}
/* A 360px-tall phone cannot afford the larger troop thumbnails: five rows at 30px tall push
   the last tier past the fold. They shrink here and nowhere else. */
@media (max-height:400px){
  #choosePanel.previewOpen.wideDetail .cdSkill>i{width:28px;height:24px}
  #choosePanel.previewOpen .cdBlurb{margin-bottom:4px}
}

/* Smallest handsets, where a 48dp nav strip leaves under 600px of usable width. The HUD is a
   row of fixed-width panels, so something has to give; the minimap and the hero panel shrink
   because the ability buttons and item slots are what you actually tap. Every target stays at
   or above 44px. */
@media (max-width:660px){
  body.touch #minimap{width:74px;height:74px}
  body.touch #hud{padding-left:calc(86px + var(--sal));gap:4px}
  body.touch #hud::after{left:82px}
  body.touch #heroPanel{width:142px;padding:6px}
  body.touch #heroName{font-size:13px}
  body.touch #cmdCard{grid-template-columns:repeat(4,46px);grid-auto-rows:46px;gap:4px;padding:5px}
  body.touch #invPanel{grid-template-columns:repeat(3,44px);grid-auto-rows:44px;gap:4px;padding:5px}
  /* Holding the army bar clear of the utility rail pushed it left into the joystick on the
     narrowest screens. The buttons give up width; the 44px touch height is kept. */
  body.touch .armyBtn{min-width:48px;font-size:10px;padding:0 2px}
  body.touch #racialBtn{min-width:54px}
  body.touch #armyBar{gap:4px;padding:5px}
}

/* 620-704px landscape. A media query cannot read env() insets, so this tier assumes the worst
   case: a cutout on one side and a nav strip on the other can take 84px, leaving a 640px phone
   with 556px. The full layout needs ~588. The item grid folds to 2x3 and the minimap shrinks,
   which buys ~95px and keeps every target at 44px. */
@media (max-width:704px){
  body.touch #minimap{width:62px;height:62px}
  body.touch #hud{padding-left:calc(74px + var(--sal));gap:4px}
  body.touch #hud::after{left:70px}
  body.touch #heroPanel{width:120px;padding:5px}
  body.touch #heroName{font-size:12px}
  body.touch #heroStats{display:none}
  body.touch #invPanel{grid-template-columns:repeat(3,44px);grid-auto-rows:44px;gap:3px;padding:4px}
  body.touch #cmdCard{grid-template-columns:repeat(4,44px);grid-auto-rows:44px;gap:3px;padding:4px}
  body.touch .cmd{min-width:44px;min-height:44px;font-size:19px}
  body.touch #hud{padding-top:12px}
}

/* Sub-620px landscape — an old 5-inch handset, and with a cutout plus a nav strip only ~484px
   of that is usable. The HUD is minimap + hero + items + abilities and simply will not fit:
   it needs about 596px. Rather than shrink every target below the 44px floor, the two least
   essential things go. The minimap is the biggest single consumer (86px with its padding) and
   is glanceable information rather than a control; the item grid folds to 2x3, which keeps
   all six slots at full size. Abilities and the hero bars are untouched. */
@media (max-width:620px){
  body.touch #mmWrap{display:none}
  body.touch #hud{padding-left:calc(10px + var(--sal));gap:3px}
  body.touch #hud::after{left:8px}
  body.touch #heroPanel{width:130px;padding:5px}
  body.touch #heroName{font-size:12px}
  body.touch #heroStats{display:none}
  body.touch #invPanel{grid-template-columns:repeat(3,44px);grid-auto-rows:44px;gap:3px;padding:4px}
  body.touch #cmdCard{grid-template-columns:repeat(4,44px);grid-auto-rows:44px;gap:3px;padding:4px}
  body.touch .cmd{min-width:44px;min-height:44px;font-size:19px}
  body.touch #joy{width:88px;height:88px;bottom:158px}
}


/* MUST stay last. An earlier pass added #lobbyMain{grid-template-columns:...} *after* the
   mobile media query, and equal specificity means source order wins even across a media
   query — so phones were still getting two columns with the difficulty row clipped off the
   right edge. Anything that re-specifies these goes above this block, not below it. */
@media (max-width:860px){
  #lobbyMain{grid-template-columns:minmax(0,1fr)}
  /* Setup first, briefing second. This was order:-1 — the map came first — which on a
     393px-tall phone made the entire opening screen a map preview with START below the
     fold. Two rules set this order; the other one is ~380 lines up and loses to this block,
     which is exactly the source-order trap the comment above warns about. */
  #lobbyBrief{order:1}
  #mapPreview{max-width:200px;margin:0 auto}
  .diffRow{flex-wrap:wrap}
  .setupRow{flex-wrap:wrap}
  .gTab{font-size:9.5px;min-width:66px}
  #guideBody{font-size:11px;max-height:26vh}
}
