/* Astris Table -- a surface, not a referee.
   Nothing here knows the rules, so the styling has two jobs: keep 120 cards
   legible at once, and make it obvious what is attached to what. */

:root {
  --bg: #0b0e14;
  --felt: #121823;
  --felt-2: #161d2a;
  --edge: #263142;
  --ink: #e6ecf5;
  --dim: #8b9bb4;
  --accent: #6fa8ff;
  --warn: #ffb86b;
  --drop: #2f6f4f;
  --turn: #4ade80;         /* whose turn it is, and nothing else */
  --rail-h: 128px;         /* hand + piles strip; cards size themselves to it */
  --aside-w: 230px;        /* off-Band column beside the three Bands */
  --radius: 6px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; height: 100%;
  background: var(--bg); color: var(--ink);
  font: 13px/1.45 "Segoe UI", system-ui, sans-serif;
  overflow: hidden;
}

body { display: grid; grid-template-columns: 1fr 320px; grid-template-rows: auto 1fr; }
body.no-panel { grid-template-columns: 1fr 0; }
body.no-panel #panel { display: none; }

/* ---- the way in ----
   Pick two decks, press the button, and the table it opens has an address of
   its own. Deliberately one screen with one decision on it. */
body.lobby-page { display: block; overflow: auto; }
.lobby {
  max-width: 560px; margin: 0 auto; padding: 14vh 24px 40px;
  text-align: center;
}
.lobby h1 {
  margin: 0 0 6px; font-size: 42px; font-weight: 600;
  letter-spacing: .14em; color: var(--accent); text-transform: uppercase;
}
.lobby-sub { margin: 0 0 32px; color: var(--dim); line-height: 1.6; }
.lobby-decks {
  display: flex; gap: 14px; justify-content: center; flex-wrap: wrap;
  margin-bottom: 24px;
}
.lobby-decks label {
  display: flex; flex-direction: column; gap: 5px; text-align: left;
  flex: 1 1 200px; min-width: 0;
}
.lobby-decks span {
  font-size: 11px; color: var(--dim);
  text-transform: uppercase; letter-spacing: .07em;
}
.lobby-decks select {
  max-width: none; width: 100%; padding: 8px 10px; font-size: 15px;
}
.lobby-go {
  width: 100%; padding: 13px; font-size: 17px; font-weight: 600;
  background: var(--accent); color: #07101f; border-color: var(--accent);
  border-radius: 8px;
}
.lobby-go:hover { filter: brightness(1.12); }
.lobby-note {
  margin: 16px 0 0; font-size: 12px; color: var(--dim); line-height: 1.6;
}
.lobby-alt { margin-top: 30px; }
.lobby-alt button { font-size: 12px; text-decoration: underline; }

/* ---- top bar ---- */
#bar {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 10px;
  padding: 6px 12px;
  background: #0e131c; border-bottom: 1px solid var(--edge);
}
.brand { color: var(--accent); letter-spacing: .04em; }
#bar label { color: var(--dim); display: flex; align-items: center; gap: 4px; }
.spacer { flex: 1; }
select, button {
  background: #1a2231; color: var(--ink);
  border: 1px solid var(--edge); border-radius: 4px;
  padding: 3px 8px; font: inherit; cursor: pointer;
}
select { max-width: 150px; }
button:hover { border-color: var(--accent); }
button.quiet { color: var(--dim); background: transparent; }
.dice { display: flex; gap: 4px; }

