* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #0d0f13;
  color: #dfe3ea;
  font: 13px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
  user-select: none;
}

#view {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  cursor: crosshair;
}

/* In-match panels, matched to the setup screen: the same dark glass, the same
   hairline, the same soft shadow — so the game does not change its look the
   moment a match begins. */
.panel {
  position: absolute;
  background: linear-gradient(180deg,
    rgba(22, 27, 35, 0.90), rgba(13, 16, 21, 0.90));
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 10px;
  padding: 10px 12px;
  backdrop-filter: blur(8px);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
  min-width: 210px;
}

/* A hairline of light along the top edge, which is what makes a dark panel
   read as a surface rather than a hole. */
.panel::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  border-radius: 10px 10px 0 0;
  background: linear-gradient(90deg,
    transparent, rgba(255, 255, 255, 0.16), transparent);
  pointer-events: none;
}

/* Hiding, for anything.

   Every rule that hid something used to name the one element it hid, which
   worked until a page put `hidden` on a plain wrapper: the administration
   panel and the signed-out half of the profile both carried the class and
   both stayed on screen. The gate was still a gate — the server refuses
   every one of those endpoints without the key — but the page said
   otherwise, and a lock that looks open is a bug even when it holds. */
.hidden { display: none; }
.panel.hidden { display: none; }

#resources { top: 12px; left: 12px; }
#hud       { top: 12px; right: 12px; }
#help      { bottom: 12px; left: 12px; opacity: 0.85; }
#build     { bottom: 12px; right: 12px; width: 240px; }

/* ---- minimap ---- */

#minimap-panel {
  top: 12px;
  left: 12px;
  min-width: 0;
  padding: 6px;
  line-height: 0;
}

/* Width and height are set in script: the canvas takes the map's aspect. */
#minimap {
  display: block;
  cursor: pointer;
  image-rendering: pixelated;
  border-radius: 4px;
}

/* The resource readout sits under the minimap; its top is set in script,
   since the minimap's height depends on the shape of the map. */
#resources { top: 224px; left: 12px; }

/* ---- skirmish setup ---- */

#setup {
  position: absolute;
  inset: 0;
  z-index: 10;
  display: grid;
  /* Two columns so the whole lobby fits one screen. Everything used to be one
     tall stack: the roster, then the map, then the button — which meant
     scrolling past the thing you were setting up to reach the thing that
     starts it. */
  grid-template-columns: minmax(420px, 1fr) minmax(360px, 1.1fr);
  grid-template-rows: auto 1fr auto;
  align-content: center;
  justify-content: center;
  gap: 10px 28px;
  padding: 20px 28px;
  overflow: hidden;
  background:
    radial-gradient(ellipse at 50% 8%, rgba(74, 143, 231, 0.10), transparent 60%),
    radial-gradient(ellipse at 50% 30%, #1a2028, #0b0d11 70%);
}

#setup.hidden { display: none; }

#setup .setup-head { grid-column: 1 / -1; text-align: center; }

#setup h1 {
  font-size: 34px;
  font-weight: 800;
  letter-spacing: 0.16em;
  background: linear-gradient(180deg, #eaf1fb, #93a7c2);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/*
 * The version, riding on the title. Everything here is undoing what the h1
 * does: the heading paints a gradient and clips it to the glyphs, so a child
 * inherits `color: transparent` and a background that is not its own, and
 * comes out as nothing at all.
 */
#setup h1 .version {
  background: none;
  -webkit-background-clip: border-box;
  background-clip: border-box;
  -webkit-text-fill-color: #7f8ea6;
  color: #7f8ea6;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  margin-left: 10px;
  vertical-align: 6px;
}

.setup-sub {
  color: #8b93a3;
  font-size: 13px;
  letter-spacing: 0.04em;
}

.setup-left, .setup-right {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 0;
}

.setup-foot {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}

.setup-options { display: flex; gap: 8px; flex-wrap: wrap; }

.setup-row { width: 100%; }

.setup-label {
  font-size: 11px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: #7c8698;
  margin-bottom: 5px;
}

/* ---- lobby slot table ---- */

.slot-table {
  width: 100%;
  /* Twenty rows would push the map and the start button off the screen, so the
     list scrolls. `flex: none` is what makes that safe: giving a flex child
     its own overflow sets min-height to 0, and the column then crushes it to
     nothing the moment the page is taller than the viewport — which is how the
     lobby ended up showing its header and no players at all. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-right: 4px;
}

.slot-table::-webkit-scrollbar { width: 8px; }
.slot-table::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.14);
  border-radius: 4px;
}

.slot-row {
  display: grid;
  grid-template-columns: 24px 118px 44px 104px 104px 1fr;
  gap: 8px;
  align-items: center;
  padding: 5px 8px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.06);
}

.slot-row:not(.head):hover { background: rgba(255, 255, 255, 0.06); }

.slot-row.head {
  background: none;
  border-color: transparent;
  padding-bottom: 2px;
  font-size: 10px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: #7c8698;
  position: sticky;
  top: 0;
  backdrop-filter: blur(2px);
}

.slot-row.off { opacity: 0.4; }

.slot-index {
  font-size: 11px;
  color: #6f7788;
  text-align: center;
}

/* ---- colour and team controls ---- */

.swatch-btn, .team-btn, .faction-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 7px;
  font: inherit;
  font-size: 12px;
  color: #cfd6e2;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 5px;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
}
.swatch-btn { justify-content: center; padding: 4px; }
.swatch-btn:hover:not(:disabled),
.team-btn:hover:not(:disabled),
.faction-btn:hover:not(:disabled) { border-color: rgba(255, 255, 255, 0.34); }
.swatch-btn:disabled, .team-btn:disabled, .faction-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.swatch {
  width: 16px;
  height: 16px;
  border-radius: 4px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.45);
  flex: none;
}
.swatch.small { width: 11px; height: 11px; border-radius: 3px; }

