:root {
  --bg: #0e0d0b;
  --panel: #171512;
  --panel2: #201d18;
  --line: #352f28;
  --text: #e6dfd3;
  --dim: #998f82;
  --gold: #f0c674;
  --red: #ff6b6b;
  --green: #69d08f;
  --blue: #7fb4ff;
  --god: #b48cff;
  /* food is green everywhere (chips, cost dots, gauges); hp bars are red, so a food gauge never reads as health */
  --food: #9ccc65;
  --minerals: #7fb4ff;
  --watchH: 48px;   /* the Watcher strip over the board: every grid row list below counts it */
  --barH: 156px;    /* the control bar under the board: a fixed height, so the board is measured without feeding back
                       on the bar's content (every grid row list below counts it) */
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text);
  font: 13px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
button { font: inherit; color: inherit; }

/* the top bar across; under it the main column (the Watcher strip, the board, the control bar) and the right column */
#app { display: grid; height: 100vh; grid-template-columns: minmax(0, 1fr) 300px;
  grid-template-rows: 46px var(--watchH) minmax(0, 1fr) var(--barH);
  grid-template-areas: "top top" "watch right" "board right" "bar right"; }

/* ---------- top bar ---------- */
#topbar { grid-area: top; display: flex; align-items: center; gap: 7px; padding: 0 12px; min-width: 0;
  background: var(--panel); border-bottom: 1px solid var(--line); }
.brand { letter-spacing: 3px; font-size: 15px; margin-right: 6px; color: var(--dim); white-space: nowrap;
  text-decoration: none; }
a.brand:hover { filter: brightness(1.45); }   /* (a link to the main menu, online.js: all of it lights up) */
.brand b { color: var(--gold); }
.chip { background: var(--panel2); border: 1px solid var(--line); border-radius: 14px; padding: 3px 10px;
  white-space: nowrap; font-variant-numeric: tabular-nums; }
