:root {
  --felt-1: #1f6f43;
  --felt-2: #14492c;
  --felt-edge: #0d3020;
  --card: #fbfbf7;
  --card-edge: #c9c9c0;
  --ink: #1b1b1b;
  --red: #c0392b;
  --gold: #e6b422;
  --back-1: #24427a;
  --back-2: #16294d;
  --muted: rgba(255, 255, 255, 0.72);
  --radius: 9px;
  --card-w: 74px;
  --card-h: 104px;
  /* Spacing between cards in a hand.  The palace fan uses the same step, so the
     two read as the same kind of row (app.js reads this value too). */
  --hand-gap: 8px;
  --shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
  color: #fff;
  background: radial-gradient(ellipse at 50% 40%, var(--felt-1), var(--felt-2) 70%, var(--felt-edge));
}

body {
  display: grid;
  grid-template-rows: auto 1fr;
  grid-template-columns: 1fr 260px;
  grid-template-areas:
    "top top"
    "table log";
  height: 100vh;
  /* The board is laid out to fit the viewport; only the log scrolls. */
  overflow: hidden;
}

/* ------------------------------------------------------------------ top bar */
.topbar {
  grid-area: top;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 10px 18px;
  background: rgba(0, 0, 0, 0.28);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.topbar h1 { font-size: 20px; margin: 0; letter-spacing: 2px; text-transform: uppercase; }
.status { display: flex; flex-direction: column; gap: 2px; flex: 1; }
#turn-info { font-size: 13px; color: var(--muted); }
.requirement { font-size: 15px; font-weight: 600; }
.requirement.beat::before { content: "▲ "; color: var(--gold); }
.requirement.lower::before { content: "▼ "; color: var(--gold); }
.requirement.any::before { content: "◆ "; color: var(--gold); }

/* click preference in the top bar */
.pref {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}
.pref input {
  appearance: none;
  width: 34px;
  height: 18px;
  border-radius: 9px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.15);
  position: relative;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.pref input::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.15s;
}
.pref input:checked { background: var(--gold); border-color: var(--gold); }
.pref input:checked::after { transform: translateX(16px); }
.pref input:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.btn {
  font: inherit;
  padding: 8px 16px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  cursor: pointer;
  transition: background 0.15s, transform 0.05s;
}
.btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.22); }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn.scoop { border-color: var(--gold); color: var(--gold); }

/* -------------------------------------------------------------------- table */
.table {
  grid-area: table;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 10px;
  padding: 12px 24px;
  align-items: center;
  justify-items: center;
  min-height: 0;
  overflow: hidden;
}

