:root {
  --bg: #2b2b2b;
  --panel: #333335;
  --panel-2: #474749;
  --line: #5a5a5c;
  --ink: #d7d6d4;
  --muted: #8f8f92;
  --felt: #123f2e;
  --felt-line: #1c5a41;
  --accent: #d8a24a;      /* chip gold */
  --accent-ink: #1c1c1c;
  --danger: #b4483f;
  --live: #4f9e78;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
}
.hidden { display: none !important; }
.muted { color: var(--muted); }

/* ---------- brand ---------- */
.brand { font-weight: 800; font-size: 32px; letter-spacing: -1px; }
.brand span { color: var(--accent); }
.brand.small { font-size: 18px; }

/* ---------- gate ---------- */
.gate {
  min-height: 100%;
  display: grid;
  place-items: center;
  padding: 24px;
}
.gate-card {
  width: 340px;
  max-width: 100%;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 32px 28px;
  text-align: center;
}
.gate-card .tag { color: var(--muted); margin: 6px 0 24px; }
.gate .btn { display: block; width: 100%; margin: 8px 0; }
.dev { margin-top: 22px; text-align: left; color: var(--muted); }
.dev summary { cursor: pointer; font-size: 12px; }
.dev input {
  width: 100%; margin: 10px 0 8px;
  background: var(--panel-2); border: 1px solid var(--line);
  color: var(--ink); padding: 8px; border-radius: 6px;
  font-family: inherit; font-size: 12px;
}