.chip .cap { color: var(--dim); font-size: 11px; }
.chip.full { border-color: #8a6a2a; }
.chip.full .cap { color: var(--gold); }
/* some store of the kind is full (workers pass it by) while others still have room: ' · 1 full', quietly */
.chip.some { border-color: #5e4c2c; }
.chip .nfull { color: #c9a35e; font-size: 11px; }
.chip.team b { font-weight: 700; }
.chip.flash, .tool.flash, .btn.flash { animation: flash 0.5s 2; }
.chip.good, .panel.good { animation: good 0.6s 2; }
@keyframes flash { 50% { background: #5a1f24; border-color: var(--red); } }
@keyframes good { 50% { background: #1d4029; border-color: var(--green); } }
.spacer { flex: 1; }
.speed { display: flex; gap: 2px; }
.btn { background: var(--panel2); border: 1px solid var(--line); border-radius: 6px; padding: 4px 10px; cursor: pointer;
  white-space: nowrap; }
.btn:hover { border-color: #5a5045; }
.btn.on { background: #3a3122; border-color: var(--gold); }
.btn.ghost { background: transparent; }
.btn.primary { background: #4a3a1c; border-color: var(--gold); }
.btn.wide { width: 100%; margin: 6px 0 2px; padding: 6px 10px; font-weight: 600; }
.btn.off { opacity: 0.45; }
.key { font-size: 10px; color: var(--dim); border: 1px solid var(--line); border-radius: 3px; padding: 0 4px;
  text-align: center; font-weight: 400; }
.sw { display: inline-block; width: 11px; height: 11px; border-radius: 3px; margin-right: 6px; vertical-align: -1px;
  border: 1px solid rgba(255, 255, 255, 0.25); }
.rf, .rm { white-space: nowrap; }
.rf::before, .rm::before { content: ''; display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin: 0 3px 0 4px; vertical-align: 0; }
.rf::before { background: var(--food); }
.rm::before { background: var(--minerals); border-radius: 2px; transform: rotate(45deg) scale(0.85); }

/* ---------- the right column ---------- */
#right { grid-area: right; display: flex; flex-direction: column; gap: 8px; padding: 8px; min-height: 0;
  overflow-y: auto; background: var(--panel); border-left: 1px solid var(--line); }
.panel { background: var(--panel2); border: 1px solid var(--line); border-radius: 8px; padding: 7px 9px; }
.panel.grow { flex: 1 1 auto; min-height: 140px; display: flex; flex-direction: column; }
.panel h2 { margin: 0 0 5px; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--dim);
  font-weight: 600; display: flex; justify-content: space-between; align-items: baseline; }
.h2note { text-transform: none; letter-spacing: 0; font-weight: 400; color: #6f665b; }
.small { font-size: 12px; }
.dim { color: var(--dim); }
.reason { min-height: 0; color: #ff9a8a; }
.reason:empty { display: none; }
.reason.ok { color: var(--green); }
.foot { margin-top: 2px; text-align: center; }
.hidden { display: none !important; }

/* ---------- the control bar (under the board) ---------- */
/* Four panels side by side, each a wide, low layout: the Colony, Training (its buttons in one row, Hatch into beside
   the heading, the queue as small chips), Build (the palette in two rows) and the Workers triangle. A panel's words
   and the training queue never widen it (.reason, the founding text: they wrap in the width the controls give; the
   queue's chips shrink, then the row scrolls); one taller than the bar scrolls itself, and the bar scrolls sideways
   when the column is too narrow for the four (ui.js: the wheel too). */
#bar { grid-area: bar; display: flex; gap: 3px; min-width: 0; padding: 4px 3px 3px; overflow-x: auto;
  overflow-y: hidden; background: var(--panel); border-top: 1px solid var(--line); user-select: none;
  scrollbar-width: thin; }
#bar > .panel { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; padding: 4px 5px;
  overflow-x: hidden; overflow-y: auto; scrollbar-width: thin; }
#bar .panel h2 { margin-bottom: 4px; }
#bar .small { font-size: 11.5px; line-height: 1.3; }
/* (no say in the panel's width: #panelTrain takes its min-content, so a full queue would push the bar wider) */
#bar .reason, #foundText, #evoNote, #evoMoltNote, #queue { width: 0; min-width: 100%; }
#bar .btn.wide { margin: 1px 0 3px; padding: 3px 10px; }
#bar #foundText { font-size: 11px; line-height: 1.25; }
/* Given room, the panels grow (the Colony up to 260 px; its words wrap). Short of room, the Colony and Build give
   some up (Build's names end in an ellipsis: the tooltips say them whole), down to what keeps every control whole:
   the Colony to 148 px (136 inside: its stage-2 words just fit the bar's height), Build never below --toolMin a
   column (ui.js sets --cols, its column count; + 9 px: its padding and border less one gap), so every price stays
   whole; past that the bar scrolls. Training stays whole: its buttons as tight as the palette's (.trainRow), the
   panels 3 px apart and from the bar's ends, 5 px sides, the worker triangle's canvas 136 px (ui.js TRI_W), so at
   1440 x 900 the four fit side by side at every stage, the widest Training (stage 2, Undermother: 351 px) too;
   once she has risen T holds the Egg-bearer in her place (3/3 of them: 335 px). */
#bar > #panelFound { flex: 1 1 164px; min-width: 148px; max-width: 260px; }
#bar > #panelTrain { min-width: min-content; }
#bar > #panelBuild { --toolMin: 77px; min-width: calc(var(--cols, 4) * (var(--toolMin) + 3px) + 9px); }
#bar > #panelWorkers { flex: 0 0 auto; flex-direction: row; align-items: stretch; gap: 4px; }
/* a long footer (exploring, in the tunnels) scrolls the Workers without a scrollbar: one would widen the panel, which
   takes its content's width, and push the bar past 1440 px; and at the Colony's 148 px floor the Evolve button keeps
   its keycap whole (its sides and gaps 4 px) */
#bar > #panelWorkers { scrollbar-width: none; }
#bar > #panelWorkers::-webkit-scrollbar { display: none; }
#bar .btn.wide.evobtn { padding-left: 4px; padding-right: 4px; gap: 4px; }

/* the Colony panel's evolution: the stage as pips with the path, the Evolve button (its price, its key), the molt */
.evopath { display: flex; align-items: center; gap: 6px; margin-top: 3px; font-size: 12px; }
.evopath b { color: #e3c77a; }
.pips { display: inline-flex; gap: 3px; }
.pips i { width: 8px; height: 8px; border-radius: 50%; border: 1px solid #8a6a2a; background: transparent; }
.pips i.on { background: var(--gold); border-color: var(--gold); }
.evobtn { display: flex; align-items: center; gap: 6px; }
.evobtn .ecost { flex: 1; text-align: right; font-size: 11px; font-weight: 400; color: #c9bfae; }
.evobtn .key { margin-left: 2px; }
.evobtn.poor .ecost { color: var(--red); }
.evobtn.short { opacity: 0.7; }
.evomolt { margin-top: 4px; font-size: 12px; }
.evomolt b { color: #e3c77a; }
.evomolt .num { font-variant-numeric: tabular-nums; color: var(--gold); }
.ebar { position: relative; display: block; height: 5px; margin: 3px 0 2px; background: #15130f; border-radius: 3px;
  overflow: hidden; box-shadow: inset 0 0 0 1px #2a251e; }
.ebar i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px;
  background: repeating-linear-gradient(135deg, #c9a35e 0 4px, #8a6a2a 4px 7px); }
#evoNote:empty { display: none; }

/* buttons with an icon (training and the palette): classes off, locked, full, short, poor (ui.js). The key sits on
   the button's upper edge at its right, a keycap that never widens it. */
.tool { position: relative; display: grid; grid-template-columns: 18px 1fr; grid-template-rows: auto auto;
  align-items: center; column-gap: 5px; row-gap: 1px; text-align: left; background: #1a1814;
  border: 1px solid var(--line); border-radius: 6px; padding: 4px 5px 3px; cursor: pointer; }
.tool .key { position: absolute; right: 4px; top: -6px; padding: 0 3px; font-size: 9px; line-height: 11px;
  background: #1a1814; }
.tool.on .key { border-color: var(--gold); color: var(--gold); }
.tool:hover { border-color: #5a5045; }
.tool.on { border-color: var(--gold); background: #2e2717; }
.tool.poor { opacity: 0.6; }
.tool.poor .cost { color: var(--red); }
.tool.full { opacity: 0.6; }
.tool.full .capn { color: var(--red); }
.tool.off { opacity: 0.45; }
/* not unlocked yet: greyed, its stage on the tag ('stage 1'), what unlocks it in the tip; a slot to evolve into
   (R, T, 7 before the colony has its own) says so where the price goes */
.tool.locked { opacity: 0.55; }
.tool.locked .cost { color: var(--dim); }
.tool.locked .stor { color: var(--dim); border-color: var(--line); }
.tool.slot .nm { color: var(--dim); font-style: italic; }
/* a price above the storage cap: no amount of waiting pays it, a container does ('needs storage', reason in the tip);
   the tag (or a locked type's 'stage 2') sits on a training button's lower edge, so it never widens it (the
   palette's: after the name) */
.tool.short { opacity: 0.7; }
.tool .stor { position: absolute; right: 4px; bottom: -6px; padding: 0 3px; font-size: 9px; line-height: 11px;
  color: var(--gold); white-space: nowrap; background: #1a1814; border: 1px solid #6a5426; border-radius: 3px; }
.tool .stor:empty { display: none; }
.tool canvas { display: block; }
.tool .nm { line-height: 1.15; white-space: nowrap; }
.tool .cost { font-size: 11px; color: #c9bfae; white-space: nowrap; }
.tool .cost .rf::before, .tool .cost .rm::before { margin: 0 2px 0 3px; }
/* a capped type's count ('1/2', colossus) on the upper edge at the left */
.tool .capn { position: absolute; left: 4px; top: -6px; padding: 0 3px; font-size: 9px; line-height: 11px;
  color: var(--dim); font-variant-numeric: tabular-nums; background: #1a1814; border: 1px solid var(--line);
  border-radius: 3px; }
.tool .capn:empty { display: none; }

/* training: the buttons in one row (icon and name on the first line; the price and time under them), sharing what
   room the panel has. As tight as the palette's (padding, the name 2 px from its icon, 3 px apart), so stage 2's
   four fit the 1440 px bar; never narrower than their contents (max-content: the price row spans the flexible
   column, which a min-content size leaves out, and the row then overflowed the panel, its last button cut) */
.phead { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 4px; }
#bar .phead h2 { margin: 0; justify-content: flex-start; gap: 6px; }
.trainRow { display: flex; gap: 3px; }
.trainRow .tool { flex: 1 0 auto; min-width: max-content; padding: 4px 4px 3px; column-gap: 2px; }
.trainRow .tool .cost { grid-column: 1 / 3; }
.trainRow .tool .cost .rf:first-child::before, .trainRow .tool .cost .rm:first-child::before { margin-left: 0; }
/* the queue: a chip per order (its creature's icon; a fighter bound to a legion its numeral in the legion's colour,
   set inline), the first with its progress; any number of them shrink to share the row (scrolling past that) */
.queue { display: flex; gap: 2px; min-height: 22px; margin-top: 7px; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; }
.qslot { position: relative; flex: 0 1 26px; min-width: 12px; height: 22px; padding: 0; display: flex;
  align-items: center; justify-content: center; overflow: hidden; background: #1a1814; border: 1px solid var(--line);
  border-radius: 4px; cursor: pointer; }
.qslot canvas { display: block; pointer-events: none; }
.qslot:hover { border-color: var(--red); }
.qslot:hover canvas { opacity: 0.3; }
.qslot:hover::after { content: '\00d7'; position: absolute; left: 0; right: 0; top: 1px; text-align: center;
  color: var(--red); font-weight: 700; }
.qslot .qbar { position: absolute; left: 0; bottom: 0; height: 3px; background: var(--gold); }
.qslot.q-colossus, .qslot.q-devourer, .qslot.q-scald, .qslot.q-corroder, .qslot.q-matron,
.qslot.q-undermother, .qslot.q-wyrm { border-color: #7a4a3a; }   /* the specials stand out */
.qslot.q-eggbearer { border-color: #8a7652; }   /* an Egg-bearer (a walking colony's Egg Mound on legs): pale sand */
.qslot .qn { position: absolute; right: 1px; top: -1px; font-size: 9px; font-weight: 800; line-height: 1.1;
  text-shadow: 0 0 2px #000, 0 0 2px #000; }
.qslot .qn:empty { display: none; }
.qslot:hover .qn { opacity: 0.35; }
/* 'Hatch into': Auto | I | II | III beside the heading (key G); the numerals in the legions' colours */
.hatchRow { display: flex; align-items: center; gap: 5px; font-size: 11px; }
.hatchRow.off { opacity: 0.45; }
.hatchRow .hlab { color: var(--dim); white-space: nowrap; }
.hatchRow .hlab .key { margin-left: 2px; }
.seg { display: flex; flex: 0 0 auto; min-width: 0; border: 1px solid var(--line); border-radius: 6px;
  overflow: hidden; }
/* each segment as wide as its label */
.segb { flex: 1 1 auto; padding: 1px 6px; background: #1a1814; border: none; white-space: nowrap;
  border-left: 1px solid var(--line); font-size: 12px; font-weight: 800; cursor: pointer; }
.segb:first-child { border-left: none; }
.segb:hover { background: #24201a; }
.segb.on { background: #3a3122; box-shadow: inset 0 0 0 1px var(--gold); }

/* the build palette in two rows (ui.js sets the columns: half the buttons, rounded up): icon and price on top, the
   name under them and after it a locked building's 'stage 1' (the price's own box gives way to its two parts). Its
   buttons are as tight as the training ones (the price 2 px from the icon, its first dot without its left margin),
   so the two-part prices fit the 1440 px window's five columns */
.palette { display: grid; grid-template-columns: repeat(4, minmax(0, auto)); gap: 7px 3px; }
.palette .tool { grid-template-columns: 18px minmax(0, auto) minmax(0, 1fr); column-gap: 0; padding: 4px 4px 3px; }
.palette .tool canvas { grid-column: 1; grid-row: 1; }
.palette .tool .cost { display: contents; }
.palette .tool .cost > span:first-child { grid-column: 2 / 4; grid-row: 1; margin-left: 2px; overflow: hidden;
  text-overflow: ellipsis; }
.palette .tool .cost .rf:first-child::before, .palette .tool .cost .rm:first-child::before { margin-left: 0; }
.palette .tool .nm { grid-column: 1 / 3; grid-row: 2; font-size: 11px; overflow: hidden; text-overflow: ellipsis; }
.palette .tool .stor { position: static; grid-column: 3; grid-row: 2; justify-self: start; margin-left: 4px; }

/* the worker triangle: its heading, hint and footer in a narrow column beside it (as wide as WORKERS, 58 px) */
.wside { flex: 0 0 60px; display: flex; flex-direction: column; min-width: 0; }
.wside .h2note { font-size: 11px; }
.wside .foot { margin-top: 6px; text-align: left; font-size: 11px; line-height: 1.3; }
/* drawn at its own size, 136 x 120 (ui.js makeTriangle; it maps the pointer through the displayed size) */
canvas.tri { display: block; flex: 0 0 auto; align-self: center; cursor: pointer; }

/* ---------- board ---------- */
/* the board is a viewport onto the arena (render.js's camera): it fills its column but for a thin frame, main.js
   fits it on resize */
#boardWrap { grid-area: board; position: relative; display: flex; align-items: center; justify-content: center;
  overflow: hidden; min-width: 0; min-height: 0; }
#board { display: block; cursor: crosshair; }
/* the minimap: the whole arena small in the board's bottom-left corner, clear of the banner strip and the badge
   (render.js sizes and draws it, the size it sets being the drawing's, the border outside it, and hides it while the
   whole arena is in view; a click or a drag moves the camera there) */
.minimap { position: absolute; left: 16px; bottom: 16px; display: block; box-sizing: content-box;
  border: 1px solid #4a4238; border-radius: 4px; background: rgba(14, 12, 10, 0.88);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.55); cursor: pointer; }
.minimap:hover { border-color: #6a5e4e; }
/* A slim strip at the top edge of the board (about 3 rows): founders spawn further in, so it never hides yours.
   Kicker and title share one line. */
.banner { position: absolute; left: 50%; top: 6px; transform: translate(-50%, -10px); min-width: 0; width: max-content;
  max-width: min(620px, 92%); padding: 5px 16px 7px; text-align: center; pointer-events: none; opacity: 0;
  transition: opacity 0.6s, transform 0.6s; background: rgba(14, 12, 10, 0.86); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6); }
.banner.show { opacity: 1; transform: translate(-50%, 0); }
.banner .kicker { display: inline; margin-right: 8px; font-size: 10px; letter-spacing: 2px; text-transform: uppercase;
  color: var(--dim); }
.banner .title { display: inline; font-size: 20px; font-weight: 800; letter-spacing: 1px; line-height: 1.2; }
.banner .text { margin-top: 1px; font-size: 13px; line-height: 1.35; color: #d8cfc0; }
.banner.k-god { border-color: var(--god); } .banner.k-god .title { color: #d2b6ff; }
.banner.k-omen { border-color: #4fb3c8; } .banner.k-omen .title { color: #8fe3f0; }
.banner.k-wrath { border-color: #e04a7a; } .banner.k-wrath .title { color: #ff8fb4; }
.banner.k-elim { border-color: var(--red); } .banner.k-elim .title { color: #ff9a8a; }
.banner.k-good { border-color: var(--green); } .banner.k-good .title { color: #a4f0bd; }
.banner.k-bad { border-color: #e0703a; } .banner.k-bad .title { color: #ffb38a; }
.banner.k-food { border-color: var(--food); } .banner.k-food .title { color: #c8eda0; }
.banner.k-minerals { border-color: var(--minerals); } .banner.k-minerals .title { color: #b8d6ff; }
/* the Watcher's favor: a boon of your own, a punishment your shrines turned aside */
.banner.k-boon { border-color: var(--gold);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6), 0 0 18px rgba(240, 198, 116, 0.25); }
.banner.k-boon .title { color: #ffe3a0; }
/* your colony's evolution: its molt begins, it has evolved */
.banner.k-evo { border-color: #c9a35e; } .banner.k-evo .title { color: #f0d79a; }
/* at the bottom edge, clear of the banner strip at the top (over the minimap on a narrow board) */
.badge { position: absolute; z-index: 2; bottom: 10px; left: 50%; transform: translateX(-50%); padding: 3px 12px;
  border-radius: 12px; background: rgba(58, 49, 34, 0.92); border: 1px solid var(--gold); color: var(--gold);
  font-weight: 600; pointer-events: none; }
.ping { position: absolute; width: 22px; height: 22px; margin: -11px 0 0 -11px; border: 2px solid #9cffb5;
  border-radius: 50%; pointer-events: none; animation: ping 0.45s ease-out forwards; }
@keyframes ping { from { transform: scale(0.3); opacity: 1; } to { transform: scale(1.4); opacity: 0; } }
.toast { position: fixed; z-index: 20; background: #3a1418; border: 1px solid var(--red); color: #ffd6d6;
  border-radius: 6px; padding: 4px 9px; font-size: 12px; pointer-events: none; white-space: nowrap;
  transform: translate(-50%, -140%); }
.toast.good { background: #14301f; border-color: var(--green); color: #d6ffe4; }
.toast.below { transform: translate(-50%, 60%); }
/* diplomacy (ui.js): the menu a right-click on another colony opens at the pointer, and the offers waiting for your
   answer as cards in the board's bottom-right corner (inside #boardWrap, so they ride with the board), newest last */
.diplo { position: absolute; z-index: 4; width: 196px; padding: 6px; background: rgba(20, 17, 13, 0.96);
  border: 1px solid #5a4e3e; border-radius: 8px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6); font-size: 12px; }
.diplo .dhead { display: flex; align-items: center; gap: 5px; font-size: 13px; }
.diplo .dstand { margin: 2px 0 5px; color: var(--dim); font-size: 11px; line-height: 1.3; }
.diplo .dbtn { display: block; width: 100%; margin-top: 3px; text-align: left; }
.diplo .btn.off { opacity: 0.5; }
.diplo .epick { display: grid; grid-template-columns: repeat(4, 1fr); gap: 3px; margin-top: 4px; }
.diplo .emo { padding: 2px 0; font-size: 17px; line-height: 1.2; text-align: center; }
.offers { position: absolute; z-index: 3; right: 12px; bottom: 12px; display: flex; flex-direction: column;
  gap: 6px; width: 230px; pointer-events: none; }
.offer { padding: 7px 9px; background: rgba(20, 17, 13, 0.95); border: 1px solid var(--green); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6); font-size: 12px; pointer-events: auto; }
.offer .ohead { display: flex; align-items: center; gap: 5px; font-size: 13px; }
.offer .otext { margin: 3px 0 4px; color: #d8cfc0; line-height: 1.3; }
.offer .oleft { font-weight: 700; color: var(--gold); }
.offer .obar { height: 3px; background: #2c271f; border-radius: 2px; overflow: hidden; }
.offer .obar i { display: block; height: 100%; background: var(--green); }
.offer .obtns { display: flex; gap: 4px; margin-top: 6px; }
.offer .obtns .btn { flex: 1; padding: 3px 0; }
.trow .dip { grid-column: 2 / 4; font-size: 11px; }
.trow .dtruce { color: var(--green); }
.trow .dhost { color: #e0a080; }
.trow .dask { color: var(--gold); }

/* ---------- the Watcher strip (over the board column, under the top bar) ---------- */
/* How He regards you (a face whose colour also edges the strip), the decree in two lines (its title, its text and the
   clock; a bar of the time left and your goal bar with its label) and the omen to come. Its height is fixed, so the
   board under it is measured without feeding back on itself. */
.watch { grid-area: watch; display: flex; align-items: center; gap: 10px; height: var(--watchH); min-width: 0;
  padding: 0 10px 0 8px; overflow: hidden; background: var(--panel); border-bottom: 1px solid var(--line);
  border-left: 3px solid #4b3870; user-select: none; }
.watch .face { flex: 0 0 auto; display: flex; align-items: center; gap: 7px; color: #b48cff; cursor: help; }
.watch .fsvg { display: block; width: 32px; height: 32px; overflow: visible; }
.watch .fsvg .hd { fill: currentColor; fill-opacity: 0.14; stroke: currentColor; stroke-width: 1.6; }
.watch .fsvg .ln { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round;
  stroke-linejoin: round; }
.watch .fsvg .dot { fill: currentColor; }
.watch .fsvg .gape { fill: currentColor; fill-opacity: 0.85; stroke: currentColor; stroke-width: 1.2;
  stroke-linejoin: round; }
.watch .flabs { display: flex; flex-direction: column; line-height: 1.15; white-space: nowrap; }
.watch .fk { font-size: 9px; letter-spacing: 1px; text-transform: uppercase; color: var(--dim); }
.watch .fl { font-size: 13px; font-weight: 800; letter-spacing: 0.5px; }
/* the face's level: gold beaming .. red scowl (with a soft glow); the strip's left edge in the same colour */
.watch.f-beaming { border-left-color: var(--gold); }
.watch.f-beaming .face { color: var(--gold); }
.watch.f-beaming .fsvg { filter: drop-shadow(0 0 3px rgba(240, 198, 116, 0.55)); }
.watch.f-smile { border-left-color: var(--green); }
.watch.f-smile .face { color: var(--green); }
.watch.f-flat { border-left-color: #6f5aa0; }
.watch.f-flat .face { color: #c3a6ff; }
.watch.f-frown { border-left-color: #e0803a; }
.watch.f-frown .face { color: #ffa45c; }
.watch.f-scowl { border-left-color: #ff5e8a; }
.watch.f-scowl .face { color: #ff6e94; }
.watch.f-scowl .fsvg { filter: drop-shadow(0 0 4px rgba(255, 94, 138, 0.7)); }
.watch.f-scowl .fsvg .ln { stroke-width: 2.4; }
.wbody { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 4px; }
.wl1 { display: flex; align-items: baseline; gap: 8px; min-width: 0; white-space: nowrap; line-height: 1.25; }
.wtitle { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: #d2b6ff; font-weight: 700; }
.wtext { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: 12px; color: #c9bfae; }
.wtitle.quiet { color: #a89cc0; font-weight: 600; }   /* no decree: the silence until the next one */
.wnext { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: 12px; color: var(--dim); }
.wnext b { color: var(--gold); font-variant-numeric: tabular-nums; }
.wclock { flex: 0 0 auto; margin-left: auto; font-variant-numeric: tabular-nums; color: var(--gold); font-weight: 700; }
.wl2 { display: flex; align-items: center; gap: 12px; min-width: 0; height: 14px; }
.wtime, .wgbar { position: relative; display: block; height: 6px; background: #15130f; border-radius: 3px;
  overflow: hidden; box-shadow: inset 0 0 0 1px #2a251e; }
.wtime i, .wgbar i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; }
/* the decree's time left (or the silence until the next one), draining; under its last fifth it turns red */
.wtime { flex: 1 1 0; min-width: 48px; max-width: 240px; }
.wtime i { background: linear-gradient(90deg, #6a5acd, #b48cff); }
.wtime.low i { background: linear-gradient(90deg, #e04a7a, #ff8fb4); }
.wl2.wide .wtime { max-width: none; }
/* your progress toward the minimum, coloured by your standing; the label beside it says where you stand */
.wgoal { flex: 1.7 1 0; display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 11px;
  white-space: nowrap; }
.wgbar { flex: 1 1 0; min-width: 36px; max-width: 200px; }
.wgbar i { background: var(--gold); }
.wglab { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: #d9c48e;
  font-variant-numeric: tabular-nums; }
.wglab .sw { width: 8px; height: 8px; margin-right: 3px; }
.wgoal.lead .wgbar i, .wgoal.ok .wgbar i { background: var(--green); }
.wgoal.lead .wglab, .wgoal.ok .wglab { color: #a4f0bd; }
.wgoal.below .wgbar i { background: var(--red); }
.wgoal.below .wglab { color: #ff9a8a; }
/* a tribute (a food or minerals decree) measures that kind: its mark and hue, as the store gauges; the label (and,
   below the minimum, a red edge round the bar) still says where you stand */
.wgoal > .rf, .wgoal > .rm { flex: 0 0 auto; margin-right: -3px; line-height: 0; }
.wgoal > .rf::before, .wgoal > .rm::before { margin: 0; }
.wgoal.k-food .wgbar i { background: var(--food); }
.wgoal.k-minerals .wgbar i { background: var(--minerals); }
.wgoal.below.k-food .wgbar, .wgoal.below.k-minerals .wgbar { box-shadow: inset 0 0 0 1px #2a251e,
  0 0 0 1px rgba(255, 107, 107, 0.75); }
.wgoal.exempt .wgbar i { background: #6f665b; }
.wgoal.exempt .wglab, .wgoal.note .wglab { color: var(--dim); }
.wgoal.note .wgbar { display: none; }   /* only words: before founding, a destroy decree */
/* the game is over: one line, no bars */
.watch.over .wl2, .watch.over .women { display: none; }
.watch.over .wtitle { font-size: 14px; }
.watch.over.won .wtitle { color: var(--gold); }
.watch.over.lost .wtitle { color: #ff9a8a; }
/* the omen to come (or under way), at the strip's right */
.women { flex: 0 0 auto; max-width: 30%; min-width: 0; padding: 2px 8px; font-size: 12px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; border-left: 3px solid #4fb3c8; background: #1a1d1f; border-radius: 3px;
  cursor: help; }
.women:empty { display: none; }
.women b { color: #8fe3f0; }
.women .dim { font-variant-numeric: tabular-nums; }
.women.on { border-left-color: var(--gold); background: #24201a; }
.women.on b { color: #ffe3a0; }
/* news from the Watcher: a decree or its end (purple), His gift to you (gold), His anger (red) */
.watch.pulse { animation: wpulse 0.7s 2; }
.watch.pgood { animation: wgood 0.7s 2; }
.watch.pbad { animation: wbad 0.7s 2; }
@keyframes wpulse { 50% { background: #2a2140; } }
@keyframes wgood { 50% { background: #33290f; } }
@keyframes wbad { 50% { background: #3a1420; } }

/* ---------- the Watcher ---------- */
.panel.god { border-color: #4b3870; }
.decree { margin-bottom: 6px; }
.row { display: flex; justify-content: space-between; align-items: baseline; gap: 6px; }
.godc { color: #d2b6ff; }
.cd { font-variant-numeric: tabular-nums; color: var(--gold); font-weight: 700; }
.dtext { font-size: 12px; color: #c9bfae; margin: 2px 0 4px; }
.srow { display: grid; grid-template-columns: 17px 52px 1fr 34px; align-items: center; gap: 4px; font-size: 12px; }
.srow.dead { opacity: 0.4; }
.srow.me .nm { font-weight: 700; }
.srow b { text-align: right; font-variant-numeric: tabular-nums; }
.sbar { position: relative; height: 7px; background: #15130f; border-radius: 4px; overflow: hidden; }
.sbar i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 4px; }
/* the minimum: gold with a black edge, so it shows on every team's bar (White's too) */
.sbar u { position: absolute; top: -1px; bottom: -1px; width: 2px; background: var(--gold);
  box-shadow: 0 0 0 1px #000; }
.wrathline { margin-top: 1px; color: #a89cc0; }
.wrathline.hot { color: #ff8fb4; }
.stand { margin-top: 3px; font-size: 12px; font-weight: 600; }
.stand.ok, .stand.lead { color: var(--green); }
.stand.below { color: var(--red); }
.omen { font-size: 12px; padding: 3px 6px; margin: 3px 0; border-left: 3px solid #4fb3c8; background: #1a1d1f;
  border-radius: 3px; }
.omen.active { border-left-color: var(--gold); background: #24201a; }
.omen .dim { font-size: 11px; }
/* the Watcher's waves: what is left of the current one (the bar fills as it is gathered), when the next one falls */
.waves { margin: 6px 0 2px; }
.wave { font-size: 12px; padding: 2px 0; }
.wave + .wave { border-top: 1px solid #262119; }
.wave .num { font-variant-numeric: tabular-nums; }
.wave .dim { font-size: 11px; }
.wbar { position: relative; display: block; height: 4px; margin: 2px 0 1px; background: #15130f; border-radius: 2px; }
.wbar i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 2px; }
.wbar i.food { background: var(--food); }
.wbar i.minerals { background: var(--minerals); }
.wbar u { position: absolute; top: -1px; bottom: -1px; width: 2px; background: var(--gold);
  box-shadow: 0 0 0 1px #000; }
.mood { display: grid; grid-template-columns: 38px 1fr 64px; gap: 6px; align-items: center; font-size: 12px;
  margin: 6px 0 2px; }
.mbar { position: relative; height: 8px; background: #15130f; border-radius: 4px; overflow: hidden; }
.mbar i { position: absolute; left: 0; top: 0; bottom: 0;
  background: linear-gradient(90deg, #6a5acd, #b48cff, #ff5e8a); }
.mbar u { position: absolute; top: 0; bottom: 0; width: 2px; background: #ff5e8a; }
.mlabel { text-align: right; color: #d2b6ff; }
/* favor: the viewer's shrines, their boon chance and chance to be spared (gold, quiet when there are none) */
.favor { font-size: 12px; margin: 5px 0 2px; padding: 2px 6px; border-left: 3px solid #b8954a; background: #1f1b14;
  border-radius: 3px; }
.favor .flab { color: #e3c77a; }
.favor .num { font-variant-numeric: tabular-nums; color: var(--gold); }
.favor .fsub { font-size: 11px; color: #d9c48e; }
.favor .fsub .sw { width: 8px; height: 8px; margin-right: 3px; }
.favor.none { border-left-color: var(--line); background: transparent; }
.favor.none .flab, .favor.none .fsub { color: var(--dim); }
.favor .nw, .inspect .favorc .nw { white-space: nowrap; }   /* '45% to be spared' wraps whole, never mid-phrase */
.hist { font-size: 11px; color: #a89cc0; margin-top: 3px; }
.hist div { padding: 1px 0; border-top: 1px solid #262119; }
.hist .t { color: #6f665b; margin-right: 5px; font-variant-numeric: tabular-nums; }

/* teams */
/* the name takes what it needs, the status the rest (it wraps, right-aligned: 'founded NW · Swarm · Matron') */
.trow { display: grid; grid-template-columns: 17px auto minmax(0, 1fr); align-items: center; gap: 2px 4px;
  font-size: 12px; padding: 2px 0; border-bottom: 1px solid #262119; }
.trow:last-child { border-bottom: none; }
.trow.dead { opacity: 0.45; }
.trow .who { color: var(--dim); font-size: 11px; margin-left: 4px; }
.trow .st { font-size: 11px; text-align: right; }
.trow .st.founded { color: var(--green); }
.trow .st.wandering { color: var(--gold); }
.trow .st.eliminated { color: var(--red); }
.trow .uc { grid-column: 2 / 4; font-size: 11px; color: #c9bfae; }
/* more colonies than the default: tighter rows (Teams, the decree's scores) */
#right.many .trow { padding: 1px 0; gap: 0 4px; }
#right.many .trow .uc { font-size: 10.5px; line-height: 1.25; }
#right.many .srow { line-height: 1.25; }

/* inspect */
.inspect { min-height: 48px; }
.inspect .it { padding: 2px 0; }
.inspect .it + .it { border-top: 1px solid #262119; }
.inspect .hp { color: var(--red); font-variant-numeric: tabular-nums; }   /* health is red, as on the board */
.inspect .okc { color: var(--green); }
.inspect .bad { color: #ff9a8a; }
.inspect .where { color: #6f665b; font-size: 11px; }
.inspect .farmc { color: #a6d47a; }
.inspect .minec { color: var(--minerals); }
.inspect .sfull { color: var(--gold); }
.inspect .favorc { color: #e3c77a; }
.inspect .seen { font-size: 11px; font-style: italic; }   /* fog memory: 'last seen 0:42 ago' */
.inspect .rf::before, .inspect .rm::before { margin-left: 1px; }

/* log */
.log { overflow-y: auto; flex: 1; font-size: 12px; min-height: 0; }
.log div { padding: 1px 0; border-bottom: 1px solid #221e18; }
.log .t { color: #6f665b; margin-right: 5px; font-variant-numeric: tabular-nums; }
.log .sw { width: 8px; height: 8px; margin-right: 4px; }

/* ---------- overlays ---------- */
.overlay { position: fixed; inset: 0; background: rgba(6, 5, 4, 0.78); display: flex; align-items: center;
  justify-content: center; z-index: 10; }
.overlay.top { z-index: 55; }   /* Settings: over the home screen too */
.setRow { display: flex; align-items: center; gap: 10px; margin: 10px 0 4px; font-size: 14px; cursor: pointer; }
.setRow input { width: 16px; height: 16px; accent-color: var(--gold); }
.setNote { margin: 0 0 8px 26px; max-width: 380px; }
.overlayInner { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 18px 22px;
  max-width: 780px; max-height: 88vh; overflow-y: auto; }
.overlayInner h1 { margin: 0 0 8px; font-size: 22px; letter-spacing: 3px; }
.overlayInner h1.won { color: var(--gold); }
.overlayInner h1.lost { color: var(--red); }
.overlayInner h3 { margin: 14px 0 4px; font-size: 13px; color: var(--gold); }
.overlayInner p, .overlayInner li { color: #d0c7b8; }
.overlayInner ul { padding-left: 20px; margin: 4px 0; }
.overlayInner table { border-collapse: collapse; width: 100%; font-size: 12px; }
.overlayInner td, .overlayInner th { padding: 2px 6px; border-bottom: 1px solid #2a251e; vertical-align: top;
  text-align: left; }
.overlayInner th { color: var(--dim); font-weight: 600; }
.overlayInner td:first-child { color: var(--gold); white-space: nowrap; }
.overlayInner .stats td:first-child { color: inherit; }
.overlayInner .stats td { text-align: right; font-variant-numeric: tabular-nums; }
.overlayInner .stats td:first-child, .overlayInner .stats th:first-child { text-align: left; }
.overlayInner .actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 14px; }
.overlayInner code { background: var(--panel2); padding: 0 4px; border-radius: 3px; }
/* the New game setup: colonies, arena, size as rows of segmented buttons, what the choice makes under them */
.setup { display: flex; flex-direction: column; gap: 8px; margin: 6px 0 4px; }
.setrow { display: grid; grid-template-columns: 74px minmax(0, 1fr); align-items: center; gap: 8px; }
.setlab { color: var(--dim); font-size: 12px; text-transform: uppercase; letter-spacing: 1px; }
.setup .seg { flex-wrap: wrap; }
.setup .segb { padding: 5px 10px; font-size: 13px; font-weight: 600; color: #d0c7b8; }
.setup .segb.on { color: var(--gold); }
.setup .segb b { margin-left: 3px; font-weight: 400; color: var(--dim); font-variant-numeric: tabular-nums; }
.setup .segb.on b { color: #c9a35e; }
.setup .shp { width: 14px; height: 14px; margin-right: 5px; vertical-align: -2px; fill: currentColor; opacity: 0.85; }
.setnote { margin: 2px 0 0; min-height: 3.2em; font-size: 12px; color: #c9bfae; }
.setnote b { color: var(--text); }
/* the Evolve choice: a card per direction (2 x 2) or pick (side by side), the picked one lit like a segment; each
   with its digit, its words, its creature and building (an icon, the price, the numbers) and what it leads to */
.evohead { margin: 0 0 6px; font-size: 12px; }
.evocards { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 8px 0 4px; }
.evocard { background: var(--panel2); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px;
  font-size: 12px; color: #d0c7b8; cursor: pointer; user-select: none; }
.evocard:hover { border-color: #5a5045; }
.evocard.on { border-color: var(--gold); background: #2e2717; box-shadow: inset 0 0 0 1px var(--gold); }
.evocard .eh { display: flex; align-items: baseline; gap: 7px; }
.evocard .eh b { font-size: 15px; letter-spacing: 0.5px; color: var(--text); }
.evocard.on .eh b { color: var(--gold); }
.evocard .esub { color: #c9a35e; }
.evocard .ek { margin-left: auto; }
.evocard .eflav { margin: 3px 0 6px; font-style: italic; color: #c9bfae; }
.evocard .eline { display: grid; grid-template-columns: 18px minmax(0, 1fr); align-items: center; gap: 7px;
  margin: 4px 0; line-height: 1.3; }
.evocard .ethen { margin-top: 6px; font-size: 11px; color: var(--dim); }
.overlayInner .evocards + .reason { min-height: 1.4em; }

/* (the right column a little narrower, so the control bar's four panels fit side by side at 1280 px) */
@media (max-width: 1300px) {
  #app { grid-template-columns: minmax(0, 1fr) 250px; }
}
/* Narrower still, the four panels cannot fit even squeezed: each keeps its whole width and the bar scrolls sideways. */
@media (max-width: 1200px) {
  #bar > #panelFound { min-width: 164px; }
  #bar > #panelBuild { min-width: max-content; }
  .brand { display: none; }
  #topbar { gap: 4px; padding: 0 6px; }
  .chip { padding: 3px 7px; }
}
/* Short windows (1366 x 768, a 1080p laptop with browser chrome): the right column's panels a little tighter */
@media (max-height: 900px) {
  #right .panel { padding: 5px 8px; }
  #right .panel h2 { margin-bottom: 3px; }
}
/* Narrower: a slimmer right column and a top bar that may wrap. */
@media (max-width: 1150px) {
  #app { grid-template-columns: minmax(0, 1fr) 234px;
    grid-template-rows: auto var(--watchH) minmax(0, 1fr) var(--barH); }
  #topbar { flex-wrap: wrap; row-gap: 4px; padding: 6px; }
  #right { padding: 6px; gap: 6px; scrollbar-width: thin; }
  #right .panel { padding: 6px 7px; }
  .srow { grid-template-columns: 15px 46px 1fr 30px; }
}
/* Narrow windows: the right column (the Watcher, teams, inspector, log) drops below the control bar; scroll down to
   it. The strip, the board and the bar keep the window's height (the board's row is what the others leave), so the
   board is measured without feeding back on itself. The strip stays at the top of the window while the page scrolls:
   it is placed from its row to the grid's end (over the rows under it, at their top: align-self) so that sticky has
   room to move in. */
@media (max-width: 1000px) {
  #app { height: auto; min-height: 100vh; grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto var(--watchH) max(240px, calc(100vh - 46px - var(--watchH) - var(--barH))) var(--barH)
      auto;
    grid-template-areas: "top" "watch" "board" "bar" "right"; }
  #watchStrip { grid-area: auto; grid-column: watch; grid-row: watch-start / -1; align-self: start; position: sticky;
    top: 0; z-index: 5; box-shadow: 0 6px 14px rgba(0, 0, 0, 0.35); }
  #right { flex-direction: row; flex-wrap: wrap; align-items: flex-start; overflow: visible; border-left: none;
    border-top: 1px solid var(--line); }
  #right > .panel { flex: 1 1 260px; min-width: 0; }
  #right > .panel.grow { min-height: 0; }
  #right .log { max-height: 260px; }
}
/* Phone-narrow: one column, the board first (most of the window's height: the panels peek out under it), then the
   control bar's panels stacked (as tall as they need: the page scrolls down to them), then the right column's. */
@media (max-width: 620px) {
  #app { grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto var(--watchH) max(320px, calc(100vh - 160px - var(--watchH))) auto auto;
    grid-template-areas: "top" "watch" "board" "bar" "right"; }
  /* the strip on a phone: the face smaller, no kicker, the decree's title and clock without its text */
  .watch { gap: 7px; padding: 0 7px 0 5px; }
  .watch .face { gap: 5px; }
  .watch .fsvg { width: 26px; height: 26px; }
  .watch .fk, .wtext { display: none; }
  .wl2 { gap: 8px; }
  .women { max-width: 34%; padding: 2px 6px; font-size: 11px; }
  .setrow { grid-template-columns: minmax(0, 1fr); gap: 3px; }
  .evocards { grid-template-columns: minmax(0, 1fr); }
  #bar { flex-direction: column; gap: 6px; overflow: visible; }
  #bar > .panel, #bar > #panelFound, #bar > #panelTrain, #bar > #panelBuild, #bar > #panelWorkers { flex: 0 0 auto;
    min-width: 0; max-width: none; overflow: visible; }
  .trainRow { flex-wrap: wrap; }
  .trainRow .tool { flex: 1 0 40%; }
  .palette { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }   /* (ui.js sets the columns inline) */
  .palette .tool .nm { overflow: hidden; text-overflow: ellipsis; }
  #panelWorkers { justify-content: center; }
}

/* a game on the server (online.js): its bar over the board */
.online { position: absolute; right: 8px; bottom: 8px; z-index: 15; display: flex;
  align-items: center; gap: 8px; flex-wrap: wrap; max-width: calc(100% - 32px); padding: 4px 10px;
  background: rgba(23, 21, 18, 0.92); border: 1px solid var(--line); border-radius: 8px; font-size: 12px; }
.online:empty { display: none; }
.online .ol-head { margin: 0; font-size: 18px; }
.online .ol-row { display: flex; align-items: center; gap: 8px; }
.online .ol-code { font-size: 20px; font-weight: 700; letter-spacing: 3px; color: var(--text); }
.online .ol-copy { padding: 2px 10px; }
.online .ol-link { width: 210px; background: var(--panel2); color: var(--text); border: 1px solid var(--line);
  border-radius: 4px; padding: 2px 4px; font: inherit; }
.online .ol-join { width: 64px; background: var(--panel2); color: var(--text); border: 1px solid var(--line);
  border-radius: 4px; padding: 2px 4px; font: inherit; text-transform: uppercase; }

/* the home screen of the server's page (online.js): the title over the menu card, over a frame of an all-AI game
   (img/home.webp, drawn by render.js), darkened toward its edges; the game's control bar hidden under it
   (#app.atHome). The title is the top bar's brand writ large (BROOD light, FIGHT gold and bold, spaced out), in the
   player's own system font like everything else: the page loads no font. */
.home { position: fixed; inset: 0; z-index: 40; display: flex; flex-direction: column; align-items: center;
  justify-content: safe center; gap: 14px; padding: 16px 0; overflow-y: auto;
  background: radial-gradient(ellipse at center, rgba(14, 13, 11, 0.12), rgba(14, 13, 11, 0.6)),
    url("../img/home.webp") center / cover no-repeat, var(--bg); }
.home.hidden { display: none; }
#app.atHome #bar { visibility: hidden; }
.homeHead { text-align: center; padding: 0 16px; }
.homeTitle { margin: 0; font-size: clamp(34px, 8vw, 64px); font-weight: 400; line-height: 1.1;
  letter-spacing: 0.22em; padding-left: 0.22em; color: #d6cebf;
  text-shadow: 0 2px 0 #1e140b, 0 0 24px rgba(0, 0, 0, 0.8); }
.homeTitle b { color: var(--gold); font-weight: 800; }
.homeFoot { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.homeRight { display: flex; gap: 12px; align-items: baseline; }
.homeVer { color: var(--dim); font-size: 12px; }
/* a deploy since the page loaded (online.js stale): over everything, with a reload */
.olStale { position: fixed; top: 10px; left: 50%; transform: translateX(-50%); z-index: 60; display: flex; gap: 12px;
  align-items: center; padding: 8px 12px; background: var(--panel); border: 1px solid var(--gold); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5); }
.homeLink { color: var(--dim); font-size: 12px; }
.homeLink:hover { color: var(--gold); }
.homeTag { margin-top: 4px; color: var(--text); font-size: 15px; text-shadow: 0 1px 3px #000, 0 0 12px #000; }
.homeCard { width: min(560px, calc(100% - 32px)); flex: none; background: rgba(23, 21, 18, 0.94);
  border: 1px solid var(--line); border-radius: 10px; padding: 20px 24px; display: flex; flex-direction: column;
  gap: 12px; box-shadow: 0 12px 40px rgba(0, 0, 0, 0.55); }
.homeRow { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.homeBig { min-width: 170px; padding: 8px 14px; font-size: 14px; }
.homeLabel { min-width: 90px; }
.homeName, .homeCode { background: var(--panel2); color: var(--text); border: 1px solid var(--line); border-radius: 6px;
  padding: 5px 8px; font: inherit; }
.homeCode { width: 90px; text-transform: uppercase; }
.homeLine { color: var(--text); flex: 1 1 160px; }
/* an arena before its game (online.js drawMap: the public game's beside Play, a waiting game's in its bar) */
.homeMap { width: 120px; height: 120px; flex: none; }
.online .ol-map { width: 140px; height: 140px; }
/* the tutorial's card over the board (tutorial.js), and what its step is about, lit */
.tut { position: absolute; bottom: 10px; right: 10px; z-index: 16; width: min(320px, calc(100% - 20px));
  padding: 12px 14px; background: rgba(23, 21, 18, 0.95); border: 1px solid var(--gold); border-radius: 8px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5); font-size: 13px; }
.tut .tutN { color: var(--dim); font-size: 11px; letter-spacing: 1px; text-transform: uppercase; }
.tut .tutTitle { margin: 2px 0 6px; font-size: 16px; color: var(--gold); }
.tut .tutText { margin: 0 0 10px; line-height: 1.45; }
.tut .tutRow { display: flex; justify-content: flex-end; gap: 8px; }
.tutHi { outline: 2px solid var(--gold); outline-offset: 2px; animation: tutPulse 1.2s ease-in-out infinite; }
@keyframes tutPulse { 50% { outline-color: rgba(240, 198, 116, 0.25); } }
.online.waiting { right: auto; bottom: auto; left: 50%; top: 50%; transform: translate(-50%, -50%);
  flex-direction: column; flex-wrap: nowrap; max-height: calc(100% - 16px); overflow-y: auto; padding: 14px 18px;
  font-size: 14px; }