.seat { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.seat-label { font-size: 13px; color: var(--muted); }
.seat-label .name { font-weight: 700; color: #fff; }
.seat-label.active .name { color: var(--gold); }
.seat-label .counts { margin-left: 8px; }

/* Opponents sit in a single row across the top; up to three seats fit.  Their
   cards are drawn smaller and their face-down hands are fanned, because three
   full-size seats with spread hands wrapped onto two rows and pushed the
   player's own hand below the fold.  --card-w/--card-h are overridden in JS to
   the width the row actually has, so these are just the starting values. */
.opponents {
  --card-w: 44px;
  --card-h: 62px;
  display: flex;
  gap: 24px;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: wrap;
  width: 100%;
  /* On a genuinely narrow board (the log takes 260px) three seats cannot fit on
     one row even at the smallest card size.  Capping the row keeps a wrapped
     row from eating the board and pushing the player's own hand off the
     bottom; the extra seats scroll instead. */
  max-height: 30vh;
  overflow-y: auto;
  scrollbar-width: thin;
}
.opponents .seat { gap: 6px; }
.opponents .seat .seat-label { font-size: 12px; }

/* A fanned row: cards are absolutely positioned so the row is one card wide
   plus the fan offsets rather than one column per card.  The width is set in
   JS; the min-height keeps the row as tall as a card, since absolutely
   positioned children would otherwise collapse it. */
.fan { position: relative; gap: 0; min-height: var(--card-h); }
.fan .card { position: absolute; top: 0; left: 0; }

/* The two palaces are one fan instead of two rows of cards.  Each of its three
   slots is an upper/lower PAIR: the face-up upper palace card, with the
   face-down lower palace card behind it and offset down so just its edge shows
   underneath.  Slots are spaced exactly like the cards in a hand (--hand-gap),
   so the palace reads as three of the same slots rather than two unrelated
   groups.  A palace holds at most three cards (engine.PALACE_SIZE).  layoutDeck
   in app.js places the cards and sets the width, because it depends on how many
   cards each palace still holds; the height is fixed here so the board does not
   jump.  Hover the fan for which layer is which. */
.palace-deck {
  position: relative;
  /* Fallback before layoutDeck measures it: three slots at hand spacing, plus
     the sideways peek of the face-down card (DECK_SHIFT_RATIO in app.js). */
  width: calc(var(--card-w) * 3 + var(--hand-gap) * 2 + var(--card-w) * 0.06);
  height: calc(var(--card-h) + var(--card-w) * 0.14);
}
.palace-deck .cards { position: absolute; inset: 0; }
.palace-deck .card { position: absolute; top: 0; left: 0; }
/* Before the palaces are filled (setup) the empty box would still reserve a
   card's height, which the board does not have to spare. */
.palace-deck.empty { height: 0; }
.palace-deck.empty .deck-badge { display: none; }

/* An opponent's palace cards are hidden, so the fan says what it holds instead
   of showing them.  Absolutely positioned so the badge costs the seat no width
   or height, and it sits over card backs only. */
.deck-badge {
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: 20;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: #fff;
  background: rgba(0, 0, 0, 0.55);
  border-radius: 999px;
  padding: 1px 6px;
  pointer-events: none;
}

.hand { display: flex; gap: var(--hand-gap); min-height: var(--card-h); }

/* -------------------------------------------------------------------- cards */
.card {
  position: relative;
  width: var(--card-w);
  height: var(--card-h);
  border-radius: var(--radius);
  background: var(--card);
  border: 1px solid var(--card-edge);
  box-shadow: var(--shadow);
  color: var(--ink);
  user-select: none;
  transition: transform 0.15s, box-shadow 0.15s;
}
.card.red { color: var(--red); }

.card .corner {
  position: absolute;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.card .corner.tl { top: 6px; left: 7px; }
.card .corner.br { bottom: 6px; right: 7px; transform: rotate(180deg); }
.card .corner .pip { font-size: 13px; }
.card .center-pip {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 34px;
}

.card.back {
  background: repeating-linear-gradient(
    45deg,
    var(--back-1) 0 6px,
    var(--back-2) 6px 12px
  );
  border-color: #0c1830;
}
.card.back::after {
  content: "";
  position: absolute;
  inset: 5px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 6px;
}

.card.special::before {
  content: "★";
  position: absolute;
  top: -7px;
  right: -7px;
  width: 18px;
  height: 18px;
  font-size: 11px;
  display: grid;
  place-items: center;
  color: #3a2a00;
  background: var(--gold);
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  z-index: 2;
}

/* player hand interactivity */
.hand .card.playable { cursor: pointer; }
.hand .card.playable:hover { transform: translateY(-10px); box-shadow: 0 12px 22px rgba(0, 0, 0, 0.45); }
.hand .card.dim { opacity: 0.45; filter: grayscale(0.4); }
.hand .card.selected { transform: translateY(-14px); outline: 2px solid var(--gold); }

/* pile + stock */
.center { display: flex; align-items: center; gap: 40px; }
.stock, .pile-wrap { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.stock-pile, .pile { position: relative; min-width: var(--card-w); }
/* Both the pile and the stock are overlapping fans: cards are absolutely
   positioned so each is one card tall rather than a scrolling column.  The
   min-height also reserves the fan's vertical offset (top: i * 3 / i * 2),
   otherwise the deepest card reaches into the "to beat" tag below it. */
.pile { min-height: calc(var(--card-h) + 12px); }
.stock-pile { min-height: calc(var(--card-h) + 8px); }
.pile .card, .stock-pile .card { position: absolute; top: 0; left: 0; }
.stock-count, .pile-count { font-size: 12px; color: var(--muted); }

/* The pile card the next play must beat (the top card, or the one under an 8). */
.pile .card.beat { box-shadow: 0 0 0 3px var(--gold), var(--shadow); }
/* The tag sits in the pile's own column rather than on the card: the fan
   overlaps the card it marks, and a label under that card collided with the
   pile count.  It keeps its space when hidden so the count never jumps. */
.beat-tag {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: #241a00;
  background: var(--gold);
  border-radius: 999px;
  padding: 2px 7px;
  white-space: nowrap;
}
.beat-tag.off { visibility: hidden; }

/* action buttons under the pile */
.controls { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.pick-hint { font-size: 11px; color: var(--gold); min-height: 14px; }

/* animations */
@keyframes deal-in { from { opacity: 0; transform: translateY(24px) scale(0.9); } to { opacity: 1; } }
@keyframes flip { from { transform: rotateY(90deg); } to { transform: rotateY(0); } }
@keyframes pop { 0% { transform: scale(1); } 40% { transform: scale(1.18); } 100% { transform: scale(1); } }
.card.deal-in { animation: deal-in 0.3s ease; }
.card.flip { animation: flip 0.3s ease; }
.card.pop { animation: pop 0.3s ease; }

/* ---------------------------------------------------------------------- log */
.log {
  grid-area: log;
  background: rgba(0, 0, 0, 0.3);
  border-left: 1px solid rgba(255, 255, 255, 0.08);
  padding: 12px 14px;
  overflow-y: auto;
  font-size: 13px;
  line-height: 1.5;
}
.log h3 { margin: 0 0 8px; font-size: 12px; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); }
.log ul { list-style: none; margin: 0; padding: 0; }
.log li { padding: 3px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.05); }
.log li.special { color: var(--gold); }
.log li.you { color: #bfe6c8; }

/* ------------------------------------------------------------- room chrome */
.room-chip {
  font-size: 13px;
  color: var(--muted);
  padding: 4px 10px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 999px;
}
.btn.primary { background: var(--gold); color: #241a00; border-color: var(--gold); font-weight: 700; }
.btn.primary:hover:not(:disabled) { background: #f2c53a; }
.btn.ghost { background: transparent; }

/* ------------------------------------------------------- lobby / waiting */
.overlay {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(0, 0, 0, 0.55);
  z-index: 55;
}
/* Same reason as the banner: an explicit display beats [hidden]. */
.overlay[hidden] { display: none; }
.panel {
  width: min(420px, 92vw);
  background: var(--felt-2);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 14px;
  padding: 26px 30px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.panel h2 { margin: 0; font-size: 26px; letter-spacing: 1px; }
.field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--muted); }
.panel input {
  font: inherit;
  padding: 9px 12px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(0, 0, 0, 0.25);
  color: #fff;
}
.panel input:focus { outline: 2px solid var(--gold); }
.divider { text-align: center; color: var(--muted); font-size: 12px; margin: 4px 0; }
.joinrow { display: flex; gap: 8px; }
.joinrow input { flex: 1; text-transform: uppercase; letter-spacing: 3px; }
.hint { color: var(--muted); font-size: 12px; margin: 0; }
.code-line { margin: 0; font-size: 14px; color: var(--muted); }
.code {
  font-weight: 800;
  letter-spacing: 4px;
  font-size: 22px;
  color: var(--gold);
  margin-left: 6px;
}
.players { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.players li { padding: 8px 12px; background: rgba(0, 0, 0, 0.22); border-radius: 8px; font-weight: 600; }
.players li.cpu { color: var(--muted); font-style: italic; }
.players li .tag { margin-left: 8px; font-size: 11px; color: var(--gold); font-weight: 400; }
.wait-actions { display: flex; gap: 10px; }

/* --------------------------------------------------- fit short viewports */
/* Shrink the cards so opponents + centre + hand stay on one screen. */
@media (max-height: 820px) { :root { --card-w: 62px; --card-h: 88px; } }
@media (max-height: 700px) {
  :root { --card-w: 52px; --card-h: 74px; }
  .table { gap: 6px; padding: 8px 16px; }
  .opponents { gap: 20px; }
}

/* ------------------------------------------------------------------- banner */
.banner {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(0, 0, 0, 0.6);
  z-index: 50;
}
/* An explicit display overrides the [hidden] attribute's UA display:none, so
   re-assert it or the invisible overlay swallows every click. */
.banner[hidden] { display: none; }
.banner-inner {
  background: var(--felt-2);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 14px;
  padding: 28px 40px;
  text-align: center;
  box-shadow: var(--shadow);
}
.banner-inner h2 { margin: 0 0 8px; font-size: 28px; }
.banner-inner p { margin: 0 0 18px; color: var(--muted); }

/* -------------------------------------------------------------------- toast */
.toast {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  background: #7a1f1f;
  color: #fff;
  padding: 10px 18px;
  border-radius: 8px;
  box-shadow: var(--shadow);
  z-index: 60;
}

@media (max-width: 720px) {
  body { grid-template-columns: 1fr; grid-template-areas: "top" "table" "log"; }
  .log { max-height: 160px; }
  :root { --card-w: 56px; --card-h: 80px; }
}