/* Our own dropdown. The browser's is drawn by the operating system and comes
   up as a pale sheet with pale text on this theme — unreadable, and nothing
   like the rest of the game. */
.popup-menu {
  position: fixed;
  z-index: 100;
  max-height: 320px;
  overflow-y: auto;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: #141922;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 7px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.6);
}

.popup-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 6px 8px;
  font: inherit;
  font-size: 12px;
  color: #dbe2ee;
  background: none;
  border: 0;
  border-radius: 5px;
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
}
.popup-item:hover { background: rgba(255, 255, 255, 0.10); }
.popup-item.on { background: rgba(74, 143, 231, 0.22); color: #fff; }

.popup-dot {
  width: 13px;
  height: 13px;
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.45);
  flex: none;
}

.seg { display: flex; gap: 4px; }

.seg-btn {
  flex: 1;
  padding: 5px 6px;
  font-size: 12px;
  white-space: nowrap;
}

.seg-btn.on { background: #35608f; border-color: #4a86c8; color: #fff; }
.seg-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.team-seg .seg-btn { flex: 0 0 28px; padding: 5px 0; text-align: center; }

.setup-warn {
  width: min(760px, 100%);
  min-height: 18px;
  font-size: 12px;
  color: #ffb454;
}

/* ---- lobby map ---- */

/* The lobby map fits the space it is given, in BOTH directions.
   Boards are different shapes — the world is wide and short, South America is
   nearly square — so constraining the width alone makes a tall board tall
   enough to push everything else off the screen. Two maxima with automatic
   width and height is the one combination that scales a canvas down into a box
   while keeping its proportions. */
.map-picker {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  margin: 2px 0;
}

.map-picker-canvas {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  min-height: 0;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  image-rendering: pixelated;
  background: #0b0d11;
}

.map-picker-hint {
  font-size: 12px;
  color: #8b93a3;
  min-height: 16px;
  text-align: center;
}

.team-select,
.region-select {
  padding: 5px 6px;
  font: inherit;
  font-size: 12px;
  color: #cfd6e2;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 5px;
  max-width: 100%;
}

/* Where a slot starts. A button rather than a list, because the choice is a
   place on the map and no list can hold 65,000 tiles. The armed one is lit:
   it is the slot the next click on the map places. */
.start-btn {
  padding: 5px 6px;
  font: inherit;
  font-size: 12px;
  color: #cfd6e2;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 5px;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}
.start-btn:hover:not(:disabled) { border-color: rgba(255, 255, 255, 0.35); }
.start-btn.arming {
  border-color: #6ea8ff;
  color: #dce8ff;
  background: rgba(110, 168, 255, 0.16);
  box-shadow: 0 0 0 1px rgba(110, 168, 255, 0.3);
}
.start-btn:disabled { opacity: 0.4; cursor: default; }

.team-select:disabled,
.region-select:disabled { opacity: 0.4; }
.region-line { margin: -2px 0 4px 14px; opacity: 0.8; }

/* The room panel is narrow, so its copy of the map scales to fit rather than
   pushing the panel out to the map's natural width. */

.seed-row { display: flex; align-items: center; gap: 10px; }
.seed-row .setup-label { margin-bottom: 0; }

.small-btn {
  padding: 6px 12px;
  font-size: 12px;
  border-radius: 6px;
  transition: background 120ms ease, border-color 120ms ease;
}

#start-btn:disabled {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.12);
  color: #6f7788;
  cursor: not-allowed;
}

.seed-input {
  width: 180px;
  padding: 7px 9px;
  font: inherit;
  color: #cfd6e2;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 5px;
}

#start-btn {
  margin-top: 6px;
  padding: 11px 34px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #fff;
  background: #35608f;
  border-color: #4a86c8;
}

#start-btn:hover { background: #427099; }

/* ---- online ---- */

.online-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.online-row .setup-label { margin-bottom: 0; }
.code-input { width: 190px; text-transform: uppercase; }
.online-status { font-size: 12px; color: #8fd4a8; }




/* ---- online room table ---- */





.room-row.off { opacity: 0.5; }
.room-who { font-size: 13px; }

/* Transient one-liners: why an order did nothing. Sits above the build panel
   so it never covers the thing the player just clicked. */
#toast {
  position: absolute;
  bottom: 96px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 12;
  padding: 8px 14px;
  border-radius: 6px;
  font-size: 13px;
  color: #f2f5f9;
  background: rgba(20, 24, 30, 0.92);
  border: 1px solid rgba(255, 214, 140, 0.5);
  pointer-events: none;
}

#toast.hidden { display: none; }

#netstatus {
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9;
  padding: 6px 14px;
  border-radius: 6px;
  background: rgba(16, 19, 24, 0.9);
  border: 1px solid rgba(255, 255, 255, 0.12);
  font-size: 13px;
  color: #ffb454;
}

#netstatus.hidden { display: none; }
#netstatus.bad { color: #ff7a6d; border-color: #a33; }

/* ---- match result ---- */