/* ---------- buttons ---------- */
.btn {
  display: inline-block;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--ink);
  padding: 9px 14px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  transition: transform .04s ease, filter .12s ease;
}
.btn:hover { filter: brightness(1.12); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: default; }
.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.btn-danger { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn-ghost { background: transparent; }

/* ---------- app shell ---------- */
.app { display: flex; flex-direction: column; min-height: 100%; }
.top {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 18px; border-bottom: 1px solid var(--line);
}
/* ---------- top-bar equity calculator (from the original site) ---------- */
.calc {
  display: flex; align-items: center; gap: 8px;
  flex: 1 1 auto; min-width: 0; margin: 0 18px;
}
.calc-in {
  flex: 1 1 auto; min-width: 0; max-width: 460px;
  background: var(--panel-2); border: 1px solid var(--line);
  color: var(--ink); border-radius: 6px; padding: 7px 10px;
  font-family: inherit; font-size: 12px;
}
.calc-in:focus { outline: none; border-color: var(--accent); }
.calc-go { padding: 7px 12px; font-weight: 800; }
.calc-out { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.calc-cell {
  background: var(--panel-2); border: 1px solid var(--line);
  color: var(--ink); border-radius: 5px; padding: 4px 8px;
  font-size: 12px; font-weight: 800; white-space: nowrap;
}
.calc-msg { color: var(--muted); font-size: 11px; white-space: nowrap; }

.who { display: flex; align-items: center; gap: 10px; }
.who .muted { font-size: 12px; }
.points {
  font-weight: 800; color: var(--accent);
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 6px; padding: 5px 10px; font-size: 13px;
}
/* Balances are allowed to go under water and the player keeps playing, so
   this is a normal state to render, not an error one. */
.points.negative { color: var(--danger); }

.body { display: flex; flex: 1; min-height: 0; }

/* ---------- rail ---------- */
.rail {
  width: 210px; border-right: 1px solid var(--line);
  padding: 14px; overflow-y: auto;
}
.rail-head { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 10px; }
.hand-list { list-style: none; margin: 0; padding: 0; }
.hand-item {
  display: flex; justify-content: space-between; align-items: center;
  padding: 8px 10px; border: 1px solid var(--line);
  border-radius: 6px; margin-bottom: 6px; cursor: pointer; font-size: 12px;
}
.hand-item:hover { background: var(--panel-2); }
.hand-item.active { border-color: var(--accent); }
.hand-item .hid { color: var(--ink); }
.badge { font-size: 10px; padding: 2px 6px; border-radius: 4px; background: var(--panel-2); color: var(--muted); }
.badge.won { color: var(--live); }
.badge.lost { color: var(--danger); }
.auto-join {
  display: flex; align-items: center; gap: 8px;
  margin-top: 16px; font-size: 12px; color: var(--muted); cursor: pointer;
}
.auto-join input { accent-color: var(--accent); }

/* ---------- leaderboard ---------- */
.board-head {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--line);
}
.board-list { list-style: none; margin: 0; padding: 0; }
.board-item {
  display: flex; align-items: baseline; gap: 8px;
  padding: 4px 6px; border-radius: 4px; font-size: 12px;
}
/* The rail is 210px and the aliases are long, so the columns are laid out
   rather than left to the text: a fixed rank gutter on the left, the score
   pinned to the right, and the name in the middle taking whatever is left and
   ellipsing rather than pushing the score off the edge. */
.board-item .board-rank { width: 26px; flex: none; color: var(--muted); }
.board-item .board-alias {
  flex: 1; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.board-item .board-points { flex: none; color: var(--muted); }
.board-item.me { background: var(--panel-2); }
.board-item.me .board-alias { color: var(--accent); }
.board-you { margin-top: 8px; }

/* Errors are rendered here rather than in the in-game banner, so they are
   visible in the lobby and while queued as well as at the table. */
.app-error {
  border: 1px solid var(--danger); color: var(--danger);
  background: rgba(180,72,63,.08);
  border-radius: 6px; padding: 9px 12px; margin-bottom: 14px; font-size: 13px;
}
.tiny { font-size: 11px; }

/* ---------- lobby ---------- */
.lobby {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px; min-height: 60vh; text-align: center;
}
.btn-play { font-size: 20px; padding: 16px 56px; }
.waiting { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.spinner {
  width: 28px; height: 28px; border-radius: 50%;
  border: 3px solid var(--line); border-top-color: var(--accent);
  animation: spin 1s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 4s; } }
.lobby-note { font-size: 12px; max-width: 320px; }

/* ---------- table ---------- */
.table-wrap { flex: 1; padding: 22px; min-width: 0; }
.banner-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 10px;
}
.banner { min-height: 18px; }
.clock {
  font-size: 12px; font-weight: 800; color: var(--muted);
  border: 1px solid var(--line); border-radius: 6px; padding: 4px 9px;
  white-space: nowrap;
}
/* The turn clock is real -- run it out and somebody else's poll folds you --
   so it gets loud before it matters. */
.clock.urgent { color: var(--danger); border-color: var(--danger); }

/* The game string the server is holding, shown verbatim above the table. */
.uhand {
  font-size: 11px; color: var(--muted); word-break: break-all;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 6px; padding: 8px 10px; margin-bottom: 16px;
  max-height: 54px; overflow-y: auto;
}

/* An actual oval with the seats placed around its rim. The seat positions
   are set from JS (see positionSeats) because the angle between seats
   depends on how many are in the hand. */
.felt {
  position: relative;
  background:
    radial-gradient(120% 100% at 50% 0%, var(--felt-line), var(--felt) 60%);
  border: 1px solid var(--felt-line);
  border-radius: 50% / 50%;
  aspect-ratio: 16 / 9;
  min-height: 440px;
  margin: 0 auto 22px;
  max-width: 900px;
}
.table-center {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  width: 58%;
}
.seats { position: absolute; inset: 0; }
/* Under the seats: a marker is inside the seat ring and never reaches one,
   but a big pile should not be able to cover a stack size if it ever does. */
.markers { position: absolute; inset: 0; }
.felt-meta { display: flex; justify-content: space-between; margin-bottom: 16px; }
.pot { font-weight: 800; color: var(--accent); }
.street { color: #9fd3ba; text-transform: uppercase; letter-spacing: 2px; font-size: 12px; }
.board { display: flex; gap: 10px; justify-content: center; }

/* ---------- cards ---------- */
.card {
  position: relative;
  width: 42px; height: 58px;
  background: #f4f1ea; color: #1c1c1c;
  border-radius: 6px;
  display: flex; align-items: flex-start; justify-content: flex-start;
  padding: 6px 7px; font-weight: 800; font-size: 16px;
  box-shadow: 0 2px 0 rgba(0,0,0,.35);
}
.card.red { color: #b4302a; }
.card .suit { position: absolute; bottom: 5px; right: 7px; font-size: 15px; }
.card.back {
  background: repeating-linear-gradient(45deg, #3a3a5a, #3a3a5a 4px, #2f2f4d 4px, #2f2f4d 8px);
  color: transparent; box-shadow: inset 0 0 0 2px #575787, 0 2px 0 rgba(0,0,0,.35);
}
.card.slot { background: transparent; box-shadow: inset 0 0 0 1px var(--felt-line); }

/* ---------- seats ---------- */
.seat {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 116px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); padding: 8px;
  box-shadow: 0 3px 10px rgba(0,0,0,.35);
}
.seat.acting { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.seat.folded { opacity: .4; }
.seat-head { display: flex; justify-content: space-between; margin-bottom: 8px; font-size: 12px; }
.seat-id { color: var(--muted); }
.seat-stack { font-weight: 800; }
.hole { display: flex; gap: 6px; }
.hole .card { width: 34px; height: 46px; font-size: 13px; padding: 4px 5px; }
.hole .card .suit { font-size: 12px; bottom: 3px; right: 5px; }
/* What the seat did, on its own line under the cards. It keeps its height
   when there is nothing to say, so a seat does not grow and shrink -- and the
   ring does not jitter -- as the action goes round. */
.act {
  margin-top: 6px; min-height: 13px; line-height: 13px;
  font-size: 11px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 1px;
  color: var(--muted);
}
.act-check { color: #9fd3ba; }
.act-call { color: #9fd3ba; }
.act-bet, .act-raise { color: var(--accent); }
.act-allin { color: var(--accent); }
.act-fold { color: var(--muted); }

.seat.mine { border-color: var(--ink); }
.seat.mine .seat-id { color: var(--ink); }
/* A bot seat reads as a seat, just not as a person: same box, dashed edge. */
.seat.bot { border-style: dashed; }
.seat.bot .seat-id { font-style: italic; }
/* A chair nobody sat in. It was dealt and folded like any other seat, so it
   is drawn like any other folded seat -- just quieter, and without a name or
   a stack that would suggest somebody is holding it. */
.seat.vacant { background: transparent; box-shadow: none; border-style: dotted; }
.seat.vacant .seat-id, .seat.vacant .seat-stack { color: var(--muted); font-weight: 400; }
.bet {
  margin-top: 8px; font-size: 12px; font-weight: 800; color: var(--accent);
}
/* The chips on the felt already say this on a wide screen. */
@media (min-width: 721px) { .seat .bet { display: none; } }
.won { margin-top: 8px; color: var(--live); font-weight: 800; font-size: 13px; }
.lost { margin-top: 8px; color: var(--danger); font-weight: 800; font-size: 13px; }

/* ---------- dealer button and chips ---------- */
/* One marker per seat, centred on a ring inside the seats. The chips sit on
   the baseline so a pile grows upward from the felt, the way a real one does,
   and the button sits beside them. */
.marker {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex; align-items: flex-end; gap: 7px;
  pointer-events: none;
}
.marker.folded { opacity: .45; }

.dealer-btn {
  width: 22px; height: 22px; border-radius: 50%;
  background: #f4f1ea; color: #1c1c1c;
  font-size: 11px; font-weight: 800; letter-spacing: 0;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 4px rgba(0,0,0,.45), inset 0 0 0 2px rgba(0,0,0,.18);
}

.chips { display: flex; align-items: flex-end; gap: 3px; }
/* A column is as tall as its own pile, so every pile in a row shares a
   baseline no matter how many chips are in it. */
.chip-col { position: relative; width: 14px; flex: none; }
.chip {
  position: absolute; left: 0;
  width: 14px; height: 14px; border-radius: 50%;
  /* The dashes are the edge markings; the inset ring is the rim, and the drop
     shadow is what separates one chip from the one under it. */
  box-shadow: 0 1px 1px rgba(0,0,0,.5);
}
.chip.one {
  background: #efece4;
  border: 1px solid #b9b5aa;
}
.chip.five {
  background: #b4302a;
  border: 1px solid #7d1d19;
}
.chip-amt {
  font-size: 11px; font-weight: 800; color: var(--accent);
  text-shadow: 0 1px 2px rgba(0,0,0,.6);
  line-height: 14px;
}

/* The narrow layout has no ring to hang markers on, so the seat box carries
   the button itself. */
.seat-d {
  display: none;
  width: 15px; height: 15px; border-radius: 50%;
  background: #f4f1ea; color: #1c1c1c;
  font-size: 9px; font-weight: 800; line-height: 15px; text-align: center;
  margin-left: 6px;
}

/* ---------- actions ---------- */
.actions {
  border-top: 1px solid var(--line);
  padding-top: 16px;
}
/* The bet row is no longer pinned to the width of the buttons above it. It
   was, so the slider read as belonging to Bet/Raise rather than stretching the
   panel -- but the slider now carries the sizing curve, and at the width of
   two short buttons (~130px) that curve had a couple of pixels per bet to
   work with. It gets the room instead, capped so it does not run the width of
   a desktop. */
.bet-row {
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 12px;
  width: 100%;
  max-width: 560px;
}
/* The slider, with the sizing density standing on it. The curve is an area
   whose baseline IS the track, so the two are read together -- height over a
   point on the track is how often the model raises to that size.

   The SVG stretches to whatever width the row is (preserveAspectRatio=none on
   a 0..100 viewBox), so nothing here has to measure anything. Its bottom edge
   is pulled down onto the top of the track by the negative margin.

   Inset by half a thumb at each end, which is the whole reason --thumb-w
   exists. A range input's thumb does NOT travel the full width of the track:
   its CENTRE runs from thumb/2 to width - thumb/2, because the thumb has to
   stay inside the control at both extremes. An SVG spanning the full width
   therefore puts a given bet size up to half a thumb away from the thumb that
   selects it -- 6px of drift on a control whose whole curve can be 20px wide.
   Narrowing the SVG to exactly the thumb's travel makes its 0..100 the same
   axis the value runs on, so a size on the curve is under the handle that
   picks it. */
.bet-slider { position: relative; --thumb-w: 12px; }
.bet-curve {
  display: block; height: 36px;
  width: calc(100% - var(--thumb-w));
  margin-left: calc(var(--thumb-w) / 2);
  /* onto the track's top edge: the input is 20px tall around a 6px track */
  margin-bottom: -7px;
  overflow: visible; pointer-events: none;
}
.bet-curve .curve-fill { fill: var(--accent); opacity: .22; }
.bet-curve .curve-line {
  fill: none; stroke: var(--accent); stroke-width: 1.5;
  stroke-linejoin: round; opacity: .8;
}
/* Where the handle cuts the curve: a line up from the track to the curve at
   the bet currently set, so the number in the box and the height of the curve
   are tied together by something you can see. Stops AT the curve rather than
   running the full height -- its length is the reading. */
.bet-curve .curve-mark {
  stroke: var(--danger); stroke-width: 1.5; opacity: .95;
}
.bet-curve .curve-mark-dot { fill: var(--danger); }

.bet-row input[type=range] {
  width: 100%; height: 20px; margin: 0;
  -webkit-appearance: none; appearance: none;
  background: transparent; cursor: pointer;
  position: relative;   /* over the curve, so the thumb stays grabbable */
}
.bet-row input[type=range]:focus { outline: none; }
.bet-row input[type=range]::-webkit-slider-runnable-track {
  height: 6px; border-radius: 3px;
  border: 1px solid var(--line); background: var(--panel-2);
}
.bet-row input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  /* centres the thumb on the track: (6px track - 18px thumb) / 2 */
  width: var(--thumb-w); height: 18px; margin-top: -6px;
  border-radius: 3px;
  background: var(--ink); border: 1px solid var(--bg);
  box-shadow: 0 1px 3px rgba(0,0,0,.5);
}
.bet-row input[type=range]::-moz-range-track {
  height: 6px; border-radius: 3px;
  border: 1px solid var(--line); background: var(--panel-2);
}
.bet-row input[type=range]::-moz-range-thumb {
  width: var(--thumb-w); height: 18px; border: 1px solid var(--bg);
  border-radius: 3px; background: var(--ink);
  box-shadow: 0 1px 3px rgba(0,0,0,.5);
}
.bet-row input[type=range]:focus-visible::-webkit-slider-thumb,
.bet-row input[type=range]:focus-visible::-moz-range-thumb {
  border-color: var(--accent);
}
.bet-figures { display: flex; align-items: center; gap: 10px; }
.bet-figures .bet-input { flex: 1; min-width: 0; }
.bet-input {
  width: 110px; background: var(--panel-2); border: 1px solid var(--line);
  color: var(--ink); padding: 7px; border-radius: 6px; font-family: inherit;
}
/* Hug the buttons instead of stretching across the panel, so the bet row
   below can line up with them exactly. */
.action-btns {
  display: flex; gap: 10px; flex-wrap: wrap;
  width: fit-content; max-width: 100%;
}

/* ---------- learning mode ---------- */
/* The model's rate for an action, on the button that takes it. A button with
   a rate is two stacked lines rather than one, and every button in the row
   grows the same way whether or not it has one -- otherwise the row's
   baselines move as the rates arrive a moment after the buttons do. */
.btn-rate {
  display: block; margin-top: 3px;
  font-size: 11px; font-weight: 800; letter-spacing: .5px;
  opacity: .85;
}
.btn-rate.none { opacity: .45; }
/* A rate the player can read without reading: the button fills from the left
   in proportion to how often the model takes it. Behind the label, and low
   contrast, because the label is still the thing being clicked. */
.btn-meter {
  position: absolute; left: 0; top: 0; bottom: 0;
  background: currentColor; opacity: .13;
  pointer-events: none;
}
.action-btns .btn { position: relative; overflow: hidden; }


@media (max-width: 900px) {
  /* The calculator is a whole second row on a narrow screen rather than
     squeezing the brand and the sign-in buttons off the edge. */
  .top { flex-wrap: wrap; }
  .calc { order: 3; flex-basis: 100%; margin: 10px 0 0; }
}

@media (max-width: 720px) {
  .body { flex-direction: column; }
  /* The felt and the buttons come FIRST on a phone. Stacking the columns in
     source order put the hand rail and the whole leaderboard above the table,
     so every hand opened scrolled past the thing being played -- and the
     action buttons, which are the one part of this page that is timed, landed
     furthest down the page. Ordering rather than moving the markup: the wide
     layout wants the rail on the left, where source order is what puts it. */
  .table-wrap { order: 1; }
  .rail {
    order: 2; width: auto;
    border-right: none; border-top: 1px solid var(--line);
  }

  /* No room for an oval on a phone. Going back to static positioning also
     makes the browser ignore the inline left/top JS set for the rim. */
  .felt {
    aspect-ratio: auto; min-height: 0;
    border-radius: 18px; padding: 18px;
  }
  .table-center { position: static; transform: none; width: auto; }
  .seats {
    position: static;
    display: grid; grid-template-columns: repeat(auto-fill, minmax(116px, 1fr));
    gap: 10px; margin-top: 18px;
  }
  .seat { position: static; transform: none; width: auto; }
  /* Inline left/top are ignored once .seats is a static grid, so the markers
     would all pile up in the middle of the felt. The seat shows its own D and
     its own bet instead. */
  .markers { display: none; }
  .seat-head { align-items: center; }
  .seat-d { display: inline-block; }
}

/* ---------- equity strip (client-side WASM result, showdown only) ---------- */
.equity-strip {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 16px; padding-top: 14px;
  border-top: 1px dashed var(--felt-line);
}
.eq-label { color: #9fd3ba; text-transform: uppercase; letter-spacing: 2px; font-size: 11px; }
.eq-cell {
  background: rgba(0,0,0,.25); border: 1px solid var(--felt-line);
  color: #eafff5; border-radius: 6px; padding: 5px 10px;
  font-weight: 800; font-size: 13px;
}

/* ---- reviewing a finished hand from the rail -------------------------- */
/* .hand-item already has the pointer and hover; only the empty placeholder
   needs opting out of looking clickable. */
.hand-item.muted { cursor: default; }
.hand-item.muted:hover { background: none; }

.hand-modal {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .55); padding: 16px;
}
.hand-card {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 10px; padding: 16px; width: min(680px, 100%);
  max-height: 80vh; display: flex; flex-direction: column; gap: 8px;
}
.hand-card-head { display: flex; align-items: center; gap: 10px; }
.hand-card-title { font-weight: 800; }
.hand-card-x { margin-left: auto; font-size: 20px; line-height: 1; padding: 0 8px; }
.hand-card-label { text-transform: uppercase; letter-spacing: .08em; }
/* The u_hand is long and must stay readable and selectable: wrap it rather
   than making the dialog scroll sideways. */
.hand-card-text {
  margin: 0; overflow: auto; max-height: 46vh;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: 8px; padding: 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px; line-height: 1.5; white-space: pre-wrap; word-break: break-all;
  user-select: text;
}
.hand-card-foot { display: flex; gap: 8px; }
