/* pod — one stylesheet for the whole app.
   Dark by default: four people playing at night on four different screens, and
   a bright UI around card art is fatiguing. */

:root {
  --bg: #12100e;
  --felt: #1c2a22;
  --felt-2: #16211b;
  --panel: #1b1917;
  --panel-2: #232120;
  --line: #34302c;
  --ink: #ece7df;
  --ink-dim: #9c948a;
  --gold: #c9a227;
  --gold-dim: #8a7220;
  --danger: #c2453a;
  --good: #4f9d69;
  --radius: 10px;
  --card-w: 86px;
  --card-r: 0.717; /* a Magic card is 63 × 88 mm */
  --shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
  color-scheme: dark;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.5 ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif;
  overscroll-behavior: none;
}

a { color: var(--gold); }
button, input, select, textarea { font: inherit; color: inherit; }

button {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px 12px;
  cursor: pointer;
}
button:hover:not(:disabled) { border-color: var(--gold-dim); background: #2c2926; }
button:disabled { opacity: 0.45; cursor: default; }
button.primary { background: var(--gold); border-color: var(--gold); color: #1a1508; font-weight: 600; }
button.primary:hover:not(:disabled) { background: #dcb434; }
button.ghost { background: transparent; }
button.danger { border-color: #5a2b26; color: #e08a80; }
button.primary.danger { background: var(--danger); border-color: var(--danger); color: #fff; }
button.primary.danger:hover:not(:disabled) { background: #d0554a; }

input[type="text"], input[type="number"], textarea, select {
  background: #14120f;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px 10px;
  width: 100%;
}
input:focus, textarea:focus, select:focus { outline: 2px solid var(--gold-dim); outline-offset: -1px; }

.muted { color: var(--ink-dim); }
.row { display: flex; gap: 8px; align-items: center; }
.spread { display: flex; gap: 8px; align-items: center; justify-content: space-between; }
.wrap { flex-wrap: wrap; }
.grow { flex: 1; min-width: 0; }
.hidden { display: none !important; }

/* ---------------------------------------------------------------- *
 * Login + lobby
 * ---------------------------------------------------------------- */

.shell { max-width: 1040px; margin: 0 auto; padding: 24px 20px 64px; }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 14px 20px; border-bottom: 1px solid var(--line);
  background: var(--panel); position: sticky; top: 0; z-index: 20;
}
.brand { display: flex; align-items: center; gap: 10px; font-weight: 700; letter-spacing: 0.02em; }
.brand .dot { width: 10px; height: 10px; border-radius: 50%; background: var(--gold); }
.who { display: flex; align-items: center; gap: 8px; }
.who img { width: 26px; height: 26px; border-radius: 50%; }

.centered {
  min-height: 100vh; display: grid; place-items: center; padding: 24px;
}
.card-panel {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 14px; padding: 24px; max-width: 420px; width: 100%;
}

h1 { font-size: 22px; margin: 0 0 6px; }
h2 { font-size: 17px; margin: 28px 0 10px; }
h3 { font-size: 15px; margin: 0 0 6px; }

/* 260px so a tile's three action buttons sit on one line rather than folding
   onto a second row. `.tile-actions` still wraps if a window gets narrower than
   that — wrapping is the safety net, not the normal state. */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.tile {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px; display: flex; flex-direction: column; gap: 8px;
}
/* Buttons along the bottom of a tile.
   Wrapping is what keeps them inside the box: three buttons are wider than a
   240px tile, and a plain flex row overflowed the border rather than folding. */
.tile-actions {
  display: flex; flex-wrap: wrap; gap: 6px;
  align-items: center; margin-top: auto; min-width: 0;
}
.tile-actions button { padding: 5px 10px; font-size: 12px; }

.tile.clickable { cursor: pointer; }
.tile.clickable:hover { border-color: var(--gold-dim); }
.tile .code { font-family: ui-monospace, Consolas, monospace; font-size: 20px; letter-spacing: 3px; color: var(--gold); }
/* Commander art beside the words, rather than stacked above them — it's the
   blurb that tells a new player what they're picking, so it gets the room. */
.deck-head { display: flex; gap: 12px; align-items: flex-start; min-width: 0; }
.deck-thumb { display: flex; flex-direction: column; gap: 6px; flex: 0 0 auto; }
.deck-thumb img { width: 68px; border-radius: 5px; display: block; }
.deck-blurb { flex: 1; min-width: 0; }
.deck-blurb h3 { margin: 0 0 2px; }
.deck-desc { font-size: 12.5px; line-height: 1.45; margin: 8px 0 0; color: var(--ink-dim); }

.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 14px; }
.tabs button { border: 0; background: none; border-bottom: 2px solid transparent; border-radius: 0; padding: 8px 14px; color: var(--ink-dim); }
.tabs button[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--gold); }

/* The share output. Monospace because it's a deck list people will read down
   the left edge, and selectable so Ctrl+C works if the clipboard API doesn't. */
.share-output {
  margin-top: 10px;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12.5px;
  line-height: 1.5;
  white-space: pre;
  overflow-wrap: normal;
  overflow-x: auto;
}

.notice { border-radius: 8px; padding: 10px 12px; margin: 10px 0; border: 1px solid; }
.notice.err { background: #2a1614; border-color: #5a2b26; color: #e6a49c; }
.notice.ok { background: #16241b; border-color: #2f5a3c; color: #a7d8ba; }

/* ---------------------------------------------------------------- *
 * Table
 * ---------------------------------------------------------------- */

body.table-page { overflow: hidden; }

.table-shell {
  display: grid;
  grid-template-columns: 1fr 300px;
  grid-template-rows: 42px 1fr;
  height: 100vh;
}

.table-bar {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 12px;
  padding: 0 12px; background: var(--panel); border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.table-bar .code { font-family: ui-monospace, Consolas, monospace; letter-spacing: 2px; color: var(--gold); }

.play-area {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) minmax(0, 1.35fr) auto;
  background: radial-gradient(ellipse at 50% 40%, var(--felt) 0%, var(--felt-2) 70%, #0e1512 100%);
  min-width: 0; min-height: 0;
}

/* Phase tracker. A shared marker so four people agree on where the turn is —
   nothing in the app reads it. Scrolls inside itself on a narrow window rather
   than making the page scroll. */
.phase-bar {
  display: flex; align-items: center; gap: 4px;
  padding: 4px 6px; min-height: 0;
  background: rgba(0, 0, 0, 0.28);
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  overflow-x: auto; scrollbar-width: thin;
}
.phase-bar .whose {
  flex: 0 0 auto; font-size: 11px; color: var(--ink-dim);
  white-space: nowrap; padding-right: 4px;
}
.phase-bar .whose b { color: var(--gold); }
.phase-step {
  flex: 0 0 auto;
  background: transparent; border: 1px solid transparent;
  border-radius: 6px; padding: 2px 8px; font-size: 11px;
  color: var(--ink-dim); white-space: nowrap;
}
.phase-step:hover { color: var(--ink); border-color: var(--line); background: transparent; }
/* Steps already gone by in this turn, so the eye can find "now" instantly. */
.phase-step.past { color: #6d675f; }
.phase-step.now {
  background: var(--gold); border-color: var(--gold);
  color: #1a1508; font-weight: 700;
}
.phase-bar .sep { flex: 0 0 auto; color: #4a453f; font-size: 10px; }
.phase-bar .next { flex: 0 0 auto; margin-left: auto; padding: 2px 10px; font-size: 11px; }

/* Flex rather than three fixed columns: the width goes to players who are
   actually sitting there. An empty seat only needs room for its "Sit here"
   button, so in a two-player game the one opponent gets nearly the whole row
   instead of a third of it. */
.opponents { display: flex; gap: 4px; padding: 4px; min-height: 0; min-width: 0; }
.opponents > .seat { flex: 1 1 0; min-width: 0; }
/* An empty seat collapses to a slim strip once someone is actually playing.
   It still has to be joinable, but a whole empty board's worth of width is
   width taken away from a real player's board. */
.opponents > .seat.empty { flex: 0 0 auto; width: 54px; }
.opponents > .seat.empty .seat-body,
.opponents > .seat.empty .zonebar { display: none; }
.opponents > .seat.empty .seat-head {
  height: 100%; flex-direction: column; justify-content: center;
  gap: 8px; padding: 8px 2px; border-bottom: 0;
}
/* Turned on their side so the strip stays narrow without truncating. */
.opponents > .seat.empty .seat-head > span,
.opponents > .seat.empty .seat-head > button {
  writing-mode: vertical-rl;
  text-orientation: mixed;
}
.opponents > .seat.empty .seat-head > span { font-size: 10px; flex: 0 1 auto; }
.opponents > .seat.empty .seat-head > button { padding: 10px 4px; font-size: 11px; }

/* Before anyone sits down there is nothing to prioritise, so share it out. */
.play-area[data-opponents='0'] .opponents > .seat.empty { flex: 1 1 0; width: auto; }
.play-area[data-opponents='0'] .opponents > .seat.empty .seat-body { display: flex; }
.play-area[data-opponents='0'] .opponents > .seat.empty .zonebar { display: flex; }
.play-area[data-opponents='0'] .opponents > .seat.empty .seat-head {
  height: auto; flex-direction: row; justify-content: flex-start;
  padding: 4px 8px; border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.play-area[data-opponents='0'] .opponents > .seat.empty .seat-head > span,
.play-area[data-opponents='0'] .opponents > .seat.empty .seat-head > button {
  writing-mode: horizontal-tb;
}

/* Two players: the same board size each, rather than the host getting the
   larger half of the table. */
.play-area[data-opponents='1'] { grid-template-rows: auto minmax(0, 1fr) minmax(0, 1fr) auto; }
.play-area[data-opponents='1'] .opponents > .seat:not(.empty) { --card-w: 100px; }

/* With more than one opponent, the binding constraint is HEIGHT, not width:
   the opponents row is a fixed slice of the table however many are in it.
   64px is the largest card whose height still lets two rows fit in that slice —
   at 68px it drops to a single row and each board shows half as much. Measured,
   not guessed. So two and three opponents share a size, and fewer opponents
   buys wider boards (more columns) rather than bigger cards. */
.play-area[data-opponents='2'] .opponents > .seat:not(.empty),
.play-area[data-opponents='3'] .opponents > .seat:not(.empty) { --card-w: 64px; }

/* Your own seat has to stretch to fill its grid row — left to size itself it
   collapses to the height of its header, and you get no battlefield. */
#you-seat { display: flex; min-height: 0; padding: 0 4px 4px; }
#you-seat > .seat { flex: 1; min-height: 0; }

.seat {
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  border: 1px solid rgba(255, 255, 255, 0.05); border-radius: 8px;
  background: rgba(0, 0, 0, 0.14);
}
.seat.is-turn { border-color: var(--gold); box-shadow: inset 0 0 0 1px rgba(201, 162, 39, 0.25); }
.seat.empty { border-style: dashed; opacity: 0.6; }
.seat.you { --card-w: 100px; }

.seat-head {
  display: flex; align-items: center; gap: 8px; padding: 4px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06); font-size: 12px; flex: 0 0 auto;
}
.seat-head img.avatar { width: 20px; height: 20px; border-radius: 50%; }
.seat-head .nm { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.seat-head .off { color: var(--ink-dim); font-style: italic; }

.life {
  display: inline-flex; align-items: center; gap: 4px;
  background: #0e0d0c; border: 1px solid var(--line); border-radius: 999px; padding: 1px 4px;
}
.life .val { min-width: 26px; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }
.life button { padding: 0 6px; border: 0; background: none; line-height: 1; font-size: 14px; }
.life.low .val { color: var(--danger); }

/* Floating mana. The letter carries the meaning and the colour reinforces it,
   so the pool still reads correctly without colour vision. */
.mana-row { display: flex; gap: 3px; align-items: center; flex-wrap: wrap; }
.mana {
  display: inline-flex; align-items: center; gap: 3px;
  background: #0e0d0c; border: 1px solid var(--line); border-radius: 999px;
  padding: 1px 6px 1px 2px; font-size: 11px; cursor: pointer; user-select: none;
}
.mana:hover { border-color: var(--gold-dim); }
.mana .sym {
  width: 14px; height: 14px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 9px; font-weight: 800; color: #17130d;
}
.mana .n { font-weight: 700; font-variant-numeric: tabular-nums; min-width: 7px; text-align: center; }
.mana.zero { opacity: 0.4; }
.mana.zero:hover { opacity: 1; }
.mana.W .sym { background: #f7f2dc; }
.mana.U .sym { background: #a6dbf5; }
.mana.B .sym { background: #b6aca8; }
.mana.R .sym { background: #f2a189; }
.mana.G .sym { background: #96d0ac; }
.mana.C .sym { background: #d2ccc6; }
.mana-clear {
  border: 1px solid var(--line); background: #0e0d0c; border-radius: 999px;
  padding: 0 6px; font-size: 11px; line-height: 16px;
}

/* "Showing hand to X" — deliberately loud, because an open hand being open is
   the one thing nobody should be able to forget. */
.sharing {
  font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 190px; background: #2a2415; border: 1px solid var(--gold-dim);
  color: var(--gold); border-radius: 6px; padding: 1px 6px;
}

.pips { display: flex; gap: 4px; align-items: center; font-size: 11px; color: var(--ink-dim); }
.pip { background: #0e0d0c; border: 1px solid var(--line); border-radius: 6px; padding: 0 5px; cursor: pointer; }
.pip.lethal { color: var(--danger); border-color: #5a2b26; }

/* Command zone on the left, battlefield taking the rest. */
.seat-body { display: flex; flex: 1 1 auto; min-height: 0; min-width: 0; }

/* The command zone is on the table, not hidden behind a counter: a commander is
   public information and every player needs to see it at a glance. */
.command-zone {
  flex: 0 0 auto;
  width: calc(var(--card-w) + 12px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 3px;
  overflow-y: auto;
  overflow-x: hidden;
  border-right: 1px dashed rgba(255, 255, 255, 0.12);
  background: rgba(0, 0, 0, 0.2);
}
.command-zone .cz-label {
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-dim);
  flex: 0 0 auto;
}
/* Laid out by flexbox here rather than positioned like a battlefield card. */
.command-zone .card { position: relative; flex: 0 0 auto; }
.command-zone.empty { border-right-color: rgba(255, 255, 255, 0.06); }

/* Commander tax, pinned to the bottom of the zone so it stays put whether the
   commander is sitting there or out on the battlefield. */
.cz-tax { width: 100%; margin-top: auto; display: flex; flex-direction: column; gap: 2px; flex: 0 0 auto; }
.cz-tax-row {
  display: flex; align-items: center; justify-content: center; gap: 1px;
  background: #0e0d0c; border: 1px solid var(--line); border-radius: 6px;
  padding: 1px 2px; font-size: 10px;
}
.cz-tax-row button { border: 0; background: none; padding: 0 4px; line-height: 1; font-size: 12px; border-radius: 4px; }
.cz-tax-row button:hover:not(:disabled) { background: #2c2926; }
.cz-tax-row .v { font-weight: 700; font-variant-numeric: tabular-nums; min-width: 20px; text-align: center; color: var(--gold); }
.cz-tax-row .nm {
  color: var(--ink-dim); max-width: 34px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.command-zone.drop-target { background: rgba(201, 162, 39, 0.12); box-shadow: inset 0 0 0 2px var(--gold-dim); }

/* The battlefield: cards are absolutely positioned by fraction, so a board
   looks the same on a laptop and an ultrawide. */
.battlefield { position: relative; flex: 1 1 auto; min-height: 0; min-width: 0; overflow: hidden; }
.battlefield.drop-target { background: rgba(201, 162, 39, 0.07); box-shadow: inset 0 0 0 2px var(--gold-dim); }

.zonebar {
  display: flex; gap: 4px; padding: 4px 6px; flex: 0 0 auto;
  border-top: 1px solid rgba(255, 255, 255, 0.06); font-size: 12px; flex-wrap: wrap;
}
/* Bigger than the surrounding chrome: these are clicked constantly and are a
   drop target, so they want a real hit area.
   The growth is deliberately vertical — an opponent's seat is only ~307px wide
   and all five pills have to stay on one line there, so horizontal padding is
   the one dimension that can't afford to grow. Wide padding here pushed them
   onto a second row and ate the battlefield. */
.zone-pill {
  display: inline-flex; align-items: center; gap: 5px;
  background: #0e0d0c; border: 1px solid var(--line); border-radius: 7px;
  padding: 5px 7px; cursor: pointer; white-space: nowrap;
}
.zone-pill:hover { border-color: var(--gold-dim); }
/* Full words by default; the short forms only come out where they're needed. */
.zone-pill .zl-abbr { display: none; }

/* An opponent's seat is a third of the play area, so five full-word pills plus
   their counts only fit on a very wide screen — and "fits until someone's
   graveyard reaches double figures" is not fitting. Opponents abbreviate at any
   normal laptop or desktop width; your own seat is full width and keeps the
   full words at every size. */
@media (max-width: 1450px) {
  .opponents .zone-pill .zl-full { display: none; }
  .opponents .zone-pill .zl-abbr { display: inline; }
  /* Trimmed enough to leave room for the counts to reach three digits without
     tipping onto a second row. */
  .opponents .zone-pill { padding: 5px 5px; gap: 3px; font-size: 11.5px; }
}
.zone-pill.drop-target { border-color: var(--gold); background: #2a2415; }
.zone-pill b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* Cards ------------------------------------------------------------ */

.card {
  position: absolute;
  width: var(--card-w);
  height: calc(var(--card-w) / var(--card-r));
  border-radius: 5px;
  background: #0b0a09;
  box-shadow: var(--shadow);
  cursor: grab;
  user-select: none;
  transition: transform 0.09s ease-out, box-shadow 0.09s;
  will-change: transform;
}
.card img { width: 100%; height: 100%; border-radius: 5px; display: block; pointer-events: none; }
.card.tapped { transform: rotate(90deg); }
.card.rotated { transform: rotate(180deg); }
.card.tapped.rotated { transform: rotate(270deg); }
.card.dragging { cursor: grabbing; z-index: 9999 !important; box-shadow: 0 10px 24px rgba(0, 0, 0, 0.7); }
.card.selected { outline: 2px solid var(--gold); outline-offset: 1px; }
.card.commander-card { outline: 2px solid #7a5ea8; outline-offset: 1px; }

/* Face-down and custom tokens have no art, so they're drawn rather than shown. */
.card .back, .card .textcard {
  width: 100%; height: 100%; border-radius: 5px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 6px; font-size: 10px; line-height: 1.25;
}
.card .back {
  background: radial-gradient(ellipse at 50% 35%, #3a2f4d, #16121f 75%);
  border: 3px solid #0b0a09; color: #6d5f8c; font-weight: 700; letter-spacing: 2px;
}
.card .textcard {
  background: linear-gradient(160deg, #2b2621, #1a1714);
  border: 3px solid #0b0a09; color: var(--ink); overflow: hidden;
}
.card .textcard .tname { font-weight: 700; font-size: 11px; margin-bottom: 3px; }
.card .textcard .tpt { margin-top: auto; font-weight: 700; }

.counters {
  position: absolute; left: 2px; bottom: 2px; right: 2px;
  display: flex; flex-wrap: wrap; gap: 2px; pointer-events: none;
}
.counter {
  background: rgba(8, 8, 8, 0.9); border: 1px solid var(--gold-dim); color: var(--gold);
  border-radius: 4px; font-size: 9px; padding: 0 3px; font-weight: 700;
}
.card .note {
  position: absolute; top: 2px; left: 2px; right: 2px;
  background: rgba(8, 8, 8, 0.85); color: var(--ink); font-size: 9px;
  border-radius: 3px; padding: 0 3px; pointer-events: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Your hand -------------------------------------------------------- */

.hand-tray {
  flex: 0 0 auto; background: rgba(0, 0, 0, 0.34);
  border-top: 1px solid var(--line); padding: 6px 8px;
  display: flex; align-items: flex-end; gap: 6px; min-height: 96px;
}
.hand-tray.drop-target { background: rgba(201, 162, 39, 0.1); }
.hand-cards { display: flex; align-items: flex-end; flex: 1; min-width: 0; }
.hand-cards .card {
  position: relative; flex: 0 0 auto; --card-w: 92px;
  margin-right: -26px; transition: transform 0.1s, margin 0.1s;
}
.hand-cards .card:hover { transform: translateY(-14px); z-index: 5; }
.hand-cards .card:last-child { margin-right: 0; }

/* Sidebar ---------------------------------------------------------- */

.sidebar {
  display: flex; flex-direction: column; min-height: 0;
  background: var(--panel); border-left: 1px solid var(--line);
}
.side-actions { padding: 8px; display: flex; flex-wrap: wrap; gap: 6px; border-bottom: 1px solid var(--line); }
.side-actions button { padding: 5px 9px; font-size: 12px; }

/* The stack. Lives in the sidebar so it is on screen at all times — the whole
   point is seeing what you are about to be hit by while you decide. */
.stack-panel {
  flex: 0 0 auto; max-height: 42vh; overflow-y: auto;
  border-bottom: 1px solid var(--line);
  padding: 6px 8px;
  background: rgba(201, 162, 39, 0.04);
}
.stack-panel.drop-target { background: rgba(201, 162, 39, 0.14); box-shadow: inset 0 0 0 2px var(--gold-dim); }
.stack-panel .sp-head {
  display: flex; align-items: center; gap: 6px; margin-bottom: 6px;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--ink-dim);
}
.stack-panel .sp-head .n { color: var(--gold); font-weight: 700; }
.stack-panel .sp-head button { padding: 2px 8px; font-size: 11px; text-transform: none; letter-spacing: 0; }
.stack-panel .sp-empty { font-size: 12px; color: var(--ink-dim); }

.stack-item {
  display: flex; align-items: center; gap: 6px;
  border: 1px solid var(--line); border-radius: 8px;
  padding: 4px 6px; margin-bottom: 4px; background: var(--panel-2);
  font-size: 12px; cursor: pointer;
}
.stack-item:hover { border-color: var(--gold-dim); }
/* The top of the stack resolves first, so it is listed first and marked. */
.stack-item.top { border-color: var(--gold); }
.stack-item img { width: 30px; border-radius: 3px; flex: 0 0 auto; }
.stack-item .who { color: var(--ink-dim); font-size: 10px; }
.stack-item .what { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.stack-item .badge {
  flex: 0 0 auto; font-size: 9px; text-transform: uppercase; letter-spacing: 0.06em;
  color: #1a1508; background: var(--gold); border-radius: 4px; padding: 0 4px; font-weight: 700;
}

/* Cards someone has shown the table. Only on screen while there are any. */
.reveal-panel {
  flex: 0 0 auto; max-height: 30vh; overflow-y: auto;
  border-bottom: 1px solid var(--line); padding: 6px 8px;
  background: rgba(201, 162, 39, 0.06);
}
.reveal-row { display: flex; flex-wrap: wrap; gap: 6px; }
.reveal-card { position: relative; width: 62px; cursor: pointer; }
.reveal-card img { width: 100%; border-radius: 4px; display: block; }
.reveal-card:hover { outline: 2px solid var(--gold); outline-offset: 1px; }
.reveal-card .reveal-by {
  display: block; font-size: 9px; color: var(--ink-dim); text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Combat summary. Only on screen while something is attacking. */
.combat-panel {
  flex: 0 0 auto; max-height: 32vh; overflow-y: auto;
  border-bottom: 1px solid var(--line); padding: 6px 8px;
  background: rgba(194, 69, 58, 0.07);
}
.combat-row {
  border: 1px solid var(--line); border-left: 3px solid var(--danger);
  border-radius: 8px; padding: 4px 7px; margin-bottom: 4px;
  background: var(--panel-2); font-size: 12px;
}
.combat-row .atk { overflow-wrap: anywhere; }
.combat-row .blk { font-size: 11px; color: var(--ink-dim); margin-top: 1px; }
.combat-row .blk.unblocked { color: #e08a80; }

/* Combat state on the card itself. */
.card.in-combat { box-shadow: 0 0 0 2px var(--danger), var(--shadow); }
.combat-tag {
  position: absolute; left: 2px; right: 2px; bottom: 2px;
  background: rgba(8, 8, 8, 0.88); border-radius: 3px;
  font-size: 9px; padding: 0 3px; pointer-events: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.combat-tag.attacking { color: #f0a89e; }
.combat-tag.blocking { color: #a9dcf5; }
/* Counters sit at the bottom too, so lift them clear of the combat badge. */
.card.in-combat .counters { bottom: 15px; }

.log { flex: 1; overflow-y: auto; padding: 8px; font-size: 12px; line-height: 1.45; }
.log div { padding: 2px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.04); color: var(--ink-dim); }
.log div.hl { color: var(--gold); font-weight: 600; }
.chatbox { display: flex; gap: 6px; padding: 8px; border-top: 1px solid var(--line); }

/* Preview + menus -------------------------------------------------- */

#preview {
  position: fixed; z-index: 900; width: 280px; pointer-events: none;
  border-radius: 12px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.75);
}
#preview img { width: 100%; border-radius: 12px; display: block; }
/* Shown above the art when previewing your own face-down card, so it's obvious
   this is private and not something the table can see. */
.preview-private {
  background: var(--gold); color: #1a1508; font-size: 11px; font-weight: 700;
  border-radius: 8px 8px 0 0; padding: 4px 8px; text-align: center;
}
#preview .textcard {
  background: linear-gradient(160deg, #2b2621, #1a1714); border: 2px solid #0b0a09;
  border-radius: 12px; padding: 14px; min-height: 180px;
}

.menu {
  position: fixed; z-index: 950; min-width: 190px; padding: 4px;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
  max-height: 80vh; overflow-y: auto;
}
.menu button {
  display: block; width: 100%; text-align: left; border: 0; background: none;
  border-radius: 6px; padding: 6px 10px; font-size: 13px;
}
.menu button:hover { background: #383430; }
.menu .sep { height: 1px; background: var(--line); margin: 4px 2px; }
.menu .label { padding: 5px 10px 2px; font-size: 11px; color: var(--ink-dim); text-transform: uppercase; letter-spacing: 0.06em; }

.backdrop {
  position: fixed; inset: 0; z-index: 940; background: rgba(0, 0, 0, 0.55);
  display: grid; place-items: center; padding: 24px;
}
.modal {
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  padding: 18px; width: min(880px, 100%); max-height: 86vh; overflow-y: auto;
}
.modal h2 { margin-top: 0; }

/* Deck preview and card search share this grid. */
.preview-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; }
.preview-card { position: relative; cursor: pointer; border-radius: 6px; }
.preview-card img { width: 100%; aspect-ratio: var(--card-r); border-radius: 6px; display: block; }
.preview-card:hover { outline: 2px solid var(--gold); outline-offset: 1px; }
.preview-noart {
  aspect-ratio: var(--card-r); border-radius: 6px; padding: 8px;
  background: linear-gradient(160deg, #2b2621, #1a1714);
  display: grid; place-items: center; text-align: center; font-size: 11px;
}
.preview-count {
  position: absolute; right: 3px; bottom: 3px;
  background: rgba(8, 8, 8, 0.9); border: 1px solid var(--gold-dim); color: var(--gold);
  border-radius: 5px; font-size: 11px; font-weight: 700; padding: 0 4px;
}

/* Token picker: art with its name, size and ability underneath, because the
   art alone can't tell a plain Zombie from a decayed one. */
.token-pick { display: flex; flex-direction: column; gap: 4px; }
.token-pick .card { position: relative; width: 100%; height: auto; aspect-ratio: var(--card-r); }
.token-pick .card img { height: auto; aspect-ratio: var(--card-r); }
.token-label { font-size: 11px; line-height: 1.35; }
.token-label b { display: block; }
.token-label span { color: var(--ink-dim); }

.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 8px; }
.card-grid .card { position: relative; width: 100%; height: auto; aspect-ratio: var(--card-r); }
.card-grid .card img { height: auto; aspect-ratio: var(--card-r); }

/* Glossary. Two columns where there's room — these are short entries and a
   single long column makes scanning for a keyword slower than it should be. */
.gl-section { margin-top: 18px; }
.gl-section h3 { margin-bottom: 4px; }
.gl-blurb { margin: 0 0 8px; font-size: 12.5px; }
.gl-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 8px; }
.gl-term {
  border: 1px solid var(--line); border-left: 3px solid var(--gold-dim);
  border-radius: 8px; padding: 8px 10px; background: var(--panel-2);
}
.gl-name { font-weight: 700; margin-bottom: 2px; }
.gl-short { font-size: 12.5px; line-height: 1.45; }
.gl-detail {
  font-size: 12px; line-height: 1.45; color: var(--ink-dim);
  margin-top: 5px; padding-top: 5px; border-top: 1px solid var(--line);
}

#toasts { position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%); z-index: 990; display: flex; flex-direction: column; gap: 6px; }
.toast {
  background: var(--panel-2); border: 1px solid var(--line); border-left: 3px solid var(--gold);
  border-radius: 8px; padding: 8px 14px; box-shadow: var(--shadow); font-size: 13px;
}
.toast.err { border-left-color: var(--danger); }

/* Four battlefields will never be comfortable on a phone, but the page must
   still not scroll sideways — everything that can't fit wraps or shrinks. */
/* On a narrower window the fixed 300px sidebar is eating a quarter of the
   screen. Giving 40px of it back to the play area is what lets an opponent's
   zone bar stay on one line — and every battlefield gets wider too. */
@media (max-width: 1200px) {
  .table-shell { grid-template-columns: 1fr 260px; }
}

/* Card size has to answer to the window's HEIGHT as well as its width. A row of
   the table is a fixed slice of whatever height there is, and on a short screen
   a 100px card is taller than the space it sits in — at which point it cannot be
   placed anywhere and just overflows. */
@media (max-height: 780px) {
  .seat.you,
  .play-area[data-opponents='1'] .opponents > .seat:not(.empty) { --card-w: 84px; }
}
@media (max-height: 680px) {
  .seat.you,
  .play-area[data-opponents='1'] .opponents > .seat:not(.empty) { --card-w: 70px; }
  .play-area[data-opponents='2'] .opponents > .seat:not(.empty),
  .play-area[data-opponents='3'] .opponents > .seat:not(.empty) { --card-w: 54px; }
}

@media (max-width: 900px) {
  .table-shell { grid-template-columns: 1fr; grid-template-rows: auto 1fr 200px; }
  .table-bar { flex-wrap: wrap; padding: 6px 10px; row-gap: 6px; }
  .sidebar { border-left: 0; border-top: 1px solid var(--line); }
  /* Too narrow to sit three boards side by side — let them wrap instead of
     squashing every one of them. */
  .opponents { flex-wrap: wrap; }
  .opponents > .seat { flex: 1 1 240px; }
}

@media (max-width: 560px) {
  .opponents > .seat { flex: 1 1 100%; }
  .seat { --card-w: 64px; }
}
