/* Warcraft III Reforged-style Human interface. The ornate pieces (frames, plates, buttons, crest) are rendered
   in Blender by tools/blender/ui_art.py into assets/ui/ and used here as backgrounds and 9-slice border images. */
:root {
  --gold: #f0c860;
  --gold-d: #a07a2c;
  --gold-l: #ffe7a6;
  --ink: #0a0806;
  --text: #f2ead8;
  --muted: #b9ad94;
  --good: #7dff5a;
  --bad: #ff5a48;
  --hk: #ffcc00;
  --title: 'Cinzel', 'Friz Quadrata', 'Trajan Pro', Georgia, serif;
  --body: 'Alegreya Sans', 'Gill Sans', 'Trebuchet MS', sans-serif;
  --top-h: 40px;
  --con-h: 206px;
  --pw: 118px;            /* portrait window size */
  --btn: 44px;            /* command button size */
  --gap: 4px;
  --tb: calc((4 * var(--btn) - var(--gap)) / 5);   /* a Tech tab button: its 5 x 3 grid in the 4 x 3 card's width */
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: #000; color: var(--text); font: 15px/1.35 var(--body); overflow: hidden; overscroll-behavior: none; }
button { font: inherit; color: inherit; }
/* dvh: the height a phone's browser leaves the page (its toolbars come and go); the same as vh on a computer */
/* one column as wide as the window: nothing in it (a full top bar) can make the battlefield and the console wider */
#app { display: grid; grid-template-rows: var(--top-h) 1fr var(--con-h); grid-template-columns: minmax(0, 1fr); height: 100vh; height: 100dvh; width: 100vw; position: relative; }
/* fingers (src/client/touch.js): nothing in the game zooms, scrolls or rubber-bands the page; the dialogs, the info panel
   and the lobby chat scroll on their own */
#app { touch-action: none; -webkit-tap-highlight-color: transparent; }
#ov-body, #info, .lb-log { touch-action: pan-y; }
input, select { touch-action: manipulation; }
/* preload the hover/active chrome so the first hover does not flicker */
#app::after { content: ''; position: absolute; width: 0; height: 0; overflow: hidden; pointer-events: none;
  background: url(assets/ui/button_hover.png?v=99dfd38af943), url(assets/ui/button_active.png?v=99dfd38af943), url(assets/ui/button_empty.png?v=99dfd38af943), url(assets/ui/btn_wide_hover.png?v=99dfd38af943); }