/* playing together: a room name, who is in it, and which chair you are in */
.netbar { display: flex; align-items: center; gap: 6px; }
.net-status {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; color: var(--dim);
}
.net-status.hidden { display: none; }
/* never let someone believe they are sharing a board when they are not */
.net-status.solo { opacity: .65; font-style: italic; }
.net-status .net-room {
  color: var(--ink); background: #18202e; border: 1px solid var(--edge);
  border-radius: 3px; padding: 1px 6px; font-variant-numeric: tabular-nums;
}
.net-status.on .net-room { border-color: var(--drop); color: #9ae6b8; }
.net-status button { font-size: 11px; padding: 1px 6px; }

/* ---- table ----
   Both seats have to be visible at once or it is not a table, so the whole
   thing fits the window: the six bands share the leftover height and cards
   are sized by the band they sit in rather than by a fixed pixel width. A
   band that overflows scrolls sideways instead of growing a second row. */
#table {
  grid-column: 1; grid-row: 2;   /* pinned: auto-placement put the panel first */
  overflow-x: hidden; overflow-y: auto; padding: 6px 10px;
  display: flex; flex-direction: column; gap: 4px;
  min-height: 0;
}
.seat { flex: 0 0 auto; display: flex; flex-direction: column; gap: 4px; }
.arena { flex: 1 1 0; min-height: 0; display: flex; gap: 6px; }
.lanes { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.sidecol { flex: 0 0 var(--aside-w); display: flex; flex-direction: column; gap: 4px; }

.seat-rail {
  flex: 0 0 auto;
  display: flex; align-items: stretch; gap: 10px;
  height: var(--rail-h);
}
.piles { display: flex; gap: 6px; flex: 0 0 auto; }
.pile {
  width: calc(var(--rail-h) / 1.4); height: 100%;
  border: 1px dashed var(--edge); border-radius: var(--radius);
  background: var(--felt); position: relative;
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
}
.pile-label {
  position: absolute; top: 4px; left: 0; right: 0; text-align: center;
  font-size: 10px; color: var(--dim); text-transform: uppercase;
  letter-spacing: .06em; pointer-events: none;
}
.pile .count {
  position: absolute; bottom: 2px; right: 4px;
  font-size: 13px; color: var(--ink); pointer-events: none;
  background: rgba(6,9,14,.85); border-radius: 3px; padding: 0 4px;
  font-variant-numeric: tabular-nums;
}

.hand-head {
  display: flex; flex-direction: column; justify-content: center; gap: 4px;
  color: var(--dim); flex: 0 0 auto;
  font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
}
.hand {
  flex: 1 1 auto; min-width: 0; height: 100%;
  display: flex; gap: 4px; flex-wrap: nowrap;
  overflow-x: auto; overflow-y: hidden;
  padding: 3px; border: 1px solid var(--edge); border-radius: var(--radius);
  background: var(--felt);
}

/* ---- bands ---- */
/* The floor is what a card needs to be recognisable at a glance; above it the
   bands share whatever height the window has, so a tall monitor gets bigger
   cards and a short one scrolls instead of shrinking them to confetti. */
.band {
  position: relative; flex: 1 1 0; min-height: 108px;
  border: 1px solid var(--edge); border-left: 3px solid #2c3a4f;
  border-radius: var(--radius); background: var(--felt-2);
  padding: 3px 3px 3px 64px;
}
.band[data-band="Space"]     { border-left-color: #3c5a86; }
.band[data-band="Surface"]   { border-left-color: #6b5436; }
.band[data-band="Planetary"] { border-left-color: #3d6b4a; }

/* Space is one band at double height with a lane each: it is where the two
   sides actually meet, so two bands pretending to be adjacent was a fiction.
   The hairline is the only thing separating the lanes. */
.band-space { flex: 2 2 0; min-height: 216px; }
.space-rows { display: flex; flex-direction: column; height: 100%; }
.space-rows > .band-cards { flex: 1 1 0; min-height: 0; }
.space-rows > .band-cards:first-child { border-bottom: 1px dashed #2b3a52; }
.band-label {
  position: absolute; left: 8px; top: 50%; transform: translateY(-50%);
  font-size: 11px; color: var(--dim); text-transform: uppercase;
  letter-spacing: .08em; width: 56px; pointer-events: none;
}
.band-cards {
  display: flex; gap: 6px; align-items: stretch;
  flex-wrap: nowrap; height: 100%;
  overflow-x: auto; overflow-y: hidden;
  /* centred, so a Band with two cards reads as a line rather than drifting
     off to the left; once it overflows this behaves like flex-start again */
  justify-content: safe center;
}

/* ---- off-Band ----
   S5.10 puts unattached Devices and Storylines in no Band at all, and
   Convocate Statutes are not in one either, so they need a place that is on
   the table but not in a lane. */
.aside {
  flex: 1 1 0; min-height: 0;
  position: relative;
  border: 1px solid var(--edge); border-radius: var(--radius);
  background: var(--felt); padding: 14px 4px 4px;
  display: flex; flex-direction: column;
}
.aside-label {
  position: absolute; top: 2px; left: 0; right: 0; text-align: center;
  font-size: 10px; color: var(--dim); text-transform: uppercase;
  letter-spacing: .08em; pointer-events: none;
}
.aside-cards {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-wrap: wrap; align-content: flex-start;
  gap: 4px; overflow-y: auto; overflow-x: hidden;
}
/* Storyline fronts are landscape, so a row here is shorter than a Band */
.aside-cards .host { height: calc((100% - 4px) / 2); min-height: 48px; }

/* ---- Galactic Factors ----
   Neither player's, so it sits between the two Off-Band regions rather than
   inside either: the +4..+1 card above the -1..-4 card, both face up, their
   columns lining up into one track. Both are landscape, so the region is
   wide and short. */
.gf {
  flex: 0 0 auto; position: relative;
  border: 1px solid #3a4a66; border-radius: var(--radius);
  background: #141c2b; padding: 14px 4px 4px;
}
.gf-cards { position: relative; display: flex; flex-direction: column; gap: 2px; align-items: center; }

/* A marker per axis, laid over whichever of the two cards holds its value.
   0 has no printed cell, so it sits in the gap between the cards -- which is
   where a physical marker would go. */
.gf-marks { position: absolute; inset: 0; pointer-events: none; z-index: 20; }
.gf-mark {
  position: absolute; transform: translate(-50%, -50%);
  min-width: 26px; height: 22px; padding: 0 4px;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: #0b0e14; background: var(--warn);
  border: 2px solid #0b0e14; border-radius: 11px;
  box-shadow: 0 2px 5px rgba(0,0,0,.8);
  cursor: pointer; pointer-events: auto;
}
.gf-mark.zero { background: #cdd7e6; }
.gf-mark:hover { outline: 2px solid var(--accent); }

.gf-steps {
  display: grid; grid-template-columns: 1fr 1fr; gap: 3px; margin-top: 5px;
}
.gf-step {
  display: flex; align-items: center; gap: 1px;
  border: 1px solid var(--edge); border-radius: 4px; background: var(--felt);
  padding: 1px 2px;
}
.gf-name {
  flex: 1 1 auto; font-size: 9px; color: var(--dim);
  text-transform: uppercase; letter-spacing: .04em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gf-val {
  min-width: 20px; text-align: center; font-size: 13px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.gf-step button {
  padding: 0 4px; border: 0; background: transparent; color: var(--dim);
  font-size: 13px; line-height: 1;
}
.gf-step button:hover { color: var(--accent); }
/* each card as wide as the column allows; 822/1122 is the printed ratio */
.gf-cards .host { height: calc((var(--aside-w) - 16px) * 822 / 1122); }

/* ---- cards ----
   Height comes from the container, width from the aspect ratio, so the same
   card markup works in a band, a hand, a pile and an occupant tray. 44 of the
   faces are landscape (Statutes, Storyline fronts) and get the ratio flipped. */
.card {
  position: relative; flex: 0 0 auto;
  height: 100%; width: auto; aspect-ratio: 5 / 7;
  border-radius: var(--radius); background: #06080c;
  border: 1px solid #000; cursor: grab;
  box-shadow: 0 1px 3px rgba(0,0,0,.6);
  transition: box-shadow .08s;
}
.card.landscape { aspect-ratio: 7 / 5; }
.card img {
  width: 100%; height: 100%; display: block;
  border-radius: var(--radius); object-fit: cover;
}
.card.rotated { transform: rotate(90deg); }
.card.selected { box-shadow: 0 0 0 2px var(--accent); }
.card:hover { box-shadow: 0 0 0 1px var(--accent), 0 2px 6px rgba(0,0,0,.7); z-index: 5; }
.card.dragging { opacity: .4; }
/* face down is the printed back, and so is a hidden hand -- a blanked-out
   front still leaks a card's shape and colour to the other player */
.card.facedown > *,
.hand.hidden-hand > .card > * { visibility: hidden; }
.card.facedown,
.hand.hidden-hand > .card {
  background-image: var(--back);
  background-size: cover; background-position: center;
  border: 1px solid #2c3a55;
  /* every back is portrait, and a landscape card left landscape face down
     would announce that it is a Statute or a Storyline */
  aspect-ratio: 5 / 7;
}

/* a face with no render yet: show the words, not a blank */
.card .stub {
  position: absolute; inset: 0; padding: 5px;
  font-size: 9px; line-height: 1.25; color: #c3cee0; overflow: hidden;
  background: linear-gradient(160deg, #1c2333, #10151f);
  border-radius: var(--radius);
}
.card .stub b { display: block; font-size: 10px; margin-bottom: 3px; color: var(--warn); }

/* A stack: each occupant laid over the one before and shifted right, so a
   covered card still shows its emblem and the start of its title. Every card
   keeps the full height of the band, which is what makes the Map readable at
   a glance -- a tray underneath read better one card at a time but cost each
   card a third of its height. Hovering separates the stack.

   --ov is how much of a card stays visible when it is covered. The shift has
   to be a real length, because a percentage margin resolves against the
   containing block rather than the card, so the page publishes --card-h once
   per render and the arithmetic happens here. */
.host {
  --ov: .34;
  display: flex; flex-direction: row; flex: 0 0 auto;
  height: 100%; align-items: stretch;
}
.host > .card { position: relative; }
.host > .card + .card {
  margin-left: calc(var(--card-h, 100px) * (5 / 7) * -1 * (1 - var(--ov)));
  box-shadow: -4px 0 7px rgba(0,0,0,.8);
}
.host:hover > .card { box-shadow: -4px 0 7px rgba(0,0,0,.8), 0 0 0 1px var(--accent); }

/* counters */
.counters {
  position: absolute; bottom: 2px; left: 2px; right: 2px;
  display: flex; flex-wrap: wrap; gap: 2px;
}
.chip {
  font-size: 9px; padding: 0 3px; border-radius: 7px;
  background: rgba(8,12,20,.9); border: 1px solid var(--accent);
  color: var(--ink); cursor: pointer; line-height: 14px;
}
.chip.dmg { border-color: #ff7a6b; }

/* dice sitting on a card: a die turned to a number, not a roll result. Big
   enough to read at a glance across the Map -- the number is the whole point
   of the die, and a Character's CP is checked constantly. */
.dice-on-card {
  position: absolute; top: 3px; left: 3px;
  display: flex; flex-wrap: wrap; gap: 3px;
}
.die-chip {
  min-width: 30px; height: 30px; padding: 0 4px;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: #0b0e14; background: #e6ecf5; border-radius: 6px;
  border: 1px solid #0b0e14; cursor: pointer;
  box-shadow: 0 1px 3px rgba(0,0,0,.75);
}
.die-chip:hover { outline: 1px solid var(--accent); }
.dice .die[draggable="true"] { cursor: grab; }

.drop-ok { outline: 2px solid var(--drop); outline-offset: -2px; background: #16271f; }

/* ---- panel ---- */
#panel {
  grid-column: 2; grid-row: 2;
  overflow: auto; border-left: 1px solid var(--edge);
  background: #0d121b; display: flex; flex-direction: column;
}
/* On a narrow window the reading panel costs more than it gives; the Panel
   button in the bar brings it back. */
@media (max-width: 1000px) {
  body { grid-template-columns: 1fr 0; }
  body #panel { display: none; }
  body.show-panel { grid-template-columns: 1fr 300px; }
  body.show-panel #panel { display: flex; }
}
#panel h4 {
  margin: 10px 10px 4px; font-size: 11px; color: var(--dim);
  text-transform: uppercase; letter-spacing: .07em;
}
#zoom { padding: 10px; border-bottom: 1px solid var(--edge); }
#zoom img { width: 100%; border-radius: 8px; display: block; margin-bottom: 8px; }
#zoom .hint { color: var(--dim); }
#zoom .title { font-weight: 600; margin-bottom: 2px; }
#zoom .typeline {
  color: var(--dim); font-size: 11px; margin-bottom: 6px;
  text-transform: uppercase; letter-spacing: .04em;
}
#zoom .stats { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; }
#zoom .stat {
  font-size: 10px; background: #18202e; border: 1px solid var(--edge);
  border-radius: 3px; padding: 1px 5px; color: var(--dim);
}
#zoom .stat b { color: var(--ink); font-weight: 600; }
#zoom .text { white-space: pre-wrap; font-size: 12px; }
#zoom .text em { color: var(--warn); font-style: normal; }
#zoom .faceflip { margin-top: 8px; }

.row { display: flex; flex-wrap: wrap; gap: 4px; padding: 0 10px; }
.row button { font-size: 11px; }
#extras { border-bottom: 1px solid var(--edge); padding-bottom: 10px; }

#logwrap { flex: 1; min-height: 120px; }
#log { margin: 0; padding: 0 10px 10px 26px; font-size: 11px; color: var(--dim); }
#log li { margin-bottom: 2px; }
#log li b { color: var(--ink); font-weight: 500; }

/* ---- trackers ----
   These are read across the table, not squinted at, so the number is large and
   carries the printed glyph beside it the way the cards do. */
.trackers {
  flex: 0 0 auto; display: grid; gap: 5px;
  grid-template-columns: repeat(2, auto); align-content: center;
}
.tracker {
  display: flex; align-items: center; gap: 2px;
  border: 1px solid var(--edge); border-radius: 5px; background: var(--felt);
  padding: 2px 4px;
}
.tracker .name {
  font-size: 10px; color: var(--dim); text-transform: uppercase;
  letter-spacing: .05em; margin-right: 2px; min-width: 50px;
}
.tracker .face { display: flex; align-items: center; gap: 3px; }
.tracker .face img { height: 20px; width: auto; display: block; order: 2; }
.tracker .val {
  min-width: 26px; text-align: center; font-size: 20px; font-weight: 600;
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.tracker button {
  padding: 0 6px; border: 0; background: transparent; color: var(--dim);
  font-size: 15px; line-height: 1;
}
.tracker button:hover { color: var(--accent); }

/* ---- context menu ---- */
#menu {
  position: fixed; z-index: 100; min-width: 168px;
  background: #141b27; border: 1px solid var(--edge); border-radius: 6px;
  box-shadow: 0 6px 20px rgba(0,0,0,.6); padding: 4px; font-size: 12px;
}
#menu.hidden { display: none; }
#menu div, #menu .sep { padding: 4px 8px; border-radius: 4px; cursor: pointer; }
#menu div:hover { background: #1f2a3b; }
#menu .sep {
  color: var(--dim); font-size: 10px; text-transform: uppercase;
  letter-spacing: .06em; cursor: default; padding-top: 7px;
}
#menu .sep:hover { background: none; }

/* ---- finder ----
   A searchable list of everything a seat owns, so a deck search also answers
   what is already out and what is still to come. */
#finder {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(4,7,12,.72);
  display: flex; align-items: center; justify-content: center;
}
#finder.hidden { display: none; }
.finder-box {
  width: min(760px, 92vw); max-height: 84vh;
  display: flex; flex-direction: column;
  background: #0f151f; border: 1px solid var(--edge); border-radius: 10px;
  box-shadow: 0 20px 60px rgba(0,0,0,.8);
}
.finder-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--edge);
}
.finder-head input {
  flex: 1 1 auto; min-width: 0;
  background: #18202e; color: var(--ink);
  border: 1px solid var(--edge); border-radius: 4px;
  padding: 5px 8px; font: inherit;
}
.finder-sum {
  padding: 6px 12px; font-size: 11px; color: var(--dim);
  border-bottom: 1px solid var(--edge);
}
.finder-list { overflow-y: auto; padding: 4px; }
.finder-row {
  display: flex; align-items: center; gap: 9px;
  padding: 4px 8px; border-radius: 5px; cursor: pointer;
}
.finder-row:hover { background: #1a2331; }
/* a card that has left the pile is still listed, but dimmed: the point is to
   see what is already out, not to hide it */
.finder-row.gone { opacity: .45; }
.finder-thumb { flex: 0 0 38px; height: 53px; border-radius: 3px; overflow: hidden; background: #06080c; }
.finder-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.finder-text { flex: 1 1 auto; min-width: 0; }
.finder-name { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.finder-type {
  font-size: 10px; color: var(--dim); text-transform: uppercase;
  letter-spacing: .03em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.finder-where {
  flex: 0 0 auto; font-size: 10px; color: var(--dim);
  background: #18202e; border: 1px solid var(--edge);
  border-radius: 3px; padding: 1px 6px; white-space: nowrap;
}
.finder-empty { padding: 20px; text-align: center; color: var(--dim); }

/* Whose turn it is. The whole hand region goes green -- the label as well as
   the cards -- because this is the one thing two people lose track of, and a
   thin border on one edge of it is not enough to catch an eye that is looking
   at the Map. */
.hand.turn-now {
  outline: 3px solid var(--turn); outline-offset: -3px;
  background: rgba(74,222,128,.18);
  box-shadow: 0 0 26px rgba(74,222,128,.30), inset 0 0 60px rgba(74,222,128,.10);
}
.hand-head.turn-now {
  color: var(--turn);
  outline: 3px solid var(--turn); outline-offset: -3px; border-radius: var(--radius);
  background: rgba(74,222,128,.18);
  padding: 0 6px;
}
.hand-head.turn-now::after {
  content: attr(data-turn);
  color: #07140c; background: var(--turn); border-radius: 3px;
  padding: 1px 5px; font-weight: 700; letter-spacing: .04em;
}
.turn-row { grid-column: 1 / -1; display: flex; justify-content: stretch; }
.turn-end {
  width: 100%; font-weight: 600;
  background: var(--accent); color: #07101f; border-color: var(--accent);
}
.turn-end:disabled { opacity: .45; cursor: default; }
.turn-end:not(:disabled):hover { filter: brightness(1.12); }
.turn-wait {
  width: 100%; text-align: center; font-size: 11px; color: var(--dim);
  border: 1px dashed var(--edge); border-radius: 4px; padding: 3px 0;
}
/* a resource you may not spend reads as not yours, rather than as broken */
.tracker button:disabled { opacity: .3; cursor: default; }

/* A notice waiting on the other player. Amber, centred, and nothing else on
   the table is amber -- the failure this replaces was a discreet line along
   the top edge, which reads as the game having started. */
.notice {
  pointer-events: auto; text-align: center;
  max-width: min(560px, 92vw);
  padding: 24px 32px;
  background: #1c1608; border: 2px solid var(--warn); border-radius: 14px;
  animation: notice-pulse 2.6s ease-in-out infinite;
}
@keyframes notice-pulse {
  0%, 100% { box-shadow: 0 0 34px rgba(255,184,107,.22), 0 20px 60px rgba(0,0,0,.7); }
  50%      { box-shadow: 0 0 52px rgba(255,184,107,.45), 0 20px 60px rgba(0,0,0,.7); }
}
@media (prefers-reduced-motion: reduce) {
  .notice { animation: none; box-shadow: 0 0 40px rgba(255,184,107,.3), 0 20px 60px rgba(0,0,0,.7); }
}
.notice-eyebrow {
  font-size: 11px; color: var(--warn);
  text-transform: uppercase; letter-spacing: .16em;
}
.notice-text { font-size: 20px; margin: 10px 0 6px; color: var(--ink); }
.notice-sub { font-size: 13px; color: var(--dim); }
.notice-go {
  margin-top: 16px; padding: 9px 20px; font-size: 14px; font-weight: 600;
  background: var(--warn); color: #1a1205; border-color: var(--warn);
  border-radius: 6px;
}
.notice-go:hover { filter: brightness(1.1); }
.notice .mull-empty { margin: 14px 0 0; text-align: center; }

/* a chair nobody is in, and the address that fixes it */
.mull-empty {
  margin: 0 0 14px; padding: 10px 14px;
  border: 1px dashed var(--edge); border-radius: 8px;
  color: var(--warn); font-size: 13px;
}
.mull-link {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin-top: 8px;
}
.mull-link code {
  background: #18202e; border: 1px solid var(--edge); border-radius: 4px;
  padding: 3px 8px; color: var(--ink); font-size: 12px;
}

/* two dice, and who they belong to */
.roll-row { display: flex; gap: 22px; justify-content: center; margin-bottom: 18px; }
.roll-cell { opacity: .55; }
.roll-cell.won { opacity: 1; }
.roll-die {
  width: 74px; height: 74px; display: flex; align-items: center;
  justify-content: center; font-size: 38px; font-weight: 700;
  color: #0b0e14; background: #e6ecf5; border-radius: 12px;
  border: 1px solid #0b0e14; box-shadow: 0 2px 6px rgba(0,0,0,.7);
}
.roll-cell.won .roll-die { background: var(--accent); }
.roll-who {
  margin-top: 6px; font-size: 11px; color: var(--dim);
  text-transform: uppercase; letter-spacing: .06em;
}

/* ---- the opening hand ----
   Seven cards and one decision, over the board rather than on it. The other
   player gets a strip instead of a sheet, so they can still read the table
   while they wait for it. */
.mull {
  position: fixed; inset: 0; z-index: 250;
  background: rgba(4,7,12,.82);
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.mull.hidden, #mull.hidden { display: none; }
/* dimmed, but not blacked out, and clicks pass through to the board */
.mull.waiting { background: rgba(4,7,12,.45); pointer-events: none; }
.mull-box {
  max-width: min(1240px, 96vw); max-height: 92vh; overflow: auto;
  background: #0f151f; border: 1px solid var(--edge); border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0,0,0,.8);
  padding: 18px 22px 20px; text-align: center;
}
.mull-head {
  font-size: 11px; color: var(--dim);
  text-transform: uppercase; letter-spacing: .08em;
}
.mull-note { margin: 6px 0 16px; font-size: 15px; }
.mull-cards {
  display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;
  margin-bottom: 18px;
}
.mull-cards .card {
  height: 250px; width: auto; flex: 0 0 auto; cursor: pointer;
}
/* going to the bottom of the deck: dimmed and pushed down, the way you would
   slide one out of a fan */
.mull-cards .card.picked {
  outline: 2px solid var(--warn); outline-offset: 2px;
  transform: translateY(10px); opacity: .55;
}
.mull-row { display: flex; gap: 10px; justify-content: center; }
.mull-row button { padding: 9px 18px; font-size: 14px; }
.mull-go {
  background: var(--accent); color: #07101f; border-color: var(--accent);
  font-weight: 600;
}
.mull-go:disabled { opacity: .4; cursor: default; }
.mull-go:not(:disabled):hover { filter: brightness(1.12); }

/* ---- hover peek ----
   A stack occupant, a hand card and a search-list row are all too small to
   read where they sit. Hovering any of them opens the card without moving
   anything, host first. Above #finder (200) so it works over the search. */
#peek {
  position: fixed; z-index: 300; pointer-events: none;
  display: flex; gap: 8px; padding: 8px;
  background: rgba(10,14,22,.96); border: 1px solid var(--edge);
  border-radius: 8px; box-shadow: 0 10px 30px rgba(0,0,0,.75);
}
#peek.hidden { display: none; }
/* --peek-w is set per peek: the reading panel width, less whatever a long
   stack has to give up to stay on screen. */
.peek-card { width: var(--peek-w, 300px); flex: 0 0 auto; }
/* a landscape face is a dense table of text -- a Statute, a Storyline, the
   Galactic Factors track -- so it gets the width it needs to be read */
.peek-card.wide { width: calc(var(--peek-w, 300px) * 2.15); }
.peek-art { position: relative; }
.peek-card img { width: 100%; height: auto; display: block; border-radius: 5px; }
.peek-host img { outline: 2px solid var(--accent); outline-offset: 1px; }
/* the dice and counters ride on the separated card: which card a d10 is
   sitting on is most of the reason to open the stack */
.peek-dice {
  position: absolute; top: 6px; left: 6px; display: flex; gap: 4px;
}
.peek-dice .die-chip { min-width: 40px; height: 40px; font-size: 23px; border-radius: 7px; }
.peek-counters {
  position: absolute; bottom: 6px; left: 6px; right: 6px;
  display: flex; flex-wrap: wrap; gap: 3px;
}
.peek-counters .chip { font-size: 12px; line-height: 19px; padding: 0 6px; }
.peek-back {
  width: 100%; aspect-ratio: 5 / 7; border-radius: 5px;
  background-image: var(--back); background-size: cover; background-position: center;
}
.peek-stub {
  width: 100%; aspect-ratio: 5 / 7; border-radius: 5px; padding: 8px;
  font-size: 11px; overflow: hidden; color: #c3cee0;
  background: linear-gradient(160deg, #1c2333, #10151f);
}
.peek-cap {
  margin-top: 4px; font-size: 12px; color: var(--dim); text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.peek-host .peek-cap { color: var(--ink); }