/* The end screen ignores the mouse so the result does not sit on top of a map
   the player may still want to look at — but anything they are meant to CLICK
   has to take it back. The New game button spent its whole life unclickable
   for want of this one line. */
#result {
  position: absolute;
  top: 32%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  pointer-events: none;
}

#result .result-buttons,
#result .score { pointer-events: auto; }
#result .result-buttons {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-top: 14px;
}
#result .result-buttons .small-btn {
  padding: 9px 22px;
  font-size: 14px;
}

#result.hidden { display: none; }

#result-title {
  font-size: 56px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-shadow: 0 4px 24px rgba(0, 0, 0, 0.8);
}

#result-title.win { color: #6fe08a; }
#result-title.lose { color: #ff7a6d; }

#result-sub {
  margin-top: 6px;
  font-size: 14px;
  color: #c3cad6;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.9);
}

.row, .res {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 1px 0;
}

.row span, .res span { color: #8b93a3; }
.row b, .res b { font-weight: 600; }
.mono { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; }

.res b { font-size: 15px; }
.res b.warn { color: #ffb454; }

.buttons { display: flex; gap: 6px; margin-top: 8px; }

button {
  padding: 5px 8px;
  font: inherit;
  font-size: 12px;
  color: #cfd6e2;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 5px;
  cursor: pointer;
}

.buttons button { flex: 1; }
button:hover:not(:disabled) { background: rgba(255, 255, 255, 0.12); }
button.on { background: #35608f; border-color: #4a86c8; color: #fff; }

/* ---- build / production panel ---- */

.panel-title {
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: #7c8698;
  margin-bottom: 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}

.panel-hint {
  margin-top: 8px;
  font-size: 11px;
  color: #6f7788;
  line-height: 1.35;
}

.build-grid { display: grid; gap: 5px; }

.build-btn {
  position: relative;
  display: grid;
  grid-template-columns: 30px 1fr auto auto;
  gap: 8px;
  align-items: center;
  text-align: left;
  padding: 7px 9px;
  overflow: hidden;
}

.build-btn .bi { display: block; width: 30px; height: 30px; }
.build-btn .bn { font-weight: 600; }
.build-btn .bc { color: #8fd4a8; font-size: 11px; }
.build-btn .bt { color: #7a8294; font-size: 11px; }

.build-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.build-btn.active { border-color: #4a86c8; background: rgba(74, 134, 200, 0.22); }

/* Fills left to right as the item at the head of the queue completes. */
.build-btn .bfill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: rgba(90, 190, 255, 0.18);
  pointer-events: none;
  transition: width 120ms linear;
}

/*
 * A tray that is always there, at a height that never changes.
 *
 * The panel is anchored to the bottom of the screen, so anything that grows
 * inside it pushes the buttons UPWARD — and a player queueing five units
 * clicks the same button five times in a row. An auto-sized queue is empty for
 * the first click and 34px tall for the second, so the button the player is
 * still clicking has moved out from under the cursor. The empty tray costs one
 * row of space and makes the panel hold still.
 */
.queue {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 4px;
  margin-top: 8px;
  height: 40px;
  padding: 3px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 7px;
  background: rgba(0, 0, 0, 0.22);
}

/* One chip per kind of unit queued: the drawing, how many, and the seconds
   left on the one being built. Names were unreadable past three items and
   told the player nothing the picture does not. */
.queue-chip {
  position: relative;
  width: 34px;
  height: 34px;
  padding: 0;
  display: grid;
  place-items: center;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.05);
  cursor: pointer;
}
.queue-chip:hover { border-color: #e2574c; }
.queue-chip.building { border-color: rgba(110, 168, 255, 0.7); }
.queue-chip .qi { grid-area: 1 / 1; opacity: 0.95; }
.queue-chip .qn {
  grid-area: 1 / 1;
  align-self: end;
  justify-self: end;
  font-size: 10px;
  font-weight: 700;
  color: #f2f5f9;
  text-shadow: 0 0 3px #000, 0 0 3px #000;
  padding: 0 2px;
}
.queue-chip .qt {
  grid-area: 1 / 1;
  align-self: start;
  justify-self: start;
  font-size: 9px;
  color: #9cc8ff;
  text-shadow: 0 0 3px #000, 0 0 3px #000;
  padding: 0 2px;
}

/* ---- settings ---- */

#settings {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 14;
  width: min(360px, calc(100vw - 24px));
}

#settings.hidden { display: none; }

.set-row {
  display: grid;
  grid-template-columns: 64px 1fr 72px;
  gap: 8px;
  align-items: center;
  margin: 6px 0;
  font-size: 13px;
}

.set-row input[type="range"] { width: 100%; }
#settings .set-row .small-btn { margin: 0; width: 100%; }
/* The speed row spans the slider column and the button column: five rates do
   not fit in the 72px a Mute button lives in. */
.set-speeds {
  grid-column: 2 / span 2;
  display: flex;
  gap: 4px;
}
#settings .set-speeds .small-btn { flex: 1; margin: 0; padding: 3px 0; min-width: 0; }
.set-quality {
  grid-column: 2 / span 2;
  display: flex;
  gap: 4px;
}
#settings .set-quality .small-btn { flex: 1; margin: 0; padding: 3px 0; min-width: 0; }
.set-quality-note { margin: -2px 0 6px 72px; font-style: italic; }
#settings .set-speeds .small-btn:disabled { opacity: 0.4; }
.set-speed-note { margin: -2px 0 6px 72px; font-style: italic; }

.set-buttons { display: flex; gap: 6px; margin-top: 10px; }
.set-buttons .small-btn { flex: 1; }
.set-now-playing { margin: -2px 0 6px 72px; font-style: italic; }
.set-status { min-height: 16px; margin-top: 6px; color: #ffd68c; }

#vote-prompt {
  top: 18%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 15;
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: min(320px, calc(100vw - 24px));
}

/* ---- end-of-match scoreboard ---- */

.score {
  border-collapse: collapse;
  margin: 14px auto 10px;
  font-size: 13px;
  min-width: 340px;
}

.score th {
  text-align: right;
  padding: 3px 10px;
  color: #8b93a3;
  font-weight: 600;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

.score th:first-child, .score td:first-child { text-align: left; }
.score td { padding: 3px 10px; color: #cfd6e2; text-align: right; }
.score tr.me td { color: #fff; font-weight: 600; }

.score .dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin-right: 7px;
  vertical-align: middle;
}

/* ---- the primer ---- */

#primer {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 13;
  width: min(520px, calc(100vw - 24px));
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  line-height: 1.5;
}

#primer.hidden { display: none; }
.primer-row { margin: 9px 0; font-size: 13px; color: #cfd6e2; }
.primer-row b { color: #f2f5f9; }
.primer-hint { margin-top: 12px; font-size: 12px; color: #8b93a3; }
#primer .small-btn { margin-top: 10px; width: 100%; }

/* Selling a building. Red-tinted because it is money for something you paid
   more for, and because it cannot be undone. */
.sell-row { margin-top: 8px; }
.sell-btn {
  width: 100%;
  border-color: rgba(226, 87, 76, 0.45);
  color: #ffb0a8;
  background: rgba(226, 87, 76, 0.10);
}
.sell-btn:hover {
  border-color: #e2574c;
  background: rgba(226, 87, 76, 0.22);
}
/* Waiting for the second press. Loud on purpose: the next click is final. */
.sell-btn.armed {
  border-color: #e2574c;
  color: #fff1ef;
  background: rgba(226, 87, 76, 0.38);
  box-shadow: 0 0 0 1px rgba(226, 87, 76, 0.5);
}

/* Replay transport controls. Only present while watching a recording. */
#replay-bar {
  position: absolute;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 10px;
  border-radius: 8px;
  background: rgba(11, 13, 17, 0.88);
  border: 1px solid rgba(255, 255, 255, 0.12);
  z-index: 6;
}
#replay-bar .small-btn { margin: 0; padding: 4px 9px; }
#replay-bar .speed-btn.on {
  border-color: #6ea8ff;
  color: #dce8ff;
  background: rgba(110, 168, 255, 0.18);
}
.replay-scrub { width: 260px; accent-color: #6ea8ff; }
.replay-clock {
  font-size: 12px;
  color: #9aa3b2;
  font-variant-numeric: tabular-nums;
  min-width: 84px;
}
#replay-bar.finished .replay-scrub { opacity: 0.4; }

/* The offer to come back after a dropped connection. */
#reconnect {
  position: absolute;
  left: 50%;
  top: 40%;
  transform: translate(-50%, -50%);
  max-width: 380px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 20;
}
#reconnect .small-btn { width: 100%; margin: 0; }

/* The online and saved-match rows sit inside the two columns now, so they get
   a compact inline layout rather than a full-width band. */
.online-row, .seed-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.online-row .setup-label, .seed-row .setup-label {
  width: 100%;
  margin-bottom: 2px;
}
.online-row .seed-input { flex: 1 1 120px; min-width: 0; }
.seed-row input[type=file] { flex: 1 1 160px; min-width: 0; font-size: 11px; }

#start-btn {
  padding: 12px 40px;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.06em;
}

.small-btn.toggle.on {
  border-color: #6ea8ff;
  color: #dce8ff;
  background: rgba(110, 168, 255, 0.18);
}



/* Narrow windows get one column back. The two-column lobby needs about 820px;
   below that the roster and the map stack, and the page scrolls again — which
   is the right trade when there is genuinely not enough room. */
@media (max-width: 900px) {
  #setup {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto auto;
    overflow: auto;
    justify-content: stretch;
    padding: 16px;
  }
  .slot-table { max-height: 40vh; flex: none; }
}

/* Short windows: the roster gives up height before anything else does. */
@media (max-height: 700px) {
  #setup h1 { font-size: 26px; }
  #setup { padding: 12px 20px; gap: 8px 22px; }
}

/* ---- the online room, inside the setup screen ---- */




.room-code {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
  padding: 6px 12px;
  border-radius: 8px;
  background: rgba(74, 143, 231, 0.12);
  border: 1px solid rgba(110, 168, 255, 0.35);
}
.room-code span {
  font-size: 11px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: #9fb4d0;
}
.room-code b {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 0.22em;
  color: #dce8ff;
}




.room-who { font-size: 12px; color: #cfd6e2; }

.small-btn.primary {
  border-color: rgba(110, 168, 255, 0.5);
  color: #dce8ff;
  background: rgba(110, 168, 255, 0.16);
}
.small-btn.primary:hover:not(:disabled) { background: rgba(110, 168, 255, 0.26); }

/* ---- in-match polish, to the same standard as the setup screen ---- */

/* The build list reads as a row of cards rather than a stack of form
   controls: a picture, a name, a price, a time. */
.build-btn {
  border-radius: 7px;
  transition: background 120ms ease, border-color 120ms ease;
}
.build-btn:hover:not(:disabled) {
  border-color: rgba(110, 168, 255, 0.45);
  background: rgba(110, 168, 255, 0.10);
}
.build-btn.active {
  border-color: #6ea8ff;
  background: rgba(110, 168, 255, 0.20);
}
/* The progress fill sits under the label rather than over it. */
.build-btn .bfill {
  position: absolute;
  inset: 0 auto 0 0;
  background: rgba(110, 168, 255, 0.16);
  pointer-events: none;
  transition: width 120ms linear;
}
.build-btn > :not(.bfill) { position: relative; }

/* Resource readout: the numbers are the point, so they get the weight. */
.res {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 14px;
  padding: 2px 0;
}
.res span {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #7c8698;
}
.res b {
  font-variant-numeric: tabular-nums;
  color: #eaf1fb;
}

/* HUD figures line up in a column instead of drifting with their labels. */
#hud .row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 12px;
  padding: 1px 0;
}
#hud .row span { color: #7c8698; }
#hud .row b { font-variant-numeric: tabular-nums; color: #dbe2ee; }

/* Settings, matched to the popup menus in the lobby. */
#settings {
  border-radius: 10px;
}
#settings .panel-title { margin-bottom: 10px; }
.set-buttons { display: flex; gap: 8px; margin-top: 8px; }

/* The toast, and the connection banner, in the same visual family. */
#toast {
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  background: rgba(16, 19, 24, 0.92);
  backdrop-filter: blur(6px);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5);
}

#result-title {
  background: linear-gradient(180deg, #ffffff, #b9c8dd);
  -webkit-background-clip: text;
  background-clip: text;
}
#result-title.win {
  background: linear-gradient(180deg, #b8ffcf, #4fbf7a);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
#result-title.lose {
  background: linear-gradient(180deg, #ffc4bd, #d95c4e);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.room-code.hidden { display: none; }

/* Your own row in an online lobby, so you can find yourself at a glance. */
.slot-row.me {
  border-color: rgba(110, 168, 255, 0.40);
  background: rgba(110, 168, 255, 0.08);
}

/* A human's name where the You/Bot buttons would be. */
.room-who {
  font-size: 12px;
  color: #cfd6e2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- the games page ------------------------------------------------------ */
/* Its own layout rather than the lobby's: this page is a list and a form, and
   neither wants the lobby's fixed, canvas-sized furniture. */
/* THE DOCUMENT SCROLLS, NOT THE BODY.

   `html, body { height: 100%; overflow: hidden }` is right for the game:
   the match fills the window and nothing scrolls. On a page of text it is
   quietly wrong, and only half of it was ever undone — body became
   scrollable while html stayed a fixed-height box with the scrollbar
   inside it.

   A page scrolled that way is not scrolled as far as the browser is
   concerned: window.scrollY reads 0, and the scroll anchoring that keeps
   your place when something above you grows does not apply. Adding a
   wallet made every panel below it jump, because nothing was holding the
   page still. `<html class="doc">` marks the pages that are documents. */
html.doc, html.doc body {
  height: auto;
  min-height: 100%;
  overflow: visible;
}

body.browser-page {
  position: static;
  background: #0e1116;
}

#browser {
  max-width: 980px;
  margin: 0 auto;
  padding: 28px 20px 60px;
}

.browser-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}

.browser-head h1 {
  margin: 0 0 4px;
  font-size: 30px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: #dfe6f2;
}

.browser-sub { color: #7f8ea6; font-size: 13px; max-width: 52ch; }
.browser-actions { display: flex; gap: 8px; flex: none; }

.browser-columns {
  display: grid;
  /* minmax(0, 1fr), not 1fr: a `1fr` track will not shrink below the
     widest unbreakable thing inside it, so one long email address in the
     accounts list was enough to push the whole page sideways. */
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 16px;
  align-items: start;
}

/* THE PANELS ON THESE PAGES STACK, THEY DO NOT FLOAT.

   `.panel` is `position: absolute` because in a match it is furniture
   pinned to a corner of the canvas. On a document page that is exactly
   wrong: every panel takes itself out of the flow and lands in the same
   place, one on top of the next.

   This used to be fixed by naming the two classes the games page happened
   to use, which is why the profile and administration pages — written
   later, with plain `.panel` — came out as a pile. So it is written once,
   for the page, and any panel added to any of these pages is covered.

   `relative`, not `static`: the hairline along the top edge is an absolute
   ::before with `inset: 0 0 auto 0`, and with no positioned ancestor it
   measures itself against the page instead of its own panel. */
body.browser-page .panel { position: relative; }
.browser-list, .browser-account { padding: 14px 16px; }

.game-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 12px;
  align-items: center;
  padding: 10px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.game-row:first-of-type { border-top: 0; }

.game-title { color: #dfe6f2; font-size: 14px; }
.game-host, .game-facts { color: #7f8ea6; font-size: 12px; }

.browser-account .seed-input { width: 100%; margin: 6px 0 0; }
.browser-account .small-btn { width: 100%; margin-top: 8px; }
.browser-account .seg { display: flex; }
.browser-account .seg-btn { flex: 1; }
.account-who { color: #dfe6f2; font-size: 16px; margin-top: 6px; }
.account-coins { color: #e8c477; font-size: 13px; margin: 8px 0 4px; }
.account-problem { color: #e2574c; font-size: 12px; min-height: 16px; margin-top: 8px; }

@media (max-width: 760px) {
  .browser-columns { grid-template-columns: 1fr; }
  .game-row { grid-template-columns: 1fr auto; }
  .game-facts { grid-column: 1 / -1; }
}

/* The stake, beside the room code. Read before you agree to it. */
.stake-row .stake-input {
  width: 90px;
  margin: 0 8px 0 0;
  text-align: right;
}
.stake-note { color: #e8c477; font-size: 12px; }
.stake-note.stake-warning { color: #e2574c; }

/* --- administration ------------------------------------------------------ */
/* The administration section sits at the bottom of the operator's own
   profile, so it needs a line saying where the page stops being about your
   coins and starts being about everybody's. */
.admin-line {
  margin: 26px 0 12px;
  padding-top: 18px;
  border-top: 1px solid rgba(226, 87, 76, 0.35);
  color: #e2574c;
  font-size: 12px;
  letter-spacing: 2px;
  text-transform: uppercase;
}
.admin-expiry {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: -6px 0 16px;
  color: #7f8ea6;
  font-size: 12px;
}
.admin-gate { max-width: 420px; }
.admin-gate .seed-input, .admin-gate .small-btn { width: 100%; margin-top: 8px; }
#panel > .panel, #panel > .browser-columns,
#admin-panel > .panel, #admin-panel > .browser-columns { margin-bottom: 16px; }
.admin-totals { padding: 14px 16px; }
.admin-figures { color: #dfe6f2; font-size: 14px; margin-bottom: 4px; }
.admin-entry .game-title { color: #e8c477; }
#panel .panel .seed-input,
#admin-panel .panel .seed-input { width: 100%; margin-bottom: 8px; }
#admin-panel .game-row { grid-template-columns: 80px 1fr 1fr auto auto; }
#accounts .game-row { grid-template-columns: 1fr 1.4fr auto auto; }
#a-ledger .game-row { grid-template-columns: 80px 1fr 1fr auto auto; }

/* The queue rows carry seven things, including a transaction hash, and no
   phone is that wide. They scroll inside their own box rather than making
   the whole page scroll sideways — a page that slides under your thumb
   because one table is too wide is a page nobody can read. */
/* The published wallets, in the narrow right-hand column. Four cells with a
   34-character address among them, so the address column must be allowed to
   shrink and the address itself to break. */
/* The house's cut. */
.rake-set { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.rake-set .seed-input { width: 170px !important; margin-bottom: 0 !important; }
#admin-panel .rake-row {
  grid-template-columns: 70px 70px 1fr 90px 1fr auto;
  min-width: 620px;
}
#rake-history .rake-row { grid-template-columns: 60px 1fr 1fr 1fr auto; }
#rake-entries, #rake-history { overflow-x: auto; min-width: 0; }
#rake-entries .rake-row div:first-child { color: #4bbf73; }

/* A published wallet, in the narrow right-hand column: what it is and the
   address underneath, with the button beside them. Columns were tried and
   do not fit — an address that may break anywhere, in a track squeezed to
   nothing, breaks into one character per line, forty lines tall. */
.method-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: start;
  padding: 12px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.method-row:first-child { border-top: 0; }
.method-kind { color: #7f8ea6; font-size: 12px; }
.method-address {
  color: #dfe6f2;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 12.5px;
  line-height: 1.45;
  overflow-wrap: anywhere;
  user-select: text;      /* it exists to be copied */
  margin: 2px 0;
}
.method-label { color: #7f8ea6; font-size: 12px; }
.method-remove { align-self: start; }

/* Fourteen days with nothing in them. */
.chart.chart-empty { opacity: 0.55; }
.chart-days { gap: 8px; }
.chart-days span:nth-child(2) { color: #6b7688; font-style: italic; }

#accounts, #queue-deposits, #queue-withdrawals, #recent, #a-ledger {
  overflow-x: auto;
  min-width: 0;
}

/* The account button, top right, and the window it opens. */
.account-corner {
  position: absolute;
  top: 16px;
  right: 20px;
  z-index: 8;
  display: flex;
  align-items: center;
  gap: 8px;
}
.account-button { margin: 0; }

/* The mute button, beside the account. Square, so it reads as an icon
   rather than as a word somebody has to stop and read. */
.mute-btn {
  margin: 0;
  width: 34px;
  padding: 6px 0;
  font-size: 14px;
  line-height: 1;
  text-align: center;
}
.mute-btn.is-muted {
  color: #e2574c;
  border-color: rgba(226, 87, 76, 0.45);
  background: rgba(226, 87, 76, 0.12);
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(6, 8, 12, 0.72);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 40;
}
.modal-backdrop.hidden { display: none; }

.modal {
  position: relative;
  width: 320px;
  max-width: calc(100vw - 32px);
  padding: 18px 20px 16px;
}
.modal .seed-input { width: 100%; margin: 8px 0 0; }
.modal .small-btn { width: 100%; margin-top: 10px; }
.modal .seg { display: flex; margin-bottom: 4px; }
.modal .seg-btn { flex: 1; }
.modal .account-who { color: #dfe6f2; font-size: 18px; margin-top: 6px; }
.modal .account-coins { margin: 6px 0 0; }
.modal .account-problem { min-height: 0; }
.modal .panel-hint { margin-top: 12px; }
.modal-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 26px !important;
  margin: 0 !important;
  padding: 0 !important;
  line-height: 1;
  font-size: 16px;
}

/* What a listed game costs to enter. */
.game-stake { color: #e8c477; }

/* A quiet link inside a form: the way out of a forgotten password. */
.link-btn {
  display: block;
  margin-top: 10px;
  padding: 0;
  border: 0;
  background: none;
  color: #6ea8ff;
  font: inherit;
  font-size: 12px;
  text-align: left;
  cursor: pointer;
}
.link-btn:hover { text-decoration: underline; }
.link-btn:disabled { opacity: 0.5; cursor: default; text-decoration: none; }
/* The same slot says both "that went wrong" and "that worked". */
.account-problem.is-note { color: #7f8ea6; }

/* Waiting on a confirmed address. Amber, not red: nothing is broken, it
   is simply not finished. */
.browser-page .panel.unverified {
  border-color: rgba(232, 196, 119, 0.4);
  background: linear-gradient(180deg,
    rgba(232, 196, 119, 0.10), rgba(232, 196, 119, 0.03));
}
.browser-page .panel.unverified .panel-title { color: #e8c477; }
#verify-said { margin-left: 10px; }

/* --- the document pages, dressed --------------------------------------- */
/*
   The lobby's furniture is small, dense and pinned to the edges of a
   canvas, because it is competing with a battle for attention. A page
   about somebody's money is the opposite: it is the only thing on the
   screen, it is read rather than glanced at, and it should look like it
   is worth trusting with a bank transfer.

   So the shared controls are given room here and nowhere else. The game
   is untouched.
*/
html.doc { color-scheme: dark; }

body.browser-page {
  --ink:        #e7edf7;
  --ink-dim:    #8b98ad;
  --ink-faint:  #6b7688;
  --line:       rgba(255, 255, 255, 0.09);
  --line-soft:  rgba(255, 255, 255, 0.055);
  --surface:    rgba(255, 255, 255, 0.028);
  --raised:     rgba(255, 255, 255, 0.055);
  --gold:       #e8c477;
  --green:      #58c98a;
  --red:        #ec6a5f;
  --blue:       #6ea8ff;
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  background:
    radial-gradient(1100px 620px at 15% -8%, rgba(110, 168, 255, 0.10), transparent 60%),
    radial-gradient(900px 520px at 92% 0%, rgba(232, 196, 119, 0.06), transparent 55%),
    #0b0e13;
  background-attachment: fixed;
}

.browser-page #browser { max-width: 1060px; padding: 40px 24px 90px; }

.browser-page .browser-head {
  align-items: center;
  margin-bottom: 28px;
}
.browser-page .browser-head h1 {
  font-size: 26px;
  letter-spacing: 0.14em;
  color: var(--ink);
}
.browser-page .browser-sub { font-size: 13px; color: var(--ink-dim); }

/* Panels: fewer, quieter lines and more air inside them. */
.browser-page .panel {
  padding: 20px 22px;
  border-radius: 16px;
  border-color: var(--line);
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.015));
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05) inset,
              0 18px 40px -24px rgba(0, 0, 0, 0.9);
  backdrop-filter: none;
}
.browser-page .panel::before { border-radius: 16px 16px 0 0; }

.browser-page .panel-title {
  font-size: 12px;
  letter-spacing: 0.16em;
  color: var(--ink-dim);
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line-soft);
}
.browser-page .panel-hint {
  font-size: 12.5px;
  color: var(--ink-faint);
  line-height: 1.5;
  margin-top: 0;
}
.browser-page .panel-hint + .seed-input,
.browser-page .panel-hint + .rake-set { margin-top: 14px; }

/* Controls with something to press. */
.browser-page .seed-input {
  padding: 11px 13px;
  font-size: 13.5px;
  color: var(--ink);
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--line);
  border-radius: 10px;
  transition: border-color 120ms ease, background 120ms ease;
}
.browser-page .seed-input::placeholder { color: var(--ink-faint); }
.browser-page .seed-input:hover { border-color: rgba(255, 255, 255, 0.16); }
.browser-page .seed-input:focus {
  outline: none;
  border-color: rgba(110, 168, 255, 0.65);
  background: rgba(110, 168, 255, 0.07);
  box-shadow: 0 0 0 3px rgba(110, 168, 255, 0.14);
}

.browser-page .small-btn {
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  border-radius: 10px;
  background: var(--raised);
  border: 1px solid var(--line);
  color: var(--ink);
}
.browser-page .small-btn:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.2);
}
.browser-page .small-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.browser-page .small-btn.primary {
  background: linear-gradient(180deg, #4d8de0, #3d72bd);
  border-color: rgba(255, 255, 255, 0.14);
  color: #f2f7ff;
}
.browser-page .small-btn.primary:hover:not(:disabled) {
  background: linear-gradient(180deg, #5a99e8, #4880ca);
}

/* The balance, as the first thing on the page. */
.browser-page .balance-panel {
  padding: 26px 26px 24px;
  background:
    radial-gradient(520px 200px at 0% 0%, rgba(232, 196, 119, 0.13), transparent 70%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.015));
}
.browser-page .balance-panel .account-coins {
  font-size: 42px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.1;
  color: var(--gold);
  margin: 0;
}

/* A row of figures: the shape a report wants. */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
  margin: 4px 0 16px;
}
.stat {
  padding: 13px 15px;
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  background: var(--surface);
}
.stat-value {
  font-size: 21px;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.25;
}
.stat-value.good { color: var(--green); }
.stat-value.gold { color: var(--gold); }
.stat-label {
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: 3px;
}
.stat-note { font-size: 11.5px; color: var(--ink-dim); margin-top: 2px; }

/* Fourteen days of takings. Bars rather than a line: the question is
   "how much on each day", not "what is the trend". */
.chart {
  display: grid;
  grid-template-columns: repeat(14, 1fr);
  align-items: end;
  gap: 5px;
  height: 92px;
  margin: 6px 0 4px;
  padding: 10px 12px 0;
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  background: var(--surface);
}
.chart-bar {
  min-height: 2px;
  border-radius: 4px 4px 2px 2px;
  background: linear-gradient(180deg, var(--gold), rgba(232, 196, 119, 0.35));
}
.chart-bar.empty { background: rgba(255, 255, 255, 0.07); }
.chart-days {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--ink-faint);
  padding: 0 2px;
}

/* A state is a chip, not a coloured word. */
.pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  border: 1px solid transparent;
  white-space: nowrap;
}
.pill.state-pending {
  color: var(--gold);
  background: rgba(232, 196, 119, 0.13);
  border-color: rgba(232, 196, 119, 0.28);
}
.pill.state-approved, .pill.state-paid {
  color: var(--green);
  background: rgba(88, 201, 138, 0.13);
  border-color: rgba(88, 201, 138, 0.3);
}
.pill.state-rejected, .pill.state-refused {
  color: var(--red);
  background: rgba(236, 106, 95, 0.13);
  border-color: rgba(236, 106, 95, 0.3);
}

.browser-page .list-title {
  margin: 20px 0 4px;
  color: var(--ink-faint);
  letter-spacing: 0.14em;
}
.browser-page .money-row { padding: 12px 0; border-top-color: var(--line-soft); }
.browser-page .money-main { font-size: 14px; color: var(--ink); }
.browser-page .money-sub { font-size: 12px; color: var(--ink-faint); }
.browser-page .pay-row { padding: 12px 0; border-top-color: var(--line-soft); }
.browser-page .pay-kind { font-size: 12px; color: var(--ink-dim); }
.browser-page .pay-address { font-size: 13px; color: var(--ink); }
.browser-page .game-row {
  padding: 11px 8px;
  border-top-color: var(--line-soft);
  border-radius: 8px;
}
.browser-page .game-row:hover { background: rgba(255, 255, 255, 0.03); }

.browser-page .message {
  padding: 12px 14px;
  border-radius: 12px;
  font-size: 13.5px;
  border: 1px solid var(--line-soft);
}
.browser-page .message.from-admin {
  background: rgba(110, 168, 255, 0.11);
  border-color: rgba(110, 168, 255, 0.22);
}
.browser-page .message-list { max-height: 320px; }

.browser-page .account-problem { font-size: 12.5px; }

/* Where the page stops being about your coins. */
.browser-page .admin-line {
  margin: 40px 0 16px;
  padding-top: 24px;
  font-size: 12px;
  letter-spacing: 0.18em;
}

@media (max-width: 720px) {
  .browser-page #browser { padding: 24px 14px 60px; }
  .browser-page .panel { padding: 16px 15px; border-radius: 14px; }
  .browser-page .browser-head h1 { font-size: 21px; }
  .browser-page .balance-panel .account-coins { font-size: 34px; }
  .chart { grid-template-columns: repeat(14, 1fr); gap: 3px; }
}

/* --- profile and the money queue ----------------------------------------- */
.balance-panel { padding: 14px 16px; }
.balance-panel .account-coins { font-size: 26px; margin: 0; }
/* A place to send money to. `minmax(0, 1fr)` rather than `1fr`, because a
   plain `1fr` will not shrink a column below the width of its longest
   unbreakable word — and a 34-character wallet address is one long word,
   which is how the label after it ended up off the edge of the panel. */
.pay-row {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: 4px 12px;
  align-items: baseline;
  padding: 8px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.pay-row:first-child { border-top: 0; }
.pay-kind { color: #7f8ea6; font-size: 12px; }
.pay-address {
  color: #dfe6f2;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 12.5px;
  overflow-wrap: anywhere;
  user-select: text;      /* it exists to be copied */
}
.pay-label {
  grid-column: 2;
  color: #7f8ea6;
  font-size: 12px;
}

/* A heading for the list under a form, so three lines of numbers are not
   left to explain themselves. */
.list-title {
  color: #7f8ea6;
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  margin: 14px 0 2px;
}

/* One deposit, withdrawal or ledger entry: the fact on the first line,
   the small print on the second. */
.money-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 10px;
  padding: 9px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.money-row:first-child { border-top: 0; }
.money-main { color: #dfe6f2; font-size: 13.5px; }
.money-side { font-size: 12px; text-align: right; white-space: nowrap; }
.money-sub {
  grid-column: 1 / -1;
  color: #7f8ea6;
  font-size: 11.5px;
  overflow-wrap: anywhere;
}
#admin-panel .queue-row {
  grid-template-columns: 150px 110px 1fr 1fr auto auto auto;
  min-width: 760px;
}
#queue-deposits .game-row div, #queue-withdrawals .game-row div {
  overflow-wrap: anywhere;
}
.state-approved, .state-paid { color: #4bbf73; }
.state-rejected, .state-refused { color: #e2574c; }
.state-pending { color: #e8c477; }

.message-list {
  max-height: 260px;
  min-height: 0;
  overflow-y: auto;
  margin: 6px 0 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.message {
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.04);
  font-size: 13px;
  color: #cfd8e6;
}
.message.from-admin { background: rgba(74, 143, 231, 0.14); }
.message b { color: #dfe6f2; display: block; margin-bottom: 2px; }