.gold-text { background: linear-gradient(#fff3c4 0%, #f6d27a 38%, #c8922e 62%, #f4cf72 100%); -webkit-background-clip: text; background-clip: text; color: transparent; }

/* ---------------- top bar ---------------- */
#topbar { position: relative; z-index: 6; display: flex; align-items: center; justify-content: space-between; padding: 0 78px 2px; height: var(--top-h); }
#topbar::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 56px; z-index: -1; pointer-events: none;
  border-style: solid; border-color: transparent; border-width: 0 75px;
  border-image: url(assets/ui/topbar.png?v=99dfd38af943) 0 96 fill / 0 75px stretch;
  filter: drop-shadow(0 3px 4px rgba(0,0,0,0.75));
}
.tb-left { display: flex; flex: none; gap: 4px; align-items: center; }
.tb-btn, .tb-speed button {
  height: 26px; padding: 0 12px; cursor: pointer; font: 700 12px/16px var(--title); letter-spacing: 0.08em; color: var(--gold-l);
  text-shadow: 0 1px 1px #000, 0 0 4px #000; background: none;
  border-style: solid; border-color: transparent; border-width: 7px 10px;
  border-image: url(assets/ui/btn_wide.png?v=99dfd38af943) 22 34 fill / 7px 10px stretch;
}
.tb-btn:hover, .tb-speed button:hover { border-image-source: url(assets/ui/btn_wide_hover.png?v=99dfd38af943); color: #fff; }
.tb-btn:active, .tb-speed button:active { transform: translateY(1px); }
.tb-speed { display: flex; gap: 1px; margin-left: 6px; }
.tb-speed button { padding: 0 3px; min-width: 38px; }
.tb-speed button.on { border-image-source: url(assets/ui/btn_wide_hover.png?v=99dfd38af943); color: #fff; text-shadow: 0 0 6px rgba(255,210,100,0.9), 0 1px 1px #000; }

.tb-plaque { position: absolute; left: 50%; top: 0; width: 280px; height: 78px; transform: translateX(-50%); pointer-events: none;
  background: url(assets/ui/topbar_center.png?v=99dfd38af943) 0 0 / 100% 100% no-repeat; filter: drop-shadow(0 4px 6px rgba(0,0,0,0.7)); }
.tb-title { position: absolute; left: 56px; right: 56px; top: 9px; height: 46px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
.tb-title b { font: 800 15px/1.05 var(--title); letter-spacing: 0.12em; text-transform: uppercase; filter: drop-shadow(0 1px 1px #000); }
.tb-title small { display: block; max-width: 100%; margin-top: 2px; font: 600 11px/1.1 var(--body); color: var(--muted); letter-spacing: 0.04em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-shadow: 0 1px 1px #000; }

.tb-res { display: flex; gap: 16px; align-items: center; min-width: 0; }
/* the Chat button's icon, for the upright phone's top bar */
#btn-chat svg { display: none; width: 18px; height: 18px; margin: auto; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linejoin: round; filter: drop-shadow(0 1px 1px #000); }
.res { display: flex; align-items: center; gap: 5px; font: 800 15px var(--body); text-shadow: 0 1px 2px #000; }
.res b { color: #fff; min-width: 26px; font-weight: 800; }
#r-gold { color: #ffe08a; }
.res-sub { color: var(--muted); font-size: 12px; font-weight: 600; }
.ico { width: 24px; height: 24px; display: inline-block; flex: 0 0 auto; background: center / contain no-repeat; filter: drop-shadow(0 1px 1px rgba(0,0,0,0.8)); }
.ico-gold { background-image: url(assets/ui/res_gold.png?v=99dfd38af943); }
.ico-income { background-image: url(assets/ui/res_income.png?v=99dfd38af943); }
.ico-lives { background-image: url(assets/ui/res_lives.png?v=99dfd38af943); }
.ico-level { background-image: url(assets/ui/res_level.png?v=99dfd38af943); }
.ico-lumber { background-image: url(assets/ui/res_lumber.png?v=99dfd38af943); }
.ico-wisp { background-image: url(assets/ui/res_wisp.png?v=99dfd38af943); }

/* ---------------- battlefield ---------------- */
#stage { position: relative; background: radial-gradient(ellipse at center, #10140c, #000 75%); overflow: hidden; display: flex; align-items: center; justify-content: center; }
#view-wrap { position: relative; }
#view { display: block; cursor: default; image-rendering: auto; }
#view.placing { cursor: crosshair; }

#announce { position: absolute; left: 0; right: 0; top: 11%; text-align: center; pointer-events: none; opacity: 0; transform: translateY(-6px); transition: opacity 0.6s, transform 0.6s; }
#announce.show { opacity: 1; transform: none; }
.a-title { display: inline-block; font: 900 40px/1.1 var(--title); letter-spacing: 0.1em; text-transform: uppercase; padding: 0 0.3em;
  background: linear-gradient(#fff6cf 0%, #f8d77e 40%, #c58c26 60%, #f6d47a 100%); -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 2px 0 #000) drop-shadow(0 0 10px rgba(0,0,0,0.9)); }
.a-rule { width: min(420px, 60%); height: 14px; margin: 2px auto 0; background:
  radial-gradient(circle at 50% 50%, #9fd0ff 0 3px, #2a64c4 4px, #e8c05a 5px 6px, transparent 7px),
  linear-gradient(90deg, transparent, #c8922e 18%, #ffe39a 50%, #c8922e 82%, transparent) center / 100% 2px no-repeat;
  filter: drop-shadow(0 1px 1px #000); }
.a-sub { font: 700 19px var(--title); color: #fff; margin-top: 4px; letter-spacing: 0.05em; text-shadow: 0 2px 2px #000, 0 0 10px #000; }
#error { position: absolute; left: 0; right: 0; bottom: 9%; text-align: center; font: 800 19px var(--body); color: #ffd84a; text-shadow: 0 2px 2px #000, 0 0 8px #000; pointer-events: none; opacity: 0; transition: opacity 0.3s; }
#error.show { opacity: 1; }
#msgs { position: absolute; left: 16px; bottom: 12px; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; max-width: min(620px, 55%); pointer-events: none; font: 700 14px var(--body); }
#msgs div { text-shadow: 0 1px 2px #000, 0 0 6px #000; transition: opacity 1s; }
#wave-timer { position: absolute; right: 12px; top: 12px; padding: 0 6px; min-width: 150px; font: 700 14px var(--title); color: var(--gold-l); text-shadow: 0 1px 2px #000; pointer-events: none;
  border-style: solid; border-color: transparent; border-width: 12px; border-image: url(assets/ui/tooltip.png?v=99dfd38af943) 36 fill / 18px stretch; }
#wave-timer:empty { display: none; }
#wave-timer.tap { pointer-events: auto; cursor: pointer; }   /* a finger calls the level by tapping it */
/* what a finger does next (placing a tower), over the bottom of the view */
#hint { position: absolute; left: 50%; bottom: 10px; z-index: 3; display: none; max-width: calc(100% - 120px); padding: 0 6px; transform: translateX(-50%);
  font: 700 13px/1.3 var(--body); color: var(--gold-l); text-align: center; text-shadow: 0 1px 2px #000; pointer-events: none;
  border-style: solid; border-color: transparent; border-width: 10px; border-image: url(assets/ui/tooltip.png?v=99dfd38af943) 36 fill / 16px stretch; }
#hint.show { display: block; }
#msgs.hinted { bottom: 54px; }
#wave-timer small { display: block; font: 600 12px var(--body); color: var(--muted); letter-spacing: 0; }

/* ---------------- console ---------------- */
#console {
  position: relative; z-index: 5; display: grid; align-items: stretch;
  grid-template-columns: minmax(210px, 290px) auto minmax(0, 1fr) auto; gap: 10px; padding: 30px 30px 8px 30px;
  background: #15130f url(assets/ui/console_bg.png?v=99dfd38af943) repeat-x 0 0 / auto 100%;
  box-shadow: 0 -6px 14px rgba(0,0,0,0.75);
}
#console::before, #console::after {
  content: ''; position: absolute; top: -4px; width: 88px; height: 88px; z-index: 3; pointer-events: none;
  background: url(assets/ui/corner.png?v=99dfd38af943) 0 0 / 100% 100% no-repeat; filter: drop-shadow(0 2px 3px rgba(0,0,0,0.8));
}
#console::before { left: -4px; }
#console::after { right: -4px; transform: scaleX(-1); }
.panel {
  position: relative; min-width: 0; min-height: 0;
  border-style: solid; border-color: transparent; border-width: 18px;
  border-image: url(assets/ui/frame_gold.png?v=99dfd38af943) 64 / 32px round;
  background: radial-gradient(ellipse at 50% 0%, rgba(60,52,40,0.55), rgba(0,0,0,0) 70%), linear-gradient(#0f0d0b, #070605);
  background-clip: padding-box; background-origin: padding-box;
  box-shadow: inset 0 0 18px rgba(0,0,0,0.9);
  filter: drop-shadow(0 3px 4px rgba(0,0,0,0.7));
}
#mm-panel { display: flex; align-items: center; justify-content: center; border-width: 22px; border-image: url(assets/ui/frame_minimap.png?v=99dfd38af943) 72 / 36px stretch; background: #000; background-clip: padding-box; }
#minimap { width: 100%; height: 100%; display: block; }
/* zoom in / out, small round buttons on the minimap frame's left edge (as WC3 keeps its minimap buttons beside it) */
#mm-zoom { position: absolute; z-index: 2; left: -19px; top: 50%; transform: translateY(-50%); display: flex; flex-direction: column; gap: 5px; }
#mm-zoom button { width: 22px; height: 22px; padding: 0; cursor: pointer; border-radius: 50%; font: 900 15px/20px var(--title); color: var(--gold-l); text-shadow: 0 1px 1px #000;
  background: radial-gradient(circle at 50% 35%, #3e3422, #120e08 75%); border: 1px solid #000; box-shadow: 0 0 0 1px #a07a2c, 0 2px 3px rgba(0,0,0,0.8); }
#mm-zoom button:hover:not(:disabled) { color: #fff; box-shadow: 0 0 0 1px var(--gold), 0 0 8px rgba(255,200,80,0.45); }
#mm-zoom button:active:not(:disabled) { transform: translateY(1px); }
#mm-zoom button:disabled { opacity: 0.4; cursor: default; }
#mm-zoom svg, #view-tools svg { display: block; margin: auto; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
#mm-zoom svg { width: 12px; height: 12px; }

#portrait-frame { position: relative; align-self: center; width: var(--pw); height: var(--pw); margin: 0 calc(var(--pw) * 0.17 + 4px);
  background: radial-gradient(circle at 50% 38%, #26303e, #07090c 78%); }
#portrait-frame::after { content: ''; position: absolute; pointer-events: none;
  left: calc(var(--pw) * -36 / 216); top: calc(var(--pw) * -108 / 216); width: calc(var(--pw) * 288 / 216); height: calc(var(--pw) * 360 / 216);
  background: url(assets/ui/portrait_frame.png?v=99dfd38af943) 0 0 / 100% 100% no-repeat; filter: drop-shadow(0 3px 4px rgba(0,0,0,0.75)); }
#portrait { width: 100%; height: 100%; display: block; }

#info-panel { display: flex; padding: 2px 8px; }
#info { flex: 1; min-width: 0; overflow: hidden; }
#info h2 { margin: 0 0 1px; font: 800 19px/1.2 var(--title); letter-spacing: 0.03em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: linear-gradient(#fff3c4 0%, #f6d27a 45%, #d19a36 70%, #f4cf72 100%); -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 1px 1px #000); }
#info .tier { color: var(--muted); font: 700 11px var(--body); letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 5px; }
#info .stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 1px 16px; font-size: 14px; }
#info .stats div { display: flex; justify-content: space-between; gap: 8px; padding: 1px 0; border-bottom: 1px solid rgba(232,192,90,0.12); }
#info .stats span { color: var(--muted); }
#info .stats b { color: #fff; font-weight: 700; text-align: right; }
#info .tags { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 4px; }
#info .tag { font: 800 10.5px var(--body); text-transform: uppercase; letter-spacing: 0.06em; padding: 1px 7px; border-radius: 2px; color: var(--gold-l);
  background: linear-gradient(#2e271c, #17130d); border: 1px solid #000; box-shadow: 0 0 0 1px #6a5228, inset 0 1px 0 rgba(255,230,160,0.15); }
#info .tag.bad { color: #ffb4a8; box-shadow: 0 0 0 1px #7a2a22, inset 0 1px 0 rgba(255,160,140,0.15); }
#info .tag.good { color: #c8ffb4; box-shadow: 0 0 0 1px #2e6a24, inset 0 1px 0 rgba(180,255,160,0.15); }
#info .hp { height: 13px; margin: 4px 0 6px; background: #000; border: 1px solid #000; box-shadow: 0 0 0 1px #6a5228; position: relative; }
#info .hp i { position: absolute; inset: 0 auto 0 0; background: linear-gradient(#7dff6a, #2aa81e 55%, #157a10); }
#info .hp em { position: absolute; inset: 0; text-align: center; font: 800 10px/13px var(--body); color: #fff; text-shadow: 0 1px 1px #000; font-style: normal; }
/* a panel too small for what it shows (LtwHud.fitInfo): tighter rows that flow to their width, then smaller type, and
   a scrollbar as the last resort */
#info.fit1 h2, #info.fit2 h2 { font-size: 17px; margin: 0; }
#info.fit1 .tier, #info.fit2 .tier { margin-bottom: 2px; }
#info.fit1 .hp, #info.fit2 .hp { margin: 2px 0 3px; }
#info.fit1 .stats, #info.fit2 .stats { display: flex; flex-wrap: wrap; column-gap: 12px; font-size: 13px; }
#info.fit1 .stats div, #info.fit2 .stats div { flex: 1 1 auto; min-width: 104px; padding: 0; }
#info.fit1 .tags, #info.fit2 .tags { margin-top: 3px; gap: 3px; }
#info.fit2 { overflow-y: auto; scrollbar-width: thin; scrollbar-color: #6a5228 transparent; }
#info.fit2 h2 { font-size: 15px; }
#info.fit2 .tier { font-size: 10px; }
#info.fit2 .hp { height: 11px; }
#info.fit2 .hp em { font-size: 9px; line-height: 11px; }
#info.fit2 .stats { font-size: 12px; line-height: 1.25; }
#info.fit2 .tag { font-size: 9.5px; padding: 0 5px; }
#info .lore { margin-top: 6px; color: var(--muted); font-size: 13px; font-style: italic; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

#cmd-panel { padding: 2px; border-width: 12px; border-image-width: 24px; align-self: center; }
#commands { display: grid; grid-template-columns: repeat(4, var(--btn)); grid-template-rows: repeat(3, var(--btn)); gap: var(--gap); }
.cmd { position: relative; width: var(--btn); height: var(--btn); padding: 0; cursor: pointer; border: 0; background: #0b0a09; overflow: visible; }
.cmd canvas { position: absolute; left: 2px; top: 2px; width: calc(100% - 4px); height: calc(100% - 4px); display: block; transition: filter 0.15s; }
.cmd::after { content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none; background: url(assets/ui/button.png?v=99dfd38af943) 0 0 / 100% 100% no-repeat; }
.cmd:hover::after { background-image: url(assets/ui/button_hover.png?v=99dfd38af943); }
.cmd:hover canvas { filter: brightness(1.18) saturate(1.08); }
.cmd:hover { box-shadow: 0 0 10px rgba(255,205,90,0.55); }
.cmd:active canvas { transform: translateY(1px); filter: brightness(0.9); }
.cmd .hk { position: absolute; z-index: 2; left: 4px; top: 2px; font: 800 12px var(--title); color: var(--hk); text-shadow: 0 1px 1px #000, 0 0 3px #000, 0 0 3px #000; }
.cmd .cost { position: absolute; z-index: 2; right: 4px; bottom: 2px; font: 800 11px var(--body); color: #ffe39a; text-shadow: 0 1px 1px #000, 0 0 3px #000, 0 0 3px #000; }
.cmd.poor canvas { filter: grayscale(0.85) brightness(0.5); }
.cmd.poor .cost { color: #ff7a6a; }
.cmd.empty { cursor: default; background: transparent; box-shadow: none; }
.cmd.empty::after { background-image: url(assets/ui/button_empty.png?v=99dfd38af943); }
.cmd.active::after { background-image: url(assets/ui/button_active.png?v=99dfd38af943); }
.cmd.active { box-shadow: 0 0 12px rgba(125,255,90,0.6); }

/* ---------------- tooltip ---------------- */
#tooltip { position: fixed; z-index: 10; max-width: 330px; padding: 2px 4px; pointer-events: none; display: none; font-size: 14px;
  border-style: solid; border-color: transparent; border-width: 12px; border-image: url(assets/ui/tooltip.png?v=99dfd38af943) 36 fill / 18px stretch;
  filter: drop-shadow(0 6px 12px rgba(0,0,0,0.75)); }
#tooltip.show { display: block; }
#tooltip .t-title { font: 800 15px var(--body); color: #fff; letter-spacing: 0.01em; }
#tooltip .t-title u { text-decoration: none; color: var(--hk); }
#tooltip .t-cost { margin: 2px 0 5px; padding-bottom: 5px; color: #ffe39a; display: flex; align-items: center; gap: 5px; font-weight: 800;
  border-bottom: 1px solid; border-image: linear-gradient(90deg, rgba(232,192,90,0.7), rgba(232,192,90,0.05)) 1; }
#tooltip .t-cost.poor { color: #ff7a6a; }
#tooltip .t-cost i { width: 16px; height: 16px; }
#tooltip .t-line { color: #e6dcc6; }
#tooltip .t-line span { color: var(--muted); }
#tooltip .t-note { margin-top: 5px; color: #d9c48c; font-style: italic; font-size: 13px; }

/* ---------------- overlay dialogs ---------------- */
/* --crest-room: how far the crest reaches above the box (it stands on the box's top frame); the box never grows past
   the window, its body scrolls instead and #ov-foot (the dialog's buttons) stays in view */
#overlay { --crest-room: 124px; position: fixed; inset: 0; z-index: 20; display: none; align-items: center; justify-content: center; padding: calc(var(--crest-room) + 4px) 0 10px;
  background: radial-gradient(ellipse at center, rgba(10,8,6,0.5), rgba(0,0,0,0.92)); }
#overlay.show { display: flex; }
.ov-box { position: relative; display: flex; flex-direction: column; align-items: stretch; width: min(580px, 94vw); max-height: calc(100vh - var(--crest-room) - 14px);
  max-height: calc(100dvh - var(--crest-room) - 14px);   /* a phone's browser bars: the dialog's buttons stay above them */
  padding: 46px 30px 18px; text-align: center;
  border-style: solid; border-color: transparent; border-width: 34px; border-image: url(assets/ui/dialog.png?v=99dfd38af943) 120 fill / 60px round;
  filter: drop-shadow(0 20px 40px rgba(0,0,0,0.9)); }
.ov-box > h1, .ov-box > .ov-sub, #ov-foot { flex: none; }
#ov-foot { display: flex; flex-direction: column; align-items: center; }
#ov-foot > .ov-actions { margin-top: 8px; }
.ov-crest { position: absolute; left: 50%; top: -158px; width: 236px; height: 184px; transform: translateX(-50%); pointer-events: none;
  background: url(assets/ui/crest.png?v=99dfd38af943) center / contain no-repeat; filter: drop-shadow(0 6px 8px rgba(0,0,0,0.8)); }
.ov-box h1 { margin: 0; font: 900 46px/1.1 var(--title); letter-spacing: 0.08em;
  background: linear-gradient(#fff6cf 0%, #f8d77e 40%, #c58c26 62%, #f6d47a 100%); -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 3px 0 #000) drop-shadow(0 0 14px rgba(232,192,90,0.25)); }
.ov-sub { font: 700 13px var(--title); color: var(--muted); letter-spacing: 0.3em; text-transform: uppercase; margin: 2px 0 12px; }
.ov-sub::after { content: ''; display: block; width: 70%; height: 12px; margin: 8px auto 0; background:
  radial-gradient(circle at 50% 50%, #9fd0ff 0 2.5px, #2a64c4 3.5px, #e8c05a 4.5px 5.5px, transparent 6.5px),
  linear-gradient(90deg, transparent, #a07a2c 15%, #ffe39a 50%, #a07a2c 85%, transparent) center / 100% 1px no-repeat; }
#ov-body p { color: var(--text); margin: 8px 0 12px; }
.ov-keys { text-align: left; margin: 0 auto 16px; padding-left: 18px; color: var(--muted); font-size: 14px; max-width: 470px; }
.ov-keys li { margin: 3px 0; }
.ov-keys b { color: var(--hk); font-family: var(--title); }
.ov-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 20px; text-align: left; max-width: 320px; margin: 0 auto 16px; }
.ov-stats span { color: var(--muted); }
.ov-stats b { color: #fff; text-align: right; }
#ov-progress { height: 10px; margin: 6px auto 16px; max-width: 360px; background: #000; border: 1px solid #000; box-shadow: 0 0 0 1px var(--gold-d), 0 0 0 2px #000; }
#ov-progress div { height: 100%; width: 0%; background: linear-gradient(#fff0b8, #e0a83a 50%, #8a5a18); transition: width 0.2s; }
.wc-btn { min-width: 210px; height: 46px; padding: 0 22px; cursor: pointer; font: 800 17px/1 var(--title); letter-spacing: 0.12em; color: var(--gold-l);
  text-shadow: 0 1px 1px #000, 0 0 6px #000; background: none;
  border-style: solid; border-color: transparent; border-width: 11px 17px; border-image: url(assets/ui/btn_wide.png?v=99dfd38af943) 22 34 fill / 11px 17px stretch; }
.wc-btn:hover:not(:disabled) { border-image-source: url(assets/ui/btn_wide_hover.png?v=99dfd38af943); color: #fff; text-shadow: 0 0 8px rgba(255,210,100,0.9), 0 1px 1px #000; }
.wc-btn:active:not(:disabled) { transform: translateY(1px); }
.wc-btn:disabled { opacity: 0.6; cursor: default; }

/* ---------------- modes ---------------- */
body:not(.ltw) .ltw-only { display: none !important; }
body.ltw .classic-only, body.ltw #commands, body.ltw #wave-timer { display: none !important; }

/* ---------------- Line Tower Wars: scoreboard (multiboard) and the income list under it ---------------- */
#side { position: absolute; right: 10px; top: 10px; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; pointer-events: none; }
#board { position: relative; min-width: 214px; padding: 0 3px 1px; font: 700 13px/1.25 var(--body); color: var(--text); pointer-events: auto;
  border-style: solid; border-color: transparent; border-width: 12px; border-image: url(assets/ui/tooltip.png?v=99dfd38af943) 36 fill / 18px stretch;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.7)); user-select: none; }
.bd-title { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 0 3px 3px; margin-bottom: 2px;
  border-bottom: 1px solid; border-image: linear-gradient(90deg, rgba(232,192,90,0.7), rgba(232,192,90,0.08)) 1; }
.bd-title b { font: 800 12px var(--title); letter-spacing: 0.1em; text-transform: uppercase; color: var(--gold-l); text-shadow: 0 1px 1px #000; }
.bd-clock { font: 700 12px var(--body); color: var(--muted); }
.bd-title { cursor: pointer; }
.bd-fold { width: 0; height: 0; margin-left: -6px; align-self: center; border: 4px solid transparent; border-top: 5px solid var(--gold-l); border-bottom: 0; }
#board.folded .bd-fold { border-top: 4px solid transparent; border-bottom: 4px solid transparent; border-left: 5px solid var(--gold-l); border-right: 0; }
#board.folded .bd-head, #board.folded .bd-row { display: none; }
#board.folded .bd-title { margin-bottom: 0; padding-bottom: 0; border-bottom: 0; }
.bd-head, .bd-row { display: grid; grid-template-columns: minmax(0, 1fr) 42px 50px; gap: 6px; align-items: center; padding: 1px 4px; }
.bd-head { font: 700 10px var(--body); color: var(--muted); text-transform: uppercase; letter-spacing: 0.07em; }
.bd-head span:not(:first-child), .bd-row .lv, .bd-row .in { text-align: right; }
.bd-row { cursor: pointer; text-shadow: 0 1px 1px #000; }
.bd-row:hover { background: rgba(255,230,160,0.09); }
.bd-row.viewing { background: rgba(255,255,255,0.05); }
.bd-row.me { background: linear-gradient(90deg, rgba(232,192,90,0.2), rgba(232,192,90,0.04)); box-shadow: inset 2px 0 0 var(--gold); }
.bd-row.target { box-shadow: inset 2px 0 0 #ff4a3a; }
.bd-row .nm { display: flex; align-items: center; gap: 5px; min-width: 0; white-space: nowrap; overflow: hidden; }
.bd-row .nm i { width: 10px; height: 10px; flex: none; box-shadow: 0 0 0 1px #000; }
.bd-row .nm em { font: 600 10.5px var(--body); color: var(--muted); font-style: normal; }
.bd-row.target .nm em::after { content: ' · target'; color: #ff8a7a; }
.bd-row .lv { color: #fff; }
.bd-row .in { color: #ffe08a; }
.bd-row.dead { opacity: 0.6; }
.bd-row.dead .lv { color: #a89c86; font-style: italic; }
.bd-row .xt { display: none; padding: 0 3px; font: 800 9px/12px var(--body); letter-spacing: 0.05em; text-transform: uppercase; text-decoration: none;
  color: #ffd84a; border: 1px solid rgba(255,216,74,0.5); background: rgba(80,60,10,0.5); }
.bd-row .xt.on { display: inline-block; }
/* a click or a tap puts the income list away until the next one (#side lets everything else through to the map) */
#income-list { display: none; min-width: 150px; padding: 0 4px 1px; font: 700 12.5px/1.3 var(--body); color: var(--text); pointer-events: auto; cursor: pointer;
  border-style: solid; border-color: transparent; border-width: 10px; border-image: url(assets/ui/tooltip.png?v=99dfd38af943) 36 fill / 16px stretch;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.7)); animation: fade-in 0.25s; }
#income-list.show { display: block; }
.il-title { font: 800 11px var(--title); letter-spacing: 0.1em; text-transform: uppercase; color: var(--gold-l); text-shadow: 0 1px 1px #000; margin-bottom: 2px; }
.il-grid { display: grid; grid-template-columns: auto auto auto auto; gap: 0 8px; align-items: center; }
.il-grid span { display: flex; align-items: center; gap: 4px; color: var(--muted); }
.il-grid span i { width: 8px; height: 8px; box-shadow: 0 0 0 1px #000; }
.il-grid b { color: #ffe08a; text-align: right; }
.il-grid .idle { opacity: 0.55; }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* ---------------- Line Tower Wars: command card tabs and send buttons ---------------- */
body.ltw #cmd-panel { display: flex; gap: 5px; align-items: stretch; }
#cmd-tabs { display: flex; flex-direction: column; gap: 2px; width: 74px; }
.cmd-tab { position: relative; flex: 1; min-height: 0; padding: 0 2px; cursor: pointer; font: 800 11px/1 var(--body); letter-spacing: 0.02em; color: var(--muted); white-space: nowrap;
  text-shadow: 0 1px 1px #000; background: none;
  border-style: solid; border-color: transparent; border-width: 5px 9px; border-image: url(assets/ui/btn_wide.png?v=99dfd38af943) 22 34 fill / 5px 9px stretch; }
.cmd-tab:hover { color: #fff; border-image-source: url(assets/ui/btn_wide_hover.png?v=99dfd38af943); }
.cmd-tab.on { color: var(--gold-l); border-image-source: url(assets/ui/btn_wide_hover.png?v=99dfd38af943); text-shadow: 0 0 6px rgba(255,210,100,0.85), 0 1px 1px #000; }
.cmd-tab .tab-n { margin-left: 4px; color: #a6d6ff; font-size: 10px; }
.cmd-tab .tab-n:empty { display: none; }
/* the card keeps one size; the Tech tab packs its 5 x 3 grid (one column per element) into it (--tb, set on :root so
   the phone layouts can give it room of its own) */
#ltw-commands { display: grid; grid-template-columns: repeat(4, var(--btn)); grid-template-rows: repeat(3, var(--btn)); gap: var(--gap);
  width: calc(4 * var(--btn) + 3 * var(--gap)); height: calc(3 * var(--btn) + 2 * var(--gap)); align-content: center; }
#ltw-commands.tech { grid-template-columns: repeat(5, var(--tb)); grid-template-rows: repeat(3, var(--tb)); }
#ltw-commands.tech .cmd { width: var(--tb); height: var(--tb); }
#ltw-commands.tech .cmd .hk { left: 3px; top: 1px; font-size: 10px; }
.cmd.hidden { display: none; }
.cmd .own { display: none; position: absolute; z-index: 2; right: 3px; bottom: 0; font: 900 12px var(--body); color: #8cff6a; text-shadow: 0 1px 1px #000, 0 0 3px #000, 0 0 3px #000; }
.cmd.owned .own { display: block; }
#ltw-commands .cmd canvas.req { left: auto; top: auto; right: 2px; bottom: 2px; z-index: 2; width: 42%; height: 42%; filter: none; transform: none;
  box-shadow: 0 0 0 1px #000, 0 0 0 2px #a07a2c, 0 0 6px #000; }
.cmd.owned::before { content: ''; position: absolute; inset: 2px; z-index: 1; pointer-events: none; box-shadow: inset 0 0 0 2px rgba(125,255,90,0.7), inset 0 0 12px rgba(125,255,90,0.35); }
.cmd.armed { animation: armed 0.7s ease-in-out infinite alternate; }
@keyframes armed { from { box-shadow: 0 0 5px rgba(255,90,40,0.45); } to { box-shadow: 0 0 16px rgba(255,120,40,0.95); } }
.cmd .inc { position: absolute; z-index: 2; right: 3px; top: 2px; font: 800 10px var(--body); color: #9dff7a; text-shadow: 0 1px 1px #000, 0 0 3px #000, 0 0 3px #000; }
.cmd .inc.neg { color: #ff6a5a; }
.cmd .stk { position: absolute; z-index: 2; left: 4px; bottom: 2px; font: 800 10px var(--body); color: #fff; text-shadow: 0 1px 1px #000, 0 0 3px #000, 0 0 3px #000; }
/* the restock bar: --rs (0..1) of the button's width inside a 3 px margin either side, so a full one stops 3 px short of the edge */
.cmd .rs { position: absolute; z-index: 2; left: 3px; top: 1px; height: 2px; width: calc((100% - 6px) * var(--rs, 0)); background: linear-gradient(90deg, #4aa6ff, #bfe8ff); pointer-events: none; }
.cmd .sweep { position: absolute; inset: 2px; pointer-events: none; background: conic-gradient(transparent calc(var(--p, 1) * 1turn), rgba(0,0,0,0.72) 0); }
.cmd .lock { position: absolute; z-index: 2; inset: 2px; display: none; align-items: center; justify-content: center; background: rgba(0,0,0,0.42);
  font: 800 11px var(--body); color: #e8dcc0; text-shadow: 0 1px 1px #000; }
.cmd.locked .lock { display: flex; }
.cmd.locked canvas, .cmd.out canvas, .cmd.off canvas { filter: grayscale(0.85) brightness(0.55); }
.cmd .one { position: absolute; z-index: 2; left: 50%; bottom: 2px; transform: translateX(-50%); font: 800 9px var(--body); color: #ffd84a; text-shadow: 0 1px 1px #000, 0 0 3px #000; }
/* a send that also costs lumber: its lumber over the gold cost, red when you have too little */
.cmd .lum { position: absolute; z-index: 2; right: 2px; bottom: 14px; display: flex; align-items: center; gap: 1px; font: 800 10px/1 var(--body); color: #e8d2a0;
  text-shadow: 0 1px 1px #000, 0 0 3px #000, 0 0 3px #000; }
.cmd .lum .ico { width: 11px; height: 11px; }
.cmd.poor-lumber .lum { color: #ff7a6a; }
.cmd.locked .inc, .cmd.locked .cost { opacity: 0.55; }
#tooltip .t-why { margin-top: 5px; color: #ff7a6a; font-weight: 800; }
#tooltip .t-warn { color: #ffb08a; font-weight: 800; }
#tooltip .t-have { color: var(--muted); font-weight: 600; }
#tooltip b.pos { color: #9dff7a; }
#tooltip b.neg { color: #ff6a5a; }
#tooltip .t-cost .poor { color: #ff7a6a; }
#info .swatch { display: inline-block; width: 9px; height: 9px; margin-right: 6px; box-shadow: 0 0 0 1px #000; }
#msgs div.quiet { font-size: 12px; font-weight: 600; }
#msgs div.help { font-size: 13px; font-weight: 600; }
#msgs div.chat .say { color: #fff; font-weight: 600; }
#msgs div .times { color: #fff; }
#msgs.chatting { bottom: 52px; }
#info .hp.mid i { background: linear-gradient(#ffe86a, #c8a018 55%, #8a6a0a); }
#info .hp.low i { background: linear-gradient(#ff8a6a, #c8321a 55%, #8a160a); }
#info .stats.wide { grid-template-columns: 1fr; }
#info .stats.wide b { text-align: left; font-weight: 600; }
#info .stats .attacking b { color: #ffb08a; }
#info .stats b.up { color: #9dff7a; }
#info .tier .alarm { color: #ff8a7a; text-shadow: 0 0 6px rgba(255,60,40,0.6); }
#msgs div .note { color: #e6dcc6; font-weight: 600; }
#info .queue { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 3px 6px; margin-top: 6px; }
#info .queue .q { position: relative; height: 13px; background: #000; box-shadow: 0 0 0 1px #3a5a7a; }
#info .queue .q i { position: absolute; inset: 0 auto 0 0; background: linear-gradient(#bfe8ff, #4aa6ff 55%, #1a5a9a); }
#info .queue .q em { position: absolute; inset: 0; text-align: center; font: 800 10px/13px var(--body); color: #fff; text-shadow: 0 1px 1px #000; font-style: normal; }

/* ---------------- Line Tower Wars: the chat line (Enter or the Chat button) ---------------- */
#chat { position: absolute; left: 16px; bottom: 10px; z-index: 4; display: none; align-items: center; gap: 6px; width: min(460px, calc(100% - 32px)); padding: 0 4px;
  border-style: solid; border-color: transparent; border-width: 10px; border-image: url(assets/ui/tooltip.png?v=99dfd38af943) 36 fill / 16px stretch;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.7)); }
#chat.open { display: flex; }
#chat label { font: 800 13px var(--body); color: var(--gold-l); white-space: nowrap; text-shadow: 0 1px 1px #000; }
#chat input { flex: 1; min-width: 0; height: 24px; padding: 0 4px; font: 600 14px var(--body); color: #fff; background: rgba(0,0,0,0.45);
  border: 1px solid rgba(232,192,90,0.35); outline: none; }
#chat input:focus { border-color: rgba(255,216,74,0.7); }
#chat button { height: 24px; padding: 0 10px; cursor: pointer; font: 700 11px/1 var(--title); letter-spacing: 0.06em; color: var(--gold-l); background: none;
  border-style: solid; border-color: transparent; border-width: 5px 9px; border-image: url(assets/ui/btn_wide.png?v=99dfd38af943) 22 34 fill / 5px 9px stretch; }
#chat button:hover { border-image-source: url(assets/ui/btn_wide_hover.png?v=99dfd38af943); color: #fff; }

/* ---------------- menu, setup and end screens ---------------- */
.ov-box.wide { width: min(720px, 96vw); }
#ov-body { flex: 0 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; }
/* a scrollbar that shows (the overlay kind hides until you scroll, so nothing would say there is more) */
#ov-body::-webkit-scrollbar { width: 9px; }
#ov-body::-webkit-scrollbar-track { background: rgba(0,0,0,0.35); box-shadow: inset 0 0 0 1px rgba(232,192,90,0.15); }
#ov-body::-webkit-scrollbar-thumb { background: linear-gradient(90deg, #8a6a2c, #d8b060, #8a6a2c); border: 1px solid #000; }
@supports not selector(::-webkit-scrollbar) { #ov-body { scrollbar-color: #b08a3c rgba(0,0,0,0.35); } }
.ov-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin: 2px 0 14px; }
.wc-btn.small { min-width: 132px; height: 34px; padding: 0 14px; font-size: 13px; border-width: 8px 13px; border-image-width: 8px 13px; }
/* the pause menus' settings (the frame rate), and the mode menu's line about playing full screen (src/client/app.js) */
.ov-settings { display: flex; justify-content: center; margin: 0 0 12px; }
.ov-settings .wc-btn.small { letter-spacing: 0.06em; }
/* one row: the words (they wrap), a button, the ✕ */
.ov-app { display: flex; align-items: center; justify-content: center; gap: 10px; max-width: 470px; margin: -6px auto 12px;
  color: var(--muted); font-size: 13.5px; line-height: 1.3; text-align: center; }
.ov-app > span { min-width: 0; }
.ov-app b { color: var(--gold-l); }
.ov-app .wc-btn.small { flex: none; min-width: 0; }
.ov-share { width: 17px; height: 17px; vertical-align: -3px; fill: none; stroke: var(--gold-l); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ov-app-x { flex: none; width: 30px; height: 30px; padding: 0; cursor: pointer; border: 0; background: none; color: var(--muted); font: 800 13px var(--body); }
.ov-app-x:hover { color: var(--gold-l); }
.modes { display: flex; flex-direction: column; gap: 8px; max-width: 470px; margin: 4px auto 16px; }
.mode { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 6px 14px 8px; cursor: pointer; background: none; color: var(--gold-l); text-align: center;
  border-style: solid; border-color: transparent; border-width: 12px 18px; border-image: url(assets/ui/btn_wide.png?v=99dfd38af943) 22 34 fill / 12px 18px stretch; }
.mode b { font: 800 19px/1.1 var(--title); letter-spacing: 0.1em; text-transform: uppercase; text-shadow: 0 1px 1px #000, 0 0 6px #000; }
.mode span { font: 600 13.5px/1.25 var(--body); color: var(--muted); text-shadow: 0 1px 1px #000; }
.mode:hover:not(:disabled) { border-image-source: url(assets/ui/btn_wide_hover.png?v=99dfd38af943); }
.mode:hover:not(:disabled) b { color: #fff; text-shadow: 0 0 8px rgba(255,210,100,0.9), 0 1px 1px #000; }
.mode:active:not(:disabled) { transform: translateY(1px); }
.mode:disabled { opacity: 0.5; cursor: default; }
.mode:focus-visible { outline: none; border-image-source: url(assets/ui/btn_wide_hover.png?v=99dfd38af943); box-shadow: 0 0 0 2px var(--gold), 0 0 14px rgba(255,200,80,0.5); }
/* the map picker (src/client/screens.js): a card per map, its picture in the minimap's frame, its name and players under
   it; two by two, as wide as the window's height lets both rows show (a short window takes one row of four, a phone a
   column or a row of its own, below). A locked map is greyed with "Coming later" over it. */
.ov-box.picker { width: min(1180px, 96vw, max(620px, calc(2 * (100vh - var(--crest-room)) - 620px)));
  width: min(1180px, 96vw, max(620px, calc(2 * (100dvh - var(--crest-room)) - 620px))); }
.maps { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 16px; margin: 2px 0 14px; }
.map-card { display: flex; flex-direction: column; gap: 5px; min-width: 0; padding: 7px 7px 6px; cursor: pointer; text-align: left; color: var(--gold-l);
  background: linear-gradient(rgba(46,39,28,0.85), rgba(16,13,9,0.55)); border: 1px solid rgba(232,192,90,0.2); box-shadow: inset 0 0 18px rgba(0,0,0,0.5);
  transition: border-color 0.15s, box-shadow 0.15s; }
.map-card:hover:not(:disabled), .map-card:focus-visible { border-color: rgba(255,216,120,0.7); box-shadow: inset 0 0 18px rgba(0,0,0,0.5), 0 0 14px rgba(255,200,80,0.35); }
.map-card:focus-visible { outline: none; box-shadow: inset 0 0 18px rgba(0,0,0,0.5), 0 0 0 2px var(--gold), 0 0 18px rgba(255,200,80,0.5); }
.map-card:hover:not(:disabled) .map-pic img, .map-card:focus-visible .map-pic img { filter: brightness(1.12) saturate(1.08); }
.map-card:active:not(:disabled) { transform: translateY(1px); }
.map-card:disabled { cursor: default; }
.map-cap { display: flex; align-items: baseline; justify-content: space-between; gap: 4px 10px; flex-wrap: wrap; padding: 0 4px; }
.map-cap b { font: 800 16px/1.15 var(--title); letter-spacing: 0.08em; text-transform: uppercase; text-shadow: 0 1px 1px #000, 0 0 6px #000; }
.map-cap em { font: 600 13px var(--body); font-style: normal; color: var(--muted); white-space: nowrap; }
.map-card:hover:not(:disabled) .map-cap b, .map-card:focus-visible .map-cap b { color: #fff; text-shadow: 0 0 8px rgba(255,210,100,0.9), 0 1px 1px #000; }
.map-card.locked .map-cap b { color: var(--muted); }
/* the picture: 2:1 in the frame; a picture of another shape is shown whole (.fit), a missing one is an unexplored map */
.map-pic { position: relative; display: block; flex: none; border-style: solid; border-color: transparent; border-width: 14px;
  border-image: url(assets/ui/frame_minimap.png?v=99dfd38af943) 72 / 28px stretch; background: #050403 padding-box; filter: drop-shadow(0 3px 5px rgba(0,0,0,0.7)); }
.map-pic img { display: block; width: 100%; height: auto; aspect-ratio: 2 / 1; object-fit: cover; transition: filter 0.15s; -webkit-user-drag: none; }
.map-pic.fit img { object-fit: contain; }
.map-pic.none img { visibility: hidden; }
.map-pic.none { background: radial-gradient(ellipse at 50% 50%, rgba(232,192,90,0.1), transparent 65%),
  repeating-linear-gradient(0deg, rgba(232,192,90,0.07) 0 1px, transparent 1px 22px), repeating-linear-gradient(90deg, rgba(232,192,90,0.07) 0 1px, transparent 1px 22px), #0b0907;
  background-clip: padding-box; }
.map-pic.none::before { content: ''; position: absolute; inset: 0; margin: auto; width: 26%; height: 40%; opacity: 0.3;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e8c05a' stroke-width='1.2' stroke-linejoin='round'%3E%3Cpath d='M3 6l6-2 6 2 6-2v14l-6 2-6-2-6 2zM9 4v14M15 6v14'/%3E%3C/svg%3E") center / contain no-repeat; }
/* a locked map: dimmed, but with its players' colours, so the layout still reads; "Coming later" sits on the frame's top
   edge (top: minus half the frame), off the map */
.map-card.locked .map-pic img { filter: saturate(0.55) brightness(0.72); }
.map-lock { position: absolute; left: 50%; top: -7px; transform: translate(-50%, -50%); padding: 1px 10px; white-space: nowrap;
  font: 800 11px/1.2 var(--title); letter-spacing: 0.14em; text-transform: uppercase; color: var(--gold-l); text-shadow: 0 1px 1px #000;
  border-style: solid; border-color: transparent; border-width: 6px; border-image: url(assets/ui/tooltip.png?v=99dfd38af943) 36 fill / 12px stretch; }
/* a map's own screen (and Classic's intro): the picture beside what the map is and its ways to play, as a WC3 game
   setup shows the map; upright windows put the picture on top (below) */
.ov-box.map-box { width: min(1060px, 96vw); }
.map-ways { display: flex; align-items: center; gap: 18px; margin: 4px 0 12px; }
.map-pic.big { width: 56%; }
.map-side { display: flex; flex-direction: column; gap: 10px; flex: 1 1 0; min-width: 0; }
#ov-body .map-about { margin: 0; color: var(--muted); font-size: 14.5px; text-align: left; }
#ov-body .map-side p { margin: 0; text-align: left; }
.map-side .modes { width: 100%; margin: 0; }
.map-side .ov-keys { margin: 0; }
/* the lobby's (and the join screen's) map: a small picture, its name and players */
.lb-map { display: flex; align-items: center; gap: 12px; text-align: left; }
.on-wrap .lb-map { justify-content: center; margin: 0 auto 12px; }
.map-pic.thumb { width: 132px; border-width: 8px; border-image-width: 16px; filter: drop-shadow(0 2px 3px rgba(0,0,0,0.7)); }
.lb-mapinfo { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.lb-mapinfo b { font: 800 15px/1.15 var(--title); letter-spacing: 0.06em; text-transform: uppercase; color: var(--gold-l); text-shadow: 0 1px 1px #000; }
.lb-mapinfo em { font: 600 13px var(--body); font-style: normal; color: var(--muted); }
.setup { display: flex; flex-direction: column; gap: 4px; max-width: 540px; margin: 0 auto 8px; text-align: left; }
.seat { display: grid; grid-template-columns: 14px 96px minmax(0, 1fr) 26px; align-items: center; gap: 10px; padding: 4px 8px; min-height: 34px;
  background: linear-gradient(90deg, rgba(46,39,28,0.8), rgba(16,13,9,0.35)); border: 1px solid rgba(232,192,90,0.16); }
.seat .sw, .st-row .sw { width: 13px; height: 13px; box-shadow: 0 0 0 1px #000, 0 0 0 2px rgba(232,192,90,0.3); }
.seat b { font: 800 15px var(--title); letter-spacing: 0.04em; text-shadow: 0 1px 1px #000; }
.seat .who { color: var(--muted); font-weight: 700; }
.diffs { display: inline-flex; gap: 3px; }
.diffs button { cursor: pointer; padding: 3px 10px; font: 700 12.5px var(--body); color: var(--muted); background: linear-gradient(#2c251b, #14100b);
  border: 1px solid #000; box-shadow: 0 0 0 1px #5a4624, inset 0 1px 0 rgba(255,230,160,0.08); }
.diffs button:hover { color: #fff; }
.diffs button.on { color: #fff; background: linear-gradient(#715622, #3a2a10); box-shadow: 0 0 0 1px var(--gold), 0 0 8px rgba(255,200,80,0.35); text-shadow: 0 1px 1px #000; }
.diffs.all em { align-self: center; margin-right: 4px; font: 700 12px var(--body); font-style: normal; color: var(--muted); }
.seat .rm { width: 24px; height: 24px; padding: 0; cursor: pointer; background: linear-gradient(#2c1a14, #120a08); border: 1px solid #000; box-shadow: 0 0 0 1px #6a2a20; color: #ff9a8a; font-size: 12px; }
.seat .rm:disabled { opacity: 0.3; cursor: default; }
.seat-tools { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-top: 6px; }
#ov-body .setup-note { color: var(--muted); font-size: 13.5px; max-width: 560px; margin: 8px auto 8px; }
.end-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 22px; text-align: left; margin: 0 auto 14px; max-width: 620px; }
.end-grid .ov-stats { margin: 0; max-width: none; }
.standings { display: flex; flex-direction: column; gap: 2px; }
.st-row { display: grid; grid-template-columns: 32px 13px auto minmax(0, 1fr) auto; align-items: center; gap: 7px; padding: 2px 6px; font-size: 14px;
  background: rgba(30,25,18,0.55); border: 1px solid rgba(232,192,90,0.1); }
.st-row.me { background: linear-gradient(90deg, rgba(232,192,90,0.22), rgba(232,192,90,0.05)); border-color: rgba(232,192,90,0.35); }
.st-place { color: var(--gold-l); font: 800 12px var(--title); }
.st-row b { text-shadow: 0 1px 1px #000; }
.st-row em { color: var(--muted); font-style: normal; font-size: 12px; }
.st-row > span:last-child { color: #e6dcc6; text-align: right; }

/* ---------------- vs Players: menu, join screens and the lobby ---------------- */
body:not(.online) .online-only { display: none !important; }
body.online #btn-pause, body.online #speed { display: none !important; }
.ov-box.lobby-box { width: min(980px, 96vw); padding-top: 28px; padding-bottom: 12px; }
.ov-box.lobby-box h1 { font-size: 36px; }
.ov-box.lobby-box .ov-sub { margin-bottom: 8px; }
.lb-seats .seat { min-height: 30px; padding: 2px 8px; }
.on-wrap { max-width: 660px; margin: 0 auto 10px; text-align: left; }
.on-wrap.narrow { max-width: 470px; }
.on-field { display: flex; flex-direction: column; gap: 3px; margin: 0 auto 12px; max-width: 300px; }
.on-field span, .lb-label { font: 800 11px var(--title); letter-spacing: 0.12em; text-transform: uppercase; color: var(--gold-l); text-shadow: 0 1px 1px #000; }
.on-input, .on-field input { width: 100%; min-width: 0; height: 30px; padding: 0 8px; font: 600 15px var(--body); color: #fff; background: rgba(0,0,0,0.5);
  border: 1px solid rgba(232,192,90,0.35); box-shadow: inset 0 1px 3px rgba(0,0,0,0.8); outline: none; }
.on-input:focus, .on-field input:focus { border-color: rgba(255,216,74,0.75); }
.on-field input:disabled { opacity: 0.6; }
.on-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.on-card { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 10px 14px 14px; text-align: center;
  background: linear-gradient(rgba(46,39,28,0.85), rgba(16,13,9,0.5)); border: 1px solid rgba(232,192,90,0.18); box-shadow: inset 0 0 18px rgba(0,0,0,0.5); }
.on-card h3 { margin: 0; font: 800 17px var(--title); letter-spacing: 0.08em; text-transform: uppercase; color: var(--gold-l); text-shadow: 0 1px 1px #000; }
#ov-body .on-card p { flex: 1; margin: 0; font-size: 13.5px; color: var(--muted); }
.ov-box .on-status { min-height: 20px; margin: 10px 0 4px; text-align: center; font: 700 14px var(--body); color: #e6dcc6; }
.ov-box .on-status.bad { color: #ff7a6a; }
.ov-box .on-status.good { color: #9dff7a; }
.ov-box .on-status.warn { color: #ffd84a; }
.ov-box .on-status .dim { color: var(--muted); font-weight: 600; }
#ov-body .on-text { font-size: 15.5px; text-align: center; }
#ov-body .on-note, #ov-body .ov-note { color: var(--muted); font-size: 13.5px; text-align: center; margin: 4px auto 12px; max-width: 520px; }
.spin { display: inline-block; width: 12px; height: 12px; margin-right: 7px; vertical-align: -1px; border: 2px solid rgba(255,231,166,0.25); border-top-color: var(--gold);
  border-radius: 50%; animation: spin 0.9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.dot { display: inline-block; width: 8px; height: 8px; margin-right: 6px; border-radius: 50%; background: #8f866f; box-shadow: 0 0 0 1px #000; vertical-align: 0; }
.dot.good { background: #7dff5a; box-shadow: 0 0 0 1px #000, 0 0 5px rgba(125,255,90,0.6); }
.dot.warn { background: #ffd84a; }
.dot.bad { background: #ff5a48; box-shadow: 0 0 0 1px #000, 0 0 5px rgba(255,90,72,0.6); }
.lobby { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); grid-template-areas: "seats side" "chat chat"; gap: 10px 16px; align-items: start; text-align: left; }
.lb-seats { grid-area: seats; } .lb-side { grid-area: side; } .lb-chat { grid-area: chat; }
.lb-seats { display: flex; flex-direction: column; gap: 3px; }
.lb-seat.me { border-color: rgba(232,192,90,0.45); background: linear-gradient(90deg, rgba(232,192,90,0.2), rgba(16,13,9,0.35)); }
.lb-who { display: flex; align-items: center; gap: 8px; min-width: 0; }
.lb-who .nm { font: 700 15px var(--body); color: #fff; letter-spacing: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lb-who em { font: 600 12px var(--body); font-style: normal; color: var(--muted); }
.lb-who.open, .lb-who.closed { color: var(--muted); font-style: italic; }
.lb-who.bot { color: #e6dcc6; }
.lb-tag { margin-left: auto; padding: 1px 6px; font: 800 10px/14px var(--body); letter-spacing: 0.06em; text-transform: uppercase; white-space: nowrap; color: var(--muted);
  border: 1px solid rgba(185,173,148,0.35); background: rgba(0,0,0,0.35); }
.lb-tag.good { color: #9dff7a; border-color: rgba(125,255,90,0.45); }
.lb-tag.warn { color: #ffd84a; border-color: rgba(255,216,74,0.45); }
.lb-tag.host { color: var(--gold-l); border-color: rgba(232,192,90,0.55); }
.lb-select { width: 100%; max-width: 220px; height: 26px; padding: 0 6px; cursor: pointer; font: 700 13.5px var(--body); color: #f2ead8;
  background: linear-gradient(#2c251b, #14100b); border: 1px solid #000; box-shadow: 0 0 0 1px #5a4624, inset 0 1px 0 rgba(255,230,160,0.08); }
.lb-select:focus { outline: none; box-shadow: 0 0 0 1px var(--gold), 0 0 8px rgba(255,200,80,0.35); }
.lb-select option { background: #14100b; color: #f2ead8; }
.seat .rm.armed { color: #fff; background: linear-gradient(#8a2a1a, #3a0e08); box-shadow: 0 0 0 1px #ff7a5a, 0 0 8px rgba(255,90,60,0.6); }
.lb-side { display: flex; flex-direction: column; gap: 10px; }
.lb-invite { display: flex; flex-direction: column; gap: 4px; padding: 8px 10px; background: rgba(16,13,9,0.55); border: 1px solid rgba(232,192,90,0.16); }
.lb-linkrow { display: flex; gap: 6px; }
.lb-linkrow .on-input { height: 26px; font-size: 12.5px; color: #e6dcc6; }
.lb-room { font-size: 13px; color: var(--muted); }
.lb-room b { font: 800 15px var(--title); letter-spacing: 0.14em; color: #fff; }
.lb-btn { flex: none; height: 26px; padding: 0 12px; cursor: pointer; font: 700 11.5px/1 var(--title); letter-spacing: 0.06em; color: var(--gold-l); background: none;
  border-style: solid; border-color: transparent; border-width: 5px 9px; border-image: url(assets/ui/btn_wide.png?v=99dfd38af943) 22 34 fill / 5px 9px stretch; text-shadow: 0 1px 1px #000; }
.lb-btn:hover { border-image-source: url(assets/ui/btn_wide_hover.png?v=99dfd38af943); color: #fff; }
.lb-net { min-height: 18px; font-size: 13px; color: #e6dcc6; }
.lb-opt { display: flex; gap: 10px; align-items: flex-start; font-size: 13px; color: var(--muted); }
.lb-opt b { color: #ffd84a; }
.lb-toggle { flex: none; min-width: 44px; padding: 3px 8px; cursor: pointer; font: 800 12px var(--body); text-align: center; color: var(--muted); background: linear-gradient(#2c251b, #14100b);
  border: 1px solid #000; box-shadow: 0 0 0 1px #5a4624; }
.lb-toggle.on { color: #fff; background: linear-gradient(#715622, #3a2a10); box-shadow: 0 0 0 1px var(--gold), 0 0 8px rgba(255,200,80,0.35); }
/* the joiner's read-only view of the option: plain text, nothing to press */
.lb-flag { flex: none; min-width: 30px; padding: 2px 0; font: 800 12px var(--body); letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.lb-flag.on { color: #9dff7a; }
#ov-body .lb-rules { margin: 0; font-size: 12.5px; color: var(--muted); }
.lb-log { height: 84px; overflow-y: auto; padding: 4px 8px; font: 600 13.5px/1.35 var(--body); color: #fff; background: rgba(0,0,0,0.5);
  border: 1px solid rgba(232,192,90,0.2); box-shadow: inset 0 1px 6px rgba(0,0,0,0.8); overflow-wrap: anywhere; }
.lb-log .sys { font-style: italic; font-weight: 600; opacity: 0.9; }
.lb-say { display: flex; gap: 6px; margin-top: 6px; }
.lb-foot { display: flex; align-self: stretch; align-items: center; justify-content: space-between; gap: 12px; margin: 6px 0 8px; text-align: left; }
.lb-foot .on-status { flex: 1; margin: 0; text-align: left; }
#ov-quit.armed { color: #ffb08a; text-shadow: 0 0 8px rgba(255,120,60,0.9), 0 1px 1px #000; }
/* the game's top bar online: ping and players connected, where pause and speed are offline */
.tb-net { display: inline-flex; align-items: center; margin-left: 8px; font: 700 12px var(--body); color: #e6dcc6; white-space: nowrap; text-shadow: 0 1px 1px #000; }
.tb-net span { color: var(--muted); margin-left: 4px; }
#net-banner { position: absolute; left: 50%; top: 58px; z-index: 5; display: none; flex-direction: column; align-items: center; gap: 1px; padding: 2px 16px; transform: translateX(-50%);
  border-style: solid; border-color: transparent; border-width: 12px; border-image: url(assets/ui/tooltip.png?v=99dfd38af943) 36 fill / 18px stretch;
  filter: drop-shadow(0 4px 10px rgba(0,0,0,0.8)); pointer-events: none; animation: banner 1.2s ease-in-out infinite alternate; }
#net-banner.show { display: flex; }
#net-banner b { font: 800 15px var(--title); letter-spacing: 0.08em; color: #ffd84a; text-shadow: 0 1px 1px #000; }
#net-banner span { font: 700 13px var(--body); color: #e6dcc6; }
@keyframes banner { from { opacity: 0.75; } to { opacity: 1; } }

/* ---------------- smaller screens ---------------- */
@media (max-width: 1180px) {
  :root { --con-h: 190px; --pw: 104px; --btn: 40px; }
  #console { grid-template-columns: minmax(170px, 220px) auto minmax(0, 1fr) auto; gap: 8px; padding: 28px 24px 8px 24px; }
  .tb-res { gap: 10px; }
  .tb-btn { padding: 0 8px; }
  .tb-speed button { min-width: 32px; }
  .tb-plaque { width: 224px; height: 62px; }
  .tb-title { left: 44px; right: 44px; top: 7px; height: 37px; }
  .tb-title b { font-size: 13px; }
  .tb-title small { font-size: 10px; }
  #info .stats { grid-template-columns: repeat(auto-fill, minmax(124px, 1fr)); font-size: 13px; }
}
@media (max-width: 1140px) {
  body.ltw .tb-plaque { display: none; }   /* the Chat button needs the room; the scoreboard has the clock */
}
@media (max-width: 900px) {
  :root { --top-h: 36px; --con-h: 168px; --pw: 84px; --btn: 36px; --gap: 3px; }
  #topbar { padding: 0 54px 2px; }
  #topbar::before { height: 50px; border-width: 0 60px; border-image-width: 0 60px; }
  .tb-plaque { display: none; }
  .tb-btn, .tb-speed button { padding: 0 6px; font-size: 11px; }
  .tb-speed button { min-width: 30px; }
  .tb-res { gap: 8px; }
  .res { font-size: 13px; gap: 3px; }
  .res-sub { display: none; }
  .ico { width: 20px; height: 20px; }
  #console { grid-template-columns: auto minmax(0, 1fr) auto; gap: 6px; padding: 26px 8px 6px; }
  #console::before, #console::after { width: 64px; height: 64px; }
  #mm-panel { display: none; }
  .panel { border-width: 14px; border-image-width: 26px; }
  #cmd-panel { border-width: 10px; border-image-width: 20px; }
  #info .stats { grid-template-columns: 1fr 1fr; font-size: 12px; gap: 0 10px; }
  #info h2 { font-size: 16px; }
  #info .lore { display: none; }
  #cmd-tabs { width: 60px; }
  .cmd-tab { font-size: 10px; }
  .end-grid { grid-template-columns: 1fr; }
  .on-cards { grid-template-columns: 1fr; }
  /* a map's screen: the picture on top, as large as the height lets the rest show under it */
  .map-ways { flex-direction: column; gap: 10px; }
  .map-pic.big { width: min(100%, max(300px, calc(2 * (100vh - var(--crest-room)) - 1000px))); width: min(100%, max(300px, calc(2 * (100dvh - var(--crest-room)) - 1000px))); }
  .map-side { width: 100%; max-width: 560px; }
  #ov-body .map-about, #ov-body .map-side p { text-align: center; }
  .lobby { grid-template-columns: 1fr; grid-template-areas: "seats" "side" "chat"; }
  .ov-box h1 { font-size: 34px; }
  .a-title { font-size: 30px; }
  .a-sub { font-size: 16px; }
}
/* laptop heights (a 1366 x 768 screen leaves about 650 px, 1280 x 800 about 700): a smaller crest and tighter dialogs,
   so a dialog scrolls less, or not at all */
@media (max-height: 860px) {
  #overlay { --crest-room: 80px; }
  .ov-crest { width: 170px; height: 132px; top: -114px; }
  .ov-box, .ov-box.lobby-box { padding-top: 24px; padding-bottom: 8px; }
  .ov-box h1, .ov-box.lobby-box h1 { font-size: 34px; }
  .ov-sub, .ov-box.lobby-box .ov-sub { margin-bottom: 8px; }
  .ov-sub::after { margin-top: 5px; }
  #ov-foot .wc-btn:not(.small) { height: 40px; }
  #ov-foot > .ov-actions { margin: 6px 0 8px; }
  #ov-body p { margin: 6px 0 8px; }
  .seat { min-height: 30px; padding: 2px 8px; }
  .lb-seats .seat { min-height: 28px; }
  .lb-log { height: 64px; }
  .modes { gap: 6px; margin-bottom: 10px; }
  .mode { padding: 4px 14px 6px; }
}
@media (max-height: 860px) and (min-width: 901px) {
  /* the lobby chat moves up beside the seats, under the invite and the option, so the whole lobby fits */
  .lobby { grid-template-areas: "seats side" "seats chat"; }
  #ov-body .lb-rules { display: none; }
}
/* a short computer window: the maps in one row of four, each name on one line with the players under it, so the four
   captions match */
@media (max-height: 700px) and (min-width: 1000px) {
  .ov-box.picker { width: min(1180px, 96vw); }
  .maps { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .map-cap { flex-direction: column; align-items: flex-start; flex-wrap: nowrap; gap: 1px; }
  .map-cap b { font-size: clamp(11.5px, 1.1vw, 15px); letter-spacing: 0.06em; white-space: nowrap; }
}
/* a short narrow window (half a laptop's screen): a map's picture stays beside its ways to play, as on a phone on its
   side, where the picture on top would push the second way to play out of view */
@media (min-width: 601px) and (max-width: 900px) and (min-height: 501px) and (max-height: 760px) {
  .map-ways { flex-direction: row; gap: 14px; }
  .map-pic.big { width: 46%; }
  .map-side { width: auto; max-width: none; gap: 8px; }
  #ov-body .map-about, #ov-body .map-side p { text-align: left; }
}
@media (min-width: 601px) and (max-width: 900px) and (min-height: 501px) and (max-height: 580px) {
  #ov-body .map-about { display: none; }   /* the buttons say what each way to play is */
}
/* ---------------- phones (and other narrow windows), upright: a compact top bar and a console under the battlefield,
   the command card beside the info panel, Line Tower Wars' tabs in one row above them; the minimap and the portrait
   go (the minimap opens over the view from its button), the safe areas around a notch and the home bar are kept clear
   (a small phone on its side, under 501 px tall, takes the landscape layout below instead) */
@media (max-width: 600px) and (min-height: 501px) {
  :root { --top-h: 40px; --pw: 72px; --btn: 44px; --gap: 3px; --tb: 40px; }
  #app { grid-template-rows: calc(var(--top-h) + env(safe-area-inset-top)) minmax(0, 1fr) auto; }
  #topbar { height: auto; padding: env(safe-area-inset-top) max(6px, env(safe-area-inset-right)) 2px max(6px, env(safe-area-inset-left)); gap: 6px; }
  #topbar::before { top: env(safe-area-inset-top); border-width: 0; border-image-width: 0; }
  /* the bar fits a 360 px phone with every resource (where five digits of gold would not fit, src/client/hud.js shortens
     them as it does income, and where even that does not fit it makes the bar .tight): finger-high buttons, Chat as an
     icon */
  .tb-left { gap: 3px; }
  .tb-btn, .tb-speed button { height: 34px; padding: 0 5px; font-size: 11px; letter-spacing: 0.04em; }
  #btn-chat { min-width: 40px; padding: 0 1px; }
  #btn-chat span { display: none; }
  #btn-chat svg { display: block; }
  .tb-res { gap: 6px; }
  .res { font-size: 12.5px; gap: 2px; }
  .res b { min-width: 0; }
  .ico { width: 16px; height: 16px; }
  .tb-res.tight { gap: 3px; }
  .tb-res.tight .ico { width: 14px; height: 14px; }
  #console { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "tabs tabs" "info cmd"; gap: 4px 6px; align-items: stretch;
    padding: 22px max(6px, env(safe-area-inset-right)) calc(6px + env(safe-area-inset-bottom)) max(6px, env(safe-area-inset-left)); }
  #console::before, #console::after { width: 44px; height: 44px; }
  #mm-panel, #portrait-frame { display: none; }
  body:not(.ltw) #console { grid-template-areas: "info cmd"; }
  #info-panel { grid-area: info; }
  #cmd-panel { grid-area: cmd; justify-self: end; }
  .panel { border-width: 12px; border-image-width: 22px; }
  #info-panel { padding: 0 2px; }
  /* the console is as tall as the card (and the tabs) whatever the info panel shows: the panel fits its content to that
     (UI.fitInfo), so the battlefield above never moves; opened, it takes the room its content needs */
  #info { contain: size; }
  body.info-open #info { contain: none; }
  #info h2, #info.fit1 h2, #info.fit2 h2 { font-size: 15px; line-height: 1.12; white-space: normal; }   /* a long name takes two lines */
  #info .tier { font-size: 10px; margin-bottom: 3px; }
  #info .stats, #info.fit1 .stats { grid-template-columns: 1fr; font-size: 12px; gap: 0; }
  #info .tags, #info .lore { display: none; }
  /* Line Tower Wars: the tabs across the console, the card in its own frame */
  body.ltw #cmd-panel { display: contents; }
  body.ltw #cmd-tabs { grid-area: tabs; flex-direction: row; width: auto; height: 36px; gap: 2px; }
  .cmd-tab { font-size: 10.5px; padding: 0 1px; border-width: 5px 6px; border-image-width: 5px 6px; }
  body.ltw #ltw-commands { grid-area: cmd; justify-self: end; align-self: center; box-sizing: content-box; padding: 2px;
    border-style: solid; border-color: transparent; border-width: 10px; border-image: url(assets/ui/frame_gold.png?v=99dfd38af943) 64 / 20px round;
    background: linear-gradient(#0f0d0b, #070605) padding-box; filter: drop-shadow(0 3px 4px rgba(0,0,0,0.7)); }
  #ltw-commands.tech { width: calc(5 * var(--tb) + 4 * var(--gap)); }
  #wave-timer { font-size: 12px; min-width: 0; right: 6px; top: 6px; }
  #tooltip { max-width: calc(100vw - 16px); font-size: 13px; }
  #msgs { left: 10px; bottom: 8px; max-width: 72%; font-size: 12px; }
  #msgs div:nth-last-child(n+5) { display: none; }
  #error { bottom: 150px; padding: 0 12px; font-size: 16px; }   /* a refusal: above the map buttons and the messages */
  #hint { font-size: 12px; max-width: calc(100% - 70px); bottom: 6px; }
  #msgs.hinted { bottom: 62px; }   /* over a hint of two lines */
  #side { right: 6px; top: 6px; }
  #board { min-width: 170px; font-size: 12px; }
  #chat { top: 6px; bottom: auto; left: 6px !important; right: 6px; width: auto; }
  #chat input { font-size: 16px; }   /* 16 px or more: a phone does not zoom in to type */
  .tb-net { margin-left: 2px; font-size: 11px; }
  .tb-net .dot { margin-right: 4px; }
  .tb-net span { display: none; }   /* the ping alone, where the players connected would push the resources off */
  /* vs Computer setup: a computer's difficulties on a row of their own under its colour */
  .setup .seat[data-i] { grid-template-columns: 14px minmax(0, 1fr) 34px; grid-template-areas: "sw nm rm" "df df df"; row-gap: 5px; padding: 5px 8px; }
  .setup .seat[data-i] .sw { grid-area: sw; } .setup .seat[data-i] b { grid-area: nm; } .setup .seat[data-i] .rm { grid-area: rm; justify-self: end; }
  .setup .seat[data-i] .diffs { grid-area: df; display: grid; grid-template-columns: repeat(4, 1fr); }
  .seat-tools { flex-wrap: wrap; justify-content: center; }
  #overlay { --crest-room: 88px; }
  .ov-crest { width: 170px; height: 132px; top: -112px; }
  .ov-box { padding: 30px 8px 12px; border-width: 24px; border-image-width: 44px; }
  .a-title { font-size: 22px; }
  .a-sub { font-size: 13px; }
  .a-rule { height: 10px; }
  #announce { top: 64px; }   /* under the level timer and the folded scoreboard */
  /* vs Players lobby: a player's name gets the line under the colour (where the tag and the kick button stay), and the
     colour column narrows so a seat's choice reads in full */
  .lb-seats .seat { grid-template-columns: 14px 70px minmax(0, 1fr) auto; column-gap: 8px; }
  .lb-seats .seat > b { font-size: 13px; }
  .lb-seat.human { grid-template-columns: 14px 70px minmax(0, 1fr) auto auto; grid-template-areas: "sw col you tag rm" "sw nm nm nm rm"; row-gap: 1px; padding: 3px 8px; }
  .lb-seat.human > .sw { grid-area: sw; }
  .lb-seat.human > b { grid-area: col; }
  .lb-seat.human .lb-who { display: contents; }
  .lb-seat.human .nm { grid-area: nm; min-width: 0; }
  .lb-seat.human .lb-who em { grid-area: you; }
  .lb-seat.human .lb-tag { grid-area: tag; margin-left: 0; }
  .lb-seat.human > :last-child { grid-area: rm; }
  .ov-box.map-box h1 { font-size: 27px; letter-spacing: 0.04em; }   /* a map's or a mode's name on one line */
  /* the map picker: the playable maps across the dialog, the locked ones two to a row under them */
  .maps { gap: 8px; margin-bottom: 10px; }
  .map-card:not(.locked) { grid-column: span 2; }
  .map-card.locked { padding: 5px 5px 4px; }
  .map-card.locked .map-pic { border-width: 9px; border-image-width: 18px; }
  .map-card.locked .map-pic img { aspect-ratio: 4 / 3; }   /* the side bands give way to the map (the middle square) */
  .map-card.locked .map-cap { padding: 0 2px; }
  .map-card.locked .map-cap b { font-size: 11.5px; letter-spacing: 0.04em; }
  .map-card.locked .map-cap em { font-size: 11.5px; white-space: normal; }
  .map-lock { top: -4.5px; padding: 0 6px; font-size: 9.5px; letter-spacing: 0.08em; border-width: 4px; border-image-width: 8px; }
  .map-pic.thumb { width: 108px; }
}

/* ---------------- touch and small screens ---------------- */
/* the map buttons over the battlefield (zoom, the reset or the lane jumps, the minimap), where the minimap's own + and -
   are gone or too small for a finger; the same query as compact() in src/client/touch.js. They make a block at the foot
   of the view in two columns (the minimap's under the jumps; a phone on its side has two rows, below), and the scoreboard
   and the income list (#side) end above them, the list beside the board rather than under it: what does not fit scrolls */
#view-tools { position: absolute; right: 8px; bottom: 8px; z-index: 4; display: none; grid-template-columns: repeat(2, 40px); gap: 6px; }
#btn-speed, #rotate-hint { display: none; }
@media (max-width: 900px), (max-height: 500px), (pointer: coarse) {
  #view-tools { display: grid; }
  #vt-map { grid-column: 2; }
  #side { bottom: 154px; flex-direction: row-reverse; flex-wrap: wrap; align-items: flex-start; align-content: flex-start; }
  #board, #income-list { max-height: 100%; overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; scrollbar-width: thin; scrollbar-color: #6a5228 transparent; }
  #view-tools button { width: 40px; height: 40px; padding: 0; cursor: pointer; border-radius: 50%; font: 900 22px/38px var(--title); color: var(--gold-l); text-shadow: 0 1px 1px #000;
    background: radial-gradient(circle at 50% 35%, #3e3422, #120e08 75%); border: 1px solid #000; box-shadow: 0 0 0 1.5px #a07a2c, 0 2px 4px rgba(0,0,0,0.85); opacity: 0.92; }
  #view-tools button:active:not(:disabled) { transform: translateY(1px); color: #fff; }
  #view-tools button:disabled { opacity: 0.4; }
  #view-tools button[aria-pressed="true"] { color: #fff; box-shadow: 0 0 0 1.5px var(--gold), 0 0 10px rgba(255,200,80,0.55); }
  #view-tools svg { width: 20px; height: 20px; }
}
/* the minimap's button only where the console has no minimap: it opens over the view */
@media (min-width: 901px) and (min-height: 501px) { #vt-map { display: none; } }
@media (max-width: 900px), (max-height: 500px) {
  body.mm-open #mm-panel { display: flex; position: fixed; z-index: 7; left: calc(8px + env(safe-area-inset-left)); top: calc(var(--top-h) + env(safe-area-inset-top) + 8px);
    width: min(210px, 46vw); height: 150px; border-width: 18px; border-image-width: 30px; }
  body.mm-open:not(.ltw) #mm-panel { top: calc(var(--top-h) + env(safe-area-inset-top) + 72px); }   /* under Classic's level timer */
  #mm-zoom { display: none; }
}
/* fingers: no text selection or callouts in the game (inputs keep theirs), and controls a finger can hit */
@media (hover: none) and (pointer: coarse) {
  #app { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
  input, .lb-log { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }
  #mm-zoom { display: none; }
  .diffs button { padding: 8px 11px; }
  .seat .rm { width: 34px; height: 34px; }
  .lb-select { height: 34px; }
  .lb-btn, .lb-toggle { min-height: 32px; }
  .on-input, .on-field input { height: 38px; font-size: 16px; }
  .lb-linkrow .on-input { height: 32px; font-size: 16px; }
  .bd-title { padding: 6px 3px 8px; margin-top: -5px; }   /* the fold toggle */
  .bd-row { min-height: 24px; }
}
.touch-keys { display: none; }
/* a touch screen's menus show what fingers do, not the keys and the mouse */
@media (hover: none) and (pointer: coarse) { .ov-keys .touch-keys { display: list-item; } .ov-keys .mouse-keys { display: none; } }
/* tablets: the desktop console, with buttons for a finger */
@media (pointer: coarse) and (min-width: 601px) and (min-height: 501px) {
  :root { --btn: 48px; --con-h: 222px; }
  #cmd-tabs { width: 84px; }
  .cmd-tab { font-size: 12px; }
  .tb-btn, .tb-speed button { height: 30px; }
}
/* one speed button that steps 1x, 2x, 3x where the three would not fit; Menu pauses as Pause does */
@media (max-width: 600px), (max-height: 500px) {
  #speed, #btn-pause { display: none; }
  #btn-speed { display: inline-block; min-width: 40px; }
  body.online #btn-speed { display: none !important; }
  /* the info panel opens over the view from a tap (the console keeps its size) */
  #info-panel { cursor: pointer; }
  #info-panel::before { content: ''; position: absolute; z-index: 2; right: -6px; top: -6px; border: 5px solid transparent; border-bottom: 6px solid var(--gold-l); border-top: 0; opacity: 0.8; }
  body.info-open #info-panel { position: absolute; z-index: 8; grid-area: auto; left: max(6px, env(safe-area-inset-left)); right: max(6px, env(safe-area-inset-right)); bottom: calc(100% + 6px); max-height: min(60vh, 330px); }
  body.info-open #info-panel::before { border-bottom: 0; border-top: 6px solid var(--gold-l); }
  body.info-open #info .tags, body.info-open #info .lore { display: flex; }
  body.info-open #info .stats { grid-template-columns: 1fr 1fr; gap: 0 16px; }
  /* too small for the most compact layout: the lines that fit whole, no scrollbar (a tap shows the rest) */
  #info.fit3 { overflow: hidden; }
  #info .cut { display: none !important; }
  #chat.open ~ #side { top: 54px; }   /* the scoreboard steps down under the chat line */
  #income-list .idle { display: none; }   /* the empty slots of the map's income list */
}
/* where the unfolded scoreboard leaves no room beside it, its Income column stands in for the income list */
@media (max-width: 600px), (max-height: 500px) and (max-width: 640px) {
  #board:not(.folded) + #income-list { display: none; }
}
/* turn the phone: a hint across the foot of an upright phone's battlefield (what sits there steps up over it), clear
   of the level timer and the scoreboard; its ✕ puts it away for good, the rest of it lets taps through to the map */
@media (orientation: portrait) and (max-width: 600px) and (pointer: coarse) {
  body:not(.rotate-ok) #rotate-hint { position: absolute; left: 4px; right: 4px; bottom: 4px; z-index: 6; display: flex; align-items: center; justify-content: center; gap: 6px; padding: 0 0 0 8px;
    pointer-events: none; font: 700 13px/1.25 var(--body); color: var(--gold-l); text-shadow: 0 1px 1px #000;
    border-style: solid; border-color: transparent; border-width: 8px; border-image: url(assets/ui/tooltip.png?v=99dfd38af943) 36 fill / 16px stretch; filter: drop-shadow(0 3px 6px rgba(0,0,0,0.8)); }
  #rotate-hint span::before { content: ''; display: inline-block; width: 11px; height: 17px; margin-right: 8px; vertical-align: -3px; border: 2px solid var(--gold-l); border-radius: 3px; transform: rotate(-90deg); }
  #rotate-hint button { flex: none; width: 40px; height: 40px; padding: 0; cursor: pointer; pointer-events: auto; font: 800 15px var(--body); color: var(--gold-l); background: none; border: 0; }
  body:not(.rotate-ok) #view-tools, body:not(.rotate-ok) #msgs { bottom: 64px; }
  body:not(.rotate-ok) #error { bottom: 206px; }
  body:not(.rotate-ok) #msgs.hinted { bottom: 118px; }
  body:not(.rotate-ok) #hint { bottom: 62px; }
  body:not(.rotate-ok) #side { bottom: 210px; }
}

/* ---------------- phones on their side (the recommended way): the battlefield on the left, the console as a column on
   the right with the info panel over the Line Tower Wars tabs and the command card; the top bar stays a thin strip */
@media (max-height: 500px) and (orientation: landscape) {
  :root { --top-h: 34px; --btn: 44px; --gap: 3px; --tb: 40px; }
  #app { grid-template-rows: var(--top-h) minmax(0, 1fr); grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "top top" "stage console"; }
  #topbar { grid-area: top; height: var(--top-h); padding: 0 max(46px, env(safe-area-inset-right)) 1px max(46px, env(safe-area-inset-left)); gap: 6px; }
  #topbar::before { height: 44px; border-width: 0 48px; border-image-width: 0 48px; }
  .tb-plaque { display: none; }
  .tb-btn, .tb-speed button { height: 30px; padding: 0 7px; font-size: 11px; }
  .tb-res { gap: 10px; }
  .res { font-size: 13px; gap: 3px; }
  .res-sub { display: none; }
  .ico { width: 18px; height: 18px; }
  #stage { grid-area: stage; margin-left: env(safe-area-inset-left); }
  #console { grid-area: console; display: flex; flex-direction: column; gap: 6px; min-height: 0; width: calc(4 * var(--btn) + 3 * var(--gap) + 44px + env(safe-area-inset-right));
    padding: 12px max(8px, env(safe-area-inset-right)) calc(6px + env(safe-area-inset-bottom)) 10px; background-size: auto 360px; background-repeat: repeat;
    box-shadow: -6px 0 14px rgba(0,0,0,0.75), inset 3px 0 0 #a07a2c, inset 4px 0 0 #2a1d0a; }
  #console::before { width: 40px; height: 40px; left: -6px; top: -6px; }
  #console::after { display: none; }
  body.ltw #console { width: calc(5 * var(--tb) + 4 * var(--gap) + 44px + env(safe-area-inset-right)); }
  #mm-panel, #portrait-frame { display: none; }
  .panel { border-width: 12px; border-image-width: 22px; }
  #info-panel { flex: 1 1 auto; min-height: 44px; padding: 0 2px; }
  #info h2, #info.fit1 h2, #info.fit2 h2 { font-size: 15px; }
  #info .tier { font-size: 10px; margin-bottom: 2px; }
  #info .stats, #info.fit1 .stats { grid-template-columns: 1fr; font-size: 12px; gap: 0; }
  #info .tags, #info .lore { display: none; }
  #cmd-panel { flex: none; align-self: center; margin-top: auto; border-width: 10px; border-image-width: 20px; }
  body.ltw #cmd-panel { flex-direction: column; gap: 4px; }
  #cmd-tabs { display: grid; grid-template-columns: repeat(3, 1fr); width: auto; gap: 2px; }
  .cmd-tab { height: 30px; font-size: 10.5px; padding: 0 1px; border-width: 5px 6px; border-image-width: 5px 6px; }
  #ltw-commands { margin: 0 auto; }
  #ltw-commands.tech { width: calc(5 * var(--tb) + 4 * var(--gap)); }
  body.info-open #info-panel { left: auto; right: calc(100% + 6px); top: 6px; bottom: auto; width: min(380px, 62vw); max-height: calc(100% - 12px); }
  #wave-timer { font-size: 12px; min-width: 0; right: 6px; top: 6px; border-width: 10px; }
  #msgs { left: 10px; bottom: 8px; max-width: 60%; font-size: 12px; }
  #msgs div:nth-last-child(n+5) { display: none; }
  #side { right: 6px; top: 6px; bottom: 108px; }
  #board { min-width: 180px; font-size: 12px; }
  #view-tools { grid-template-columns: none; grid-template-rows: repeat(2, 40px); grid-auto-flow: column; }   /* low, clear of the scoreboard */
  #vt-map { grid-row: 2; grid-column: auto; }
  #chat { top: 6px; bottom: auto; left: 6px !important; width: min(460px, calc(100% - 60px)); }
  #chat input { font-size: 16px; }
  #announce { top: 64px; }   /* under the level timer and the folded scoreboard */
  .a-title { font-size: 24px; }
  .a-sub { font-size: 13px; }
  .a-rule { height: 10px; }
  /* dialogs: a small crest, a tight frame, the modes side by side; the body scrolls when it must */
  #overlay { --crest-room: 30px; padding: calc(var(--crest-room) + 2px) env(safe-area-inset-right) 4px env(safe-area-inset-left); }
  .ov-crest { width: 80px; height: 62px; top: -46px; }
  .ov-box, .ov-box.lobby-box { width: min(780px, 96vw); max-height: calc(100vh - var(--crest-room) - 8px); max-height: calc(100dvh - var(--crest-room) - 8px);
    padding: 12px 14px 4px; border-width: 22px; border-image-width: 40px; }
  .ov-box.wide { width: min(780px, 96vw); }
  .ov-box h1, .ov-box.lobby-box h1 { font-size: 24px; }
  .ov-sub, .ov-box.lobby-box .ov-sub { font-size: 11px; margin: 0 0 6px; }
  .ov-sub::after { margin-top: 4px; height: 10px; }
  #ov-body p { margin: 4px 0 6px; font-size: 14px; }
  .ov-keys { font-size: 13px; margin-bottom: 8px; }
  #ov-foot { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 4px 10px; margin: 4px 0 2px; }   /* the dialog's buttons in one row */
  #ov-foot .wc-btn:not(.small) { height: 36px; min-width: 180px; font-size: 15px; }
  #ov-foot > .ov-actions { margin: 0; flex-wrap: nowrap; }
  #ov-foot > .lb-foot { flex: 1 1 100%; margin: 0; }
  .modes { flex-direction: row; max-width: none; gap: 8px; margin: 2px 0 8px; }
  .mode { flex: 1 1 0; justify-content: flex-start; padding: 4px 8px 6px; }
  .mode b { font-size: 15px; }
  .mode span { font-size: 12.5px; }
  /* the map picker: one row that the finger swipes, two maps and a half in view (the next one shows at the edge) */
  .ov-box.picker { width: min(780px, 96vw); }
  .maps { display: flex; align-items: flex-start; gap: 10px; margin: 0 0 6px; padding: 3px 0 4px; overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory; touch-action: pan-x pan-y; scrollbar-width: thin; scrollbar-color: #6a5228 transparent; }
  .map-card { flex: 0 0 min(270px, 36vw); scroll-snap-align: start; padding: 6px 6px 5px; gap: 4px; }
  .map-pic { border-width: 10px; border-image-width: 20px; }
  .map-lock { top: -5px; }
  .map-cap b { font-size: 13.5px; }
  .map-cap em { font-size: 12px; }
  /* a map's screen: the picture beside its ways to play (the buttons say what each is; the map's own line gives way) */
  .map-ways { flex-direction: row; align-items: center; gap: 14px; margin-bottom: 6px; }
  .map-pic.big { width: 46%; }
  .map-side { flex: 1 1 0; min-width: 0; gap: 6px; }
  #ov-body .map-about { display: none; }
  #ov-body .map-side p { text-align: left; }
  .map-side .modes { flex-direction: column; gap: 6px; margin: 0; }
  .map-side .mode { flex: none; }
  .map-side .ov-keys { padding-left: 16px; }
  .map-pic.thumb { width: 88px; border-width: 6px; border-image-width: 12px; }
  .lb-map { gap: 10px; }
  .on-wrap .lb-map { margin-bottom: 6px; }
  .lb-mapinfo { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0 8px; }
  .lb-mapinfo .lb-label { flex-basis: 100%; }
  .lb-mapinfo b { font-size: 13px; }
  .lb-mapinfo em { font-size: 12px; }
  .end-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
  .lobby { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); grid-template-areas: "seats side" "seats chat"; }
  #ov-body .lb-rules { display: none; }
  .lb-log { height: 56px; }
  .on-cards { grid-template-columns: 1fr 1fr; gap: 8px; }
  .on-field { flex-direction: row; align-items: center; gap: 10px; max-width: 440px; margin-bottom: 6px; }
  .on-field span { flex: none; }
  .on-card { gap: 5px; padding: 6px 10px 8px; }
  .on-card h3 { font-size: 15px; }
  #ov-body .on-card p { font-size: 12.5px; line-height: 1.25; }
  .ov-box .on-status { min-height: 0; margin: 4px 0 0; }
}
/* a finger leaves a touch screen's :hover on the button it tapped last: no hover glow there, so a command button that
   was just pressed does not look selected */
@media (hover: none) {
  .cmd:hover { box-shadow: none; }
  .cmd:hover::after { background-image: url(assets/ui/button.png?v=99dfd38af943); }
  .cmd:hover canvas { filter: none; }
  .cmd.empty:hover::after { background-image: url(assets/ui/button_empty.png?v=99dfd38af943); }
  .cmd.active:hover::after { background-image: url(assets/ui/button_active.png?v=99dfd38af943); }
  .cmd.active:hover { box-shadow: 0 0 12px rgba(125,255,90,0.6); }
  .cmd.poor:hover canvas { filter: grayscale(0.85) brightness(0.5); }
  .cmd.locked:hover canvas, .cmd.out:hover canvas, .cmd.off:hover canvas { filter: grayscale(0.85) brightness(0.55); }
}

/* ===== The build phase (Line Tower Wars, src/client/hud.js): the timer window before the shrines open, at the top of
   the battlefield in the console's tooltip frame, as WC3 shows a map's timer. Appended by the build-phase work. ===== */
#prep-timer { position: absolute; left: 50%; top: 10px; z-index: 3; display: none; min-width: 230px; padding: 0 10px; transform: translateX(-50%);
  text-align: center; pointer-events: none; border-style: solid; border-color: transparent; border-width: 12px;
  border-image: url(assets/ui/tooltip.png?v=99dfd38af943) 36 fill / 18px stretch; }
#prep-timer.show { display: block; }
#prep-timer b { display: block; font: 800 14px var(--title); letter-spacing: 0.12em; text-transform: uppercase; color: var(--gold-l); text-shadow: 0 1px 1px #000; }
#prep-timer span { display: block; font: 700 13px var(--body); color: var(--text); text-shadow: 0 1px 1px #000; }
#prep-timer em { display: inline-block; min-width: 2.6em; font: 900 20px/1.1 var(--title); font-style: normal; color: #ffd84a; text-shadow: 0 1px 1px #000, 0 0 8px rgba(0,0,0,0.8); }
#prep-timer.soon em { color: #ff7a5a; animation: prep-soon 1s ease-in-out infinite; }
@keyframes prep-soon { 50% { transform: scale(1.12); } }
#board .bd-clock.prep { color: #ffd84a; }
body.prep #announce { top: max(11%, 78px); }   /* an announcement in the build phase shows under the timer */
/* a narrow window: the timer's middle moves left until it clears the scoreboard at the top right (248 px wide, 10 px
   from the edge, 8 px apart: 381 px with half the timer) */
#prep-timer { left: min(50%, calc(100% - 381px)); }
/* where the title plaque hangs into the battlefield (src/client/hud.js puts the phase in its line too), the timer hangs
   under it */
@media (min-width: 1141px) and (min-height: 501px) { #prep-timer { top: 28px; } body.prep #announce { top: max(11%, 100px); } }
@media (min-width: 1181px) and (min-height: 501px) { #prep-timer { top: 44px; } body.prep #announce { top: max(11%, 118px); } }
/* phones: upright the folded scoreboard holds the top right, so the timer takes the top left; the chat line, when open,
   comes first at the top */
@media (max-width: 600px) and (min-height: 501px) {
  #prep-timer { left: 6px; top: 6px; min-width: 0; padding: 0 6px; transform: none; border-width: 10px; border-image-width: 16px; }
  #prep-timer b { font-size: 12px; letter-spacing: 0.08em; }
  #prep-timer span { font-size: 12px; }
  #prep-timer em { font-size: 17px; }
  body.prep #announce { top: 104px; }   /* under the timer (6 to 61 px) and your lane's name plate, which goes under it (to 99) */
}
@media (max-height: 500px) and (orientation: landscape) {
  /* clear of the folded scoreboard (182 px, 6 px from the edge: 283 px with half the timer) */
  #prep-timer { left: min(50%, calc(100% - 283px)); top: 6px; min-width: 0; padding: 0 6px; border-width: 10px; border-image-width: 16px; }
  #prep-timer b { font-size: 12px; }
  #prep-timer span { font-size: 12px; }
  #prep-timer em { font-size: 17px; }
}
@media (max-width: 600px), (max-height: 500px) {
  #chat.open ~ #prep-timer { top: 54px; }
}

/* ===== The command card's buttons at any size: each button is a size container, so its hotkey, cost and counters are
   sized from the button itself (cqw: a percent of its width) and read the same on a 44 px phone button, a 50 px Tech
   button and an 88 px one on a large monitor. The hotkey and the cost sit on dark corner tabs, readable over any icon. ===== */
.cmd { container-type: size; }
.cmd, #info, #tooltip, .cmd-tab { font-variant-numeric: lining-nums; }   /* Alegreya's old-style figures read poorly small */
.cmd .hk { left: 2px; top: 2px; min-width: 1.15em; padding: 0.1em 0.2em 0.06em; text-align: center; font-size: clamp(12px, 24cqw, 19px); line-height: 1;
  background: linear-gradient(135deg, rgba(0,0,0,0.82), rgba(0,0,0,0.6)); border-radius: 0 0 4px 0; box-shadow: inset -1px -1px 0 rgba(255,204,0,0.28); }
.cmd .hk:empty { display: none; }   /* Esc: no letter */
.cmd .cost { right: 2px; bottom: 2px; padding: 0.08em 0.2em 0.02em; font-size: clamp(12px, 24cqw, 19px); line-height: 1.05; letter-spacing: 0.01em;
  background: linear-gradient(315deg, rgba(0,0,0,0.85), rgba(0,0,0,0.62)); border-radius: 4px 0 0 0; box-shadow: inset 1px 1px 0 rgba(255,227,154,0.22); }
.cmd .inc, .cmd .stk, .cmd .one { font-size: clamp(10px, 19cqw, 15px); line-height: 1; }
.cmd .inc { right: 3px; top: 3px; }
.cmd .stk { left: 3px; bottom: 3px; padding: 0.06em 0.18em 0; background: rgba(0,0,0,0.6); border-radius: 0 3px 0 0; }
.cmd .stk:empty { display: none; }
.cmd .one { left: 3px; bottom: 3px; transform: none; }   /* ×1 in the corner, clear of a long cost (50k) */
.cmd .one ~ .stk { bottom: calc(1em + 5px); }            /* and its stock over it */
@container (max-width: 50px) { .cmd .stk { bottom: calc(1.15 * clamp(12px, 24cqw, 19px) + 3px); } }   /* a small button: the stock over the cost */
.cmd .lum { bottom: calc(1.15 * clamp(12px, 24cqw, 19px) + 3px); right: 3px; font-size: clamp(10px, 19cqw, 15px); gap: 0.1em; }   /* over the cost's plate */
.cmd .lum .ico { width: 1.05em; height: 1.05em; }
.cmd .lock { font-size: clamp(11px, 22cqw, 17px); }
.cmd.locked .lum { display: none; }   /* a send not open yet gives the middle to its countdown (the tooltip keeps the lumber) */
@container (min-width: 48px) {       /* a computer's or a tablet's button (48 px or more): its counters 12 px or more */
  .cmd .inc, .cmd .stk, .cmd .one, .cmd .lum { font-size: clamp(12px, 19cqw, 15px); }
  .cmd .lock { font-size: clamp(12px, 22cqw, 17px); }
}
@container (min-width: 54px) {       /* a button of 54 px or more: everything 13 px or more */
  .cmd .hk, .cmd .cost { font-size: clamp(13px, 24cqw, 19px); }
  .cmd .inc, .cmd .stk, .cmd .one, .cmd .lum { font-size: clamp(13px, 19cqw, 15px); }
  .cmd .lock { font-size: clamp(13px, 22cqw, 17px); }
}
.cmd .own { font-size: clamp(12px, 24cqw, 19px); right: 4px; bottom: 2px; }
.cmd .rs { height: max(2px, 5cqh); }
#ltw-commands.tech .cmd .hk { left: 2px; top: 2px; font-size: clamp(11px, 25cqw, 17px); }
/* a button that can't be used now: greyed, with its reason in the tooltip (a send's countdown, a tower's tech in its corner) */
.cmd.off::before, .cmd.locked::before, .cmd.out::before { content: ''; position: absolute; inset: 2px; z-index: 1; pointer-events: none; background: rgba(10,6,4,0.25); }
.cmd.active canvas { filter: brightness(1.12) saturate(1.1); }
.cmd.active::before { content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none; box-shadow: inset 0 0 0 2px rgba(150,255,110,0.85), inset 0 0 14px rgba(125,255,90,0.45); }

/* ===== The responsive console (computers and tablets: 901 px wide and 501 tall or more). One unit, --u, scales the whole
   console with the window: 1 px at 1440 x 900, from the height (gentler above 900 px tall, so a large monitor gets more
   battlefield) unless the width is the tighter, 0.75 to 1.6 px. Everything in the console is a multiple of it, so the
   console keeps about a quarter of the window's height and its parts keep their proportions from a laptop to a large
   monitor: command buttons 56 px at 1280 x 800, 64 at 1440 x 900, 72 at 1920 x 1080, 88 at 2560 x 1440.
   The command card stands raised over the console's gold rail (as WC3's does); the minimap, the portrait and the info
   panel sit under it. The info panel stops at --info-max: on a wide window the space left goes to the stone either side
   of the portrait and the info panel, which keep to the middle, instead of an empty panel half the screen wide. ===== */
@media (min-width: 901px) and (min-height: 501px) {
  :root {
    --u: clamp(0.75px, min(100vh / 900, 0.375px + 100vh * 0.625 / 900, 100vw / 1440), 1.6px);
    --btn: calc(64 * var(--u));
    --gap: calc(4 * var(--u));
    --pw: calc(124 * var(--u));
    --card-fr: calc(10 * var(--u));     /* the card's frame and padding */
    --con-pt: calc(4 * var(--u)); --con-pb: calc(5 * var(--u));
    --con-h: calc(3 * var(--btn) + 2 * var(--gap) + 2 * var(--card-fr) + var(--con-pt) + var(--con-pb));
    --trim: calc(var(--con-h) * 0.1);   /* the gold rail across the console's top (console_bg.png's top 36 of 360 px) */
    --mm-w: calc(300 * var(--u));
    --info-max: calc(640 * var(--u));
    --tabs-w: max(92px, calc(108 * var(--u)));   /* room for "Super Shrine" at 13 px on a short window too */
  }
  #console { grid-template-columns: var(--mm-w) minmax(0, 1fr) auto minmax(0, var(--info-max)) minmax(0, 1fr) auto; column-gap: calc(8 * var(--u));
    padding: var(--con-pt) calc(26 * var(--u)) var(--con-pb); }
  #console::before, #console::after { width: calc(88 * var(--u)); height: calc(88 * var(--u)); top: calc(-4 * var(--u)); }
  #console::after { z-index: -1; }   /* the right corner runs on behind the raised card */
  .panel { border-width: calc(16 * var(--u)); border-image-width: calc(30 * var(--u)); }
  #mm-panel { grid-column: 1; margin-top: calc(var(--trim) - 2 * var(--u)); border-width: calc(20 * var(--u)); border-image-width: calc(34 * var(--u)); }
  #mm-zoom { left: calc(-18 * var(--u)); gap: calc(5 * var(--u)); }
  #mm-zoom button { width: calc(22 * var(--u)); height: calc(22 * var(--u)); font-size: calc(15 * var(--u)); line-height: calc(20 * var(--u)); }
  #mm-zoom svg { width: calc(12 * var(--u)); height: calc(12 * var(--u)); }
  #portrait-frame { grid-column: 3; margin-top: var(--trim); }
  #info-panel { grid-column: 4; margin-top: calc(var(--trim) - 2 * var(--u)); padding: calc(2 * var(--u)) calc(10 * var(--u)); }
  #cmd-panel { grid-column: 6; align-self: stretch; padding: calc(1 * var(--u)); border-width: calc(9 * var(--u)); border-image-width: calc(19 * var(--u)); }
  /* the info panel's type grows with the console */
  #info h2 { font-size: max(19px, calc(23 * var(--u))); margin-bottom: calc(2 * var(--u)); }
  #info .tier { font-size: max(11px, calc(12.5 * var(--u))); margin-bottom: calc(6 * var(--u)); }
  #info .stats { grid-template-columns: repeat(auto-fill, minmax(calc(158 * var(--u)), 1fr)); gap: calc(2 * var(--u)) calc(20 * var(--u)); font-size: max(14px, calc(16 * var(--u))); }
  #info .stats div { padding: calc(2 * var(--u)) 0; }
  #info .tags { margin-top: calc(8 * var(--u)); gap: calc(5 * var(--u)); }
  #info .tag { font-size: max(10.5px, calc(12 * var(--u))); padding: calc(2 * var(--u)) calc(8 * var(--u)); }
  #info .hp { height: max(13px, calc(16 * var(--u))); margin: calc(5 * var(--u)) 0 calc(7 * var(--u)); }
  #info .hp em { font-size: max(10px, calc(12 * var(--u))); line-height: max(13px, calc(16 * var(--u))); }
  #info .lore { margin-top: calc(8 * var(--u)); font-size: max(13px, calc(15 * var(--u))); }
  #info .swatch { width: calc(10 * var(--u)); height: calc(10 * var(--u)); }
  #info .queue { grid-template-columns: repeat(auto-fill, minmax(calc(80 * var(--u)), 1fr)); gap: calc(4 * var(--u)) calc(7 * var(--u)); }
  #info .queue .q { height: max(13px, calc(16 * var(--u))); }
  #info .queue .q em { font-size: max(10px, calc(12 * var(--u))); line-height: max(13px, calc(16 * var(--u))); }
  #info.fit1 h2, #info.fit2 h2 { font-size: max(17px, calc(20 * var(--u))); }
  #info.fit1 .stats, #info.fit2 .stats { font-size: max(13px, calc(14.5 * var(--u))); column-gap: calc(14 * var(--u)); }
  #info.fit1 .stats div, #info.fit2 .stats div { min-width: calc(118 * var(--u)); }
  #info.fit2 h2 { font-size: max(15px, calc(18 * var(--u))); }
  #info.fit2 .stats { font-size: max(12px, calc(13.5 * var(--u))); }
  /* tooltips */
  #tooltip { max-width: calc(380 * var(--u)); padding: calc(3 * var(--u)) calc(6 * var(--u)); font-size: max(14px, calc(15.5 * var(--u))); line-height: 1.38;
    border-width: calc(13 * var(--u)); border-image-width: calc(20 * var(--u)); }
  #tooltip .t-title { font-size: max(15px, calc(17.5 * var(--u))); }
  #tooltip .t-cost { margin: calc(3 * var(--u)) 0 calc(6 * var(--u)); padding-bottom: calc(6 * var(--u)); gap: calc(6 * var(--u)); }
  #tooltip .t-cost i { width: calc(18 * var(--u)); height: calc(18 * var(--u)); }
  #tooltip .t-note { font-size: max(13px, calc(14.5 * var(--u))); }
  /* Line Tower Wars: the tabs in a column beside the card, as tall as it; the Tech tab's 5 x 3 grid in the card's width */
  body.ltw #cmd-panel { gap: calc(5 * var(--u)); }
  #cmd-tabs { width: var(--tabs-w); gap: calc(3 * var(--u)); }
  .cmd-tab { padding: 0 calc(2 * var(--u)); font-size: max(11px, calc(13.5 * var(--u))); letter-spacing: 0.03em;
    border-width: calc(5 * var(--u)) calc(8 * var(--u)); border-image-width: calc(5 * var(--u)) calc(8 * var(--u)); }
  .cmd-tab .tab-n { font-size: max(10px, calc(12 * var(--u))); margin-left: calc(5 * var(--u)); }
  .cmd-tab.on::after { content: ''; position: absolute; right: calc(-9 * var(--u)); top: 50%; width: 0; height: 0; transform: translateY(-50%);
    border: calc(5 * var(--u)) solid transparent; border-left: calc(6 * var(--u)) solid var(--gold-l); border-right: 0; filter: drop-shadow(0 0 3px rgba(255,210,100,0.8)); }
  /* the hover glows grow with the buttons */
  .cmd.active, .cmd.active:hover { box-shadow: 0 0 calc(14 * var(--u)) rgba(125,255,90,0.65); }
}
/* the top bar, the level timer and the build-phase timer grow with the console above 1440 x 900 (to 1.3 times), so the
   HUD keeps one scale on a large monitor; narrower windows keep their own top bar (above) */
@media (min-width: 1181px) and (min-height: 501px) {
  :root { --tu: clamp(1px, var(--u), 1.3px); --top-h: calc(40 * var(--tu)); }
  #topbar { padding: 0 calc(78 * var(--tu)) calc(2 * var(--tu)); }
  #topbar::before { height: calc(56 * var(--tu)); border-width: 0 calc(75 * var(--tu)); border-image-width: 0 calc(75 * var(--tu)); }
  .tb-left { gap: calc(4 * var(--tu)); }
  .tb-btn, .tb-speed button { height: calc(26 * var(--tu)); padding: 0 calc(12 * var(--tu)); font-size: calc(12 * var(--tu)); line-height: calc(16 * var(--tu));
    border-width: calc(7 * var(--tu)) calc(10 * var(--tu)); border-image-width: calc(7 * var(--tu)) calc(10 * var(--tu)); }
  .tb-speed { margin-left: calc(6 * var(--tu)); }
  .tb-speed button { padding: 0 calc(3 * var(--tu)); min-width: calc(38 * var(--tu)); }
  .tb-plaque { width: calc(280 * var(--tu)); height: calc(78 * var(--tu)); }
  .tb-title { left: calc(56 * var(--tu)); right: calc(56 * var(--tu)); top: calc(9 * var(--tu)); height: calc(46 * var(--tu)); }
  .tb-title b { font-size: calc(15 * var(--tu)); }
  .tb-title small { font-size: calc(11 * var(--tu)); margin-top: calc(2 * var(--tu)); }
  .tb-res { gap: calc(16 * var(--tu)); }
  .res { font-size: calc(15 * var(--tu)); gap: calc(5 * var(--tu)); }
  .res b { min-width: calc(26 * var(--tu)); }
  .res-sub { font-size: calc(12 * var(--tu)); }
  .tb-res .ico { width: calc(24 * var(--tu)); height: calc(24 * var(--tu)); }
  .tb-net { font-size: calc(12 * var(--tu)); }
  #wave-timer { min-width: calc(150 * var(--tu)); padding: 0 calc(6 * var(--tu)); font-size: calc(14 * var(--tu)); border-width: calc(12 * var(--tu)); border-image-width: calc(18 * var(--tu)); }
  #wave-timer small { font-size: calc(12 * var(--tu)); }
  #prep-timer { top: calc(44 * var(--tu)); }
  body.prep #announce { top: max(11%, calc(118 * var(--tu))); }
}
/* vs Computer's top bar also has Chat: up to 1240 px wide its buttons stay as compact as a narrower window's, clear of
   the title plaque */
@media (min-width: 1181px) and (max-width: 1240px) and (min-height: 501px) {
  body.ltw .tb-btn { padding: 0 8px; }
  body.ltw .tb-speed button { min-width: 32px; }
}
/* a narrower computer window: a narrower minimap and tighter stone */
@media (min-width: 901px) and (max-width: 1180px) and (min-height: 501px) {
  :root { --mm-w: calc(250 * var(--u)); --tabs-w: max(84px, calc(104 * var(--u))); }
  .cmd-tab { letter-spacing: 0.01em; }
  #console { column-gap: calc(6 * var(--u)); padding-left: calc(20 * var(--u)); padding-right: calc(20 * var(--u)); }
}
/* tablets: the same console, with buttons at least a finger wide */
@media (pointer: coarse) and (min-width: 901px) and (min-height: 501px) {
  :root { --btn: max(48px, calc(64 * var(--u))); --tabs-w: max(92px, calc(108 * var(--u))); }
  .cmd-tab { font-size: max(12px, calc(13.5 * var(--u))); }
}
/* Classic's farthest view on a computer window wider than the map: the bars beside the map are the forest going on
   into the dark, not flat black (the map's own picture, blurred and darkened under a vignette; drawn once, under the
   battlefield's canvas) */
@media (min-width: 901px) and (min-height: 501px) {
  body:not(.ltw) #stage { background: #050604; }
  body:not(.ltw) #stage::before { content: ''; position: absolute; inset: -40px; pointer-events: none;
    background: url(assets/maps/classic.jpg?v=99dfd38af943) center / cover no-repeat; filter: blur(22px) brightness(0.32) saturate(0.85); }
  body:not(.ltw) #stage::after { content: ''; position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(ellipse 70% 90% at center, rgba(0,0,0,0) 40%, rgba(0,0,0,0.8) 100%); }
  body:not(.ltw) #view-wrap { z-index: 1; }   /* the map over them */
}

/* ===== judge's grafts on design C (from design A) ===== */
/* the tech building a button waits for sits in its top-right corner, clear of the cost (every layout) */
#ltw-commands .cmd canvas.req { left: auto; top: 3px; right: 3px; bottom: auto; width: 40%; height: 40%; }
/* three looks at a glance: usable (full colour, gold cost), too dear (dimmed, red cost on a red-ringed plate),
   greyed out (a missing tech, the build phase, a full queue: full grey, darker and hatched; the tooltip says why) */
.cmd.poor canvas { filter: grayscale(0.55) brightness(0.68); }
.cmd.poor .cost, .cmd.poor-lumber .lum { color: #ff6a58; box-shadow: inset 0 0 0 1px rgba(255,90,72,0.75); }
.cmd.locked canvas, .cmd.out canvas, .cmd.off canvas { filter: grayscale(1) brightness(0.55) contrast(0.95); }
.cmd.off:not(.owned)::before { background: repeating-linear-gradient(135deg, rgba(10,6,4,0.12) 0 6px, rgba(0,0,0,0.42) 6px 8px); }
.cmd .inc:empty { display: none; }
@media (min-width: 901px) and (min-height: 501px) {
  #ltw-commands.tech .cmd .hk { font-size: clamp(13px, 25cqw, 17px); }
  .cmd:not(.empty):not(.active):hover { box-shadow: 0 0 0 1px rgba(255,220,130,0.85), 0 0 calc(12 * var(--u)) rgba(255,205,90,0.6); }   /* not on an empty slot; an active one keeps its green */
  body:not(.ltw) #stage::before { transform: translateZ(0); }
}
/* the Line Tower Wars tabs: 13 px or more on a computer window, 12 on a narrow one */
@media (min-width: 1181px) and (min-height: 501px) { .cmd-tab { font-size: max(13px, calc(13.5 * var(--u))); } }
@media (min-width: 901px) and (max-width: 1180px) and (min-height: 501px) { .cmd-tab { font-size: max(12px, calc(13.5 * var(--u))); } }
