/* Hold'em Coach
   Black ground, hairline borders, generous tap targets. Portrait iPhone
   first, everything else secondary. */

:root {
  --bg: #000000;
  --surface: #0f0f11;
  --surface-high: #17171a;
  --line: #26262b;
  --line-soft: #1b1b1f;

  --ink: #ffffff;
  --ink-dim: #8d8d95;
  --ink-faint: #56565e;

  --accent: #3ddc97;
  --accent-soft: rgba(61, 220, 151, 0.14);
  --good: #3ddc97;
  --fine: #f0c05a;
  --mistake: #ff6f61;
  --chip: #f5c451;

  --card-face: #ffffff;
  --card-red: #e8483f;
  --card-black: #17171a;
  --card-back: #ef5350;

  --pad: 14px;
  /* Vertical rhythm. The side rail is 14px, so anything separating two
     distinct blocks matches it or beats it, and anything inside a block
     stays under it. Gaps smaller than the rail are what read as squished. */
  --v-tight: 8px;
  --v-step: 12px;
  --v-block: 20px;
  --radius-sm: 10px;
  --radius: 14px;
  --radius-lg: 18px;
  --tap: 54px;

  /* Where the light is, from -1 to 1 on each axis. Written by the tilt, and
     left at nothing when there is no gyro or the phone is lying still. */
  --tilt-x: 0;
  --tilt-y: 0;

  /* The finish on a card: a band of gloss over paper that is a shade off
     white along its length. White on white would be nothing, so the base has
     to give the band something to be brighter than. */
  --card-gloss:
    linear-gradient(104deg,
      rgba(146, 158, 176, 0) 30%,
      rgba(146, 158, 176, 0.10) 41%,
      rgba(255, 255, 255, 1) 50%,
      rgba(146, 158, 176, 0.10) 59%,
      rgba(146, 158, 176, 0) 70%),
    linear-gradient(152deg, #fcfdfe 0%, #e7ebf2 100%);
  --card-gloss-at: calc(50% - var(--tilt-x) * 25%) 0, 0 0;

  /* The back of a card, named once because both the board slots and the hand
     draw the same thing, with its own quieter band of gloss over it. */
  --card-back-art:
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.85) 0 7%, transparent 7.5%),
    radial-gradient(circle at 50% 50%, transparent 0 15%, rgba(255, 255, 255, 0.42) 15% 17%, transparent 17.5%),
    radial-gradient(circle at 50% 50%, transparent 0 27%, rgba(255, 255, 255, 0.3) 27% 28.5%, transparent 29%),
    radial-gradient(circle at 50% 50%, transparent 0 38%, rgba(255, 255, 255, 0.22) 38% 39.5%, transparent 40%),
    radial-gradient(circle at 50% 45%, #f8736a 0%, var(--card-back) 72%);
  --back-gloss:
    linear-gradient(104deg,
      rgba(255, 255, 255, 0) 38%,
      rgba(255, 255, 255, 0.26) 48%,
      rgba(255, 255, 255, 0) 58%);
  --back-gloss-at: calc(50% - var(--tilt-x) * 25%) 0, 0 0, 0 0, 0 0, 0 0, 0 0;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  /* 100% resolves against the small viewport on iOS, so when the browser
     chrome hides, the page stays short and leaves a band of dead black under
     the controls. dvh follows the viewport that is actually on screen. The
     100% above is the fallback for anything that does not know dvh. */
  height: 100dvh;
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 16px;
  line-height: 1.4;
  letter-spacing: -0.01em;
  overscroll-behavior: none;
}

body { overflow: hidden; }

#app {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

button { font: inherit; color: inherit; border: none; background: none; cursor: pointer; }

/* ---------------------------------------------------------------- top bar */

/* The climb, in the top bar. A pip per step, how much of this one is left,
   and the only number that really matters: what your stack is worth in big
   blinds, because the blinds are what kill you. */
.run-line {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  font-size: 10px;
  color: var(--ink-faint);
  font-weight: 600;
}
.run-line[hidden] { display: none; }
.run-pips { display: flex; gap: 3px; align-items: center; }
.run-pip {
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: var(--line);
}
.run-pip.done { background: var(--ink-dim); }
.run-pip.now { background: var(--accent); box-shadow: 0 0 6px rgba(61, 220, 151, 0.6); }
.run-bb { color: var(--ink-dim); font-variant-numeric: tabular-nums; }
.run-bb.low { color: var(--mistake); }


.topbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px var(--pad) var(--pad);
}

.topbar-left { display: flex; flex-direction: column; gap: 2px; line-height: 1.2; min-width: 0; }
.hand-counter { font-size: 14px; color: var(--ink); font-weight: 600; }
.hand-counter .term { color: var(--ink); text-decoration-color: rgba(61, 220, 151, 0.5); }

.level-line { display: flex; align-items: baseline; gap: 7px; }
.level-label { font-size: 11px; color: var(--ink-dim); font-weight: 600; }
.streak-label { font-size: 10px; color: var(--accent); font-weight: 700; }
.streak-label.muted { color: var(--ink-faint); font-weight: 500; }
.streak-label.hot { color: var(--chip); text-shadow: 0 0 10px rgba(245, 196, 81, 0.45); }
.streak-label.bump { animation: streak-bump 0.42s cubic-bezier(0.2, 1.3, 0.35, 1); }
.streak-label[hidden] { display: none; }

@keyframes streak-bump {
  0% { transform: scale(1); }
  40% { transform: scale(1.22); }
  100% { transform: scale(1); }
}

.level-track {
  width: 96px;
  max-width: 100%;
  height: 3px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}
.level-fill {
  height: 100%;
  width: 0;
  background: var(--accent);
  border-radius: 2px;
  transition: width 0.35s ease;
}

.topbar-nav { display: flex; gap: 4px; flex: 0 0 auto; }

.nav-btn {
  min-height: 34px;
  padding: 6px 11px;
  border-radius: 999px;
  color: var(--ink-dim);
  font-size: 13px;
  font-weight: 500;
}
.nav-btn { transition: background 0.15s ease, color 0.15s ease, transform 0.12s ease; }
.nav-btn:active { background: var(--surface-high); color: var(--ink); transform: scale(0.94); }

/* ------------------------------------------------------------------ table */

.felt {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 0 var(--pad);
  overflow: hidden;

  /* The same rings that are printed on the backs of the cards, tiled across
     the table. The point is that the table and the deck are one set rather
     than two unrelated decorations: it is the card back motif, opened out and
     laid flat. Every ring crossing the edge of the tile is drawn on the far
     side of it too, so the repeat is seamless.

     An inline SVG rather than an image file: it stays crisp at any pixel
     density, costs one line of CSS, and there is nothing extra to fetch or to
     cache for offline. Painted as backgrounds rather than as an element, so
     nothing new joins the stacking order and the cards still fly over the top
     of everything. */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'%3E%3Cg fill='none' stroke='%23ffffff' stroke-opacity='0.075' stroke-width='1.15'%3E%3Ccircle cx='30' cy='30' r='21'/%3E%3Ccircle cx='30' cy='30' r='13'/%3E%3Ccircle cx='30' cy='30' r='5.5'/%3E%3Ccircle cx='0' cy='0' r='21'/%3E%3Ccircle cx='0' cy='0' r='13'/%3E%3Ccircle cx='60' cy='0' r='21'/%3E%3Ccircle cx='60' cy='0' r='13'/%3E%3Ccircle cx='0' cy='60' r='21'/%3E%3Ccircle cx='0' cy='60' r='13'/%3E%3Ccircle cx='60' cy='60' r='21'/%3E%3Ccircle cx='60' cy='60' r='13'/%3E%3C/g%3E%3Cg fill='%23ffffff' fill-opacity='0.075'%3E%3Ccircle cx='30' cy='30' r='1.3'/%3E%3Ccircle cx='0' cy='0' r='1.3'/%3E%3Ccircle cx='60' cy='0' r='1.3'/%3E%3Ccircle cx='0' cy='60' r='1.3'/%3E%3Ccircle cx='60' cy='60' r='1.3'/%3E%3C/g%3E%3C/svg%3E"),
    radial-gradient(122% 54%
      at calc(50% + var(--tilt-x) * 11%) calc(25% + var(--tilt-y) * 9%),
      rgba(61, 220, 151, 0.05), transparent 71%);
  background-size: 60px 60px, auto;
  background-repeat: repeat, no-repeat;
  background-position:
    calc(var(--tilt-x) * -13px) calc(var(--tilt-y) * -9px),
    0 0;
}

/* Anybody who has asked their phone for more contrast gets a plain black
   table. Texture behind text is the first thing to go. */
@media (prefers-contrast: more) {
  .felt { background-image: none; }
}

/* The table in layers. Tilting the phone slides each one by a different
   amount, so they separate the way things at different distances do: the
   pattern on the cloth is furthest away and slides against the movement, the
   other players sit just above it, the board above them, and your own cards
   nearest of all and moving most. It is only ever a few pixels, because the
   point is depth rather than a visible slide.

   Transforms rather than offsets, so none of this touches layout. Every
   number resolves to zero when --tilt-x and --tilt-y are zero, which is what
   they are on a desktop, with the tilt turned off, and before the phone has
   been asked for permission. */
.opponents { transform: translate3d(calc(var(--tilt-x) * 3px), calc(var(--tilt-y) * 2px), 0); }
.middle { transform: translate3d(calc(var(--tilt-x) * 6px), calc(var(--tilt-y) * 4px), 0); }
.hero-cards-wrap { transform: translate3d(calc(var(--tilt-x) * 10px), calc(var(--tilt-y) * 6px), 0); }

/* Nobody who has asked for less movement gets any of it, whatever the setting
   says and whatever the sensor is reporting. */
@media (prefers-reduced-motion: reduce) {
  :root { --tilt-x: 0; --tilt-y: 0; }
  .opponents, .middle, .hero-cards-wrap { transform: none; }
}

/* ------------------------------------------------------------- opponents */

.opponents {
  flex: 0 0 auto;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 2px;
  flex-wrap: wrap;
}

.seat {
  position: relative;
  flex: 1 1 0;
  min-width: 56px;
  max-width: 84px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 10px 2px 4px;
  transition: opacity 0.4s ease, transform 0.3s cubic-bezier(0.2, 0.8, 0.3, 1);
}

.seat.folded { opacity: 0.28; transform: scale(0.94); }
.seat.acting { transform: translateY(-2px); }
.seat.winner { transform: scale(1.05); animation: winner-glow 1.5s ease-out 1; }

@keyframes winner-glow {
  0% { transform: scale(1); }
  35% { transform: scale(1.11); }
  100% { transform: scale(1.05); }
}

/* A caret over whoever is thinking, instead of a box around them. */
.seat-marker {
  position: absolute;
  top: 0;
  left: 50%;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid var(--ink);
  opacity: 0;
  transform: translate(-50%, -5px);
  transition: opacity 0.24s ease, transform 0.24s cubic-bezier(0.2, 0.9, 0.3, 1);
}
.seat.acting .seat-marker { opacity: 1; transform: translate(-50%, 0); }
.seat.acting .seat-marker { animation: marker-breathe 1.9s ease-in-out infinite; }
.seat.winner .seat-marker {
  opacity: 1;
  transform: translate(-50%, 0);
  border-top-color: var(--chip);
  animation: none;
}

@keyframes marker-breathe {
  0%, 100% { transform: translate(-50%, 0); }
  50% { transform: translate(-50%, 3px); }
}

.seat-avatar {
  font-size: 34px;
  line-height: 1;
  display: block;
}

.seat-name {
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-dim);
  margin-top: 5px;
  transition: color 0.3s ease;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.seat.acting .seat-name { color: var(--ink); }
.seat.winner .seat-name { color: var(--chip); }

.seat-stack {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  transition: color 0.3s ease;
}

/* Dealer button, blind marker and last action, on one row under the stack. */
.seat-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 15px;
  margin-top: 3px;
}

.seat-tag {
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  border-radius: 999px;
  font-size: 8px;
  font-weight: 800;
  letter-spacing: 0.02em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.seat-tag.dealer { background: var(--ink); color: #000; }
.seat-tag.blind { border: 1px solid var(--line); color: var(--ink-dim); }
.seat-tag.blind.big { color: var(--chip); border-color: rgba(245, 196, 81, 0.4); }
.seat-tag.start { border: 1px solid rgba(61, 220, 151, 0.45); color: var(--accent); }

.seat-action {
  font-size: 9px;
  line-height: 12px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.seat-hole { display: flex; gap: 2px; min-height: 20px; margin-top: 3px; }

.mini-card {
  width: 14px;
  height: 20px;
  border-radius: 3px;
  background: var(--card-back);
  border: 1px solid #ffffff;
}



.mini-card.face {
  background: var(--card-face);
  border-color: var(--card-face);
  color: var(--card-black);
  font-size: 9px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.mini-card.face.red { color: var(--card-red); }
/* Two glyphs where the others have one, in a box twelve pixels wide. */
.mini-card.face.ten { font-size: 7px; letter-spacing: -0.06em; }

.seat-bet {
  margin-top: 4px;
  transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.2, 0.9, 0.3, 1);
  min-width: 24px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--surface-high);
  font-size: 11px;
  font-weight: 700;
  color: var(--chip);
  font-variant-numeric: tabular-nums;
  line-height: 1.35;
}
.seat-bet.empty { visibility: hidden; opacity: 0; transform: translateY(-6px) scale(0.85); }
.seat-bet.pop { animation: chip-pop 0.34s cubic-bezier(0.2, 1.3, 0.4, 1) both; }

@keyframes chip-pop {
  from { transform: translateY(-9px) scale(0.7); opacity: 0; }
  to { transform: translateY(0) scale(1); opacity: 1; }
}

/* A copy of a bet chip sliding into the middle when a street closes. */
.chip-ghost {
  position: fixed;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--surface-high);
  color: var(--chip);
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  opacity: 1;
  transition: transform 0.58s cubic-bezier(0.35, 0, 0.2, 1), opacity 0.58s ease-in;
}
.seat-bet.win { color: var(--good); background: rgba(61, 220, 151, 0.12); }
.seat-bet.lose { color: var(--mistake); background: rgba(255, 111, 97, 0.1); }

/* ----------------------------------------------------------- board / pot */

.middle {
  /* The table does not grow to swallow spare height. It sits under the seats
     at its own size and the surplus falls below it, as one gap between the
     table and the commentary, rather than as two large voids stranding the
     board in the middle of the screen. On a short screen there is no surplus
     and the auto margin is nothing. */
  /* Shrinks last, not first. When the screen runs out of room the coach is
     the thing that gives way, because it scrolls and the board cannot: a
     squeezed board just overflows its own padding and touches the seats. */
  flex: 0 1 auto;
  margin-bottom: auto;
  min-height: 76px;
  /* A floor under the board's breathing room. Above this the middle is the
     elastic part of the table and absorbs whatever is left over. */
  padding: var(--v-tight) 0;
  display: flex;
  align-items: center;
  /* The board hugs the left rail and the pot the right one, so this row lines
     up with every other block on the screen. Centring it left the board inset
     by a different amount at every width, which is what made the table look
     like it was on its own grid. */
  justify-content: space-between;
  gap: 12px;
}

/* Board width drives board height through the card aspect ratio, so an
   uncapped board on a wide phone eats the vertical budget and ends up
   touching the seats. */
.board { display: flex; gap: 5px; flex: 1 1 auto; max-width: 300px; perspective: 1100px; }

.slot {
  flex: 1 1 0;
  aspect-ratio: 5 / 7;
  position: relative;
}

.slot-inner {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateY(0deg);
  transition: transform 0.62s cubic-bezier(0.2, 0.8, 0.25, 1);
}
.slot.revealed .slot-inner { transform: rotateY(180deg); }

.slot-face {
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  padding: 5px 6px;
  font-weight: 700;
  line-height: 1;
  overflow: hidden;
}

.card.back,
.slot-face.back {
  background-image: var(--back-gloss), var(--card-back-art);
  background-size: 320% 100%, auto, auto, auto, auto, auto;
  background-repeat: no-repeat;
  background-position: var(--back-gloss-at);
  border: 3px solid var(--card-face);
  padding: 0;
}

.slot-face.front {
  background-color: var(--card-face);
  background-image: var(--card-gloss);
  background-size: 320% 100%, auto;
  background-repeat: no-repeat, no-repeat;
  background-position: var(--card-gloss-at);
  color: var(--card-black);
  transform: rotateY(180deg);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
}
.slot-face.front.red { color: var(--card-red); }
.slot-face .rank { font-size: 21px; letter-spacing: -0.03em; }
/* A ten is the one rank that needs to pull itself in a little. */
.slot-face.ten .rank { letter-spacing: -0.07em; }
.card.ten .rank { letter-spacing: -0.07em; }
.slot-face .suit { font-size: 15px; }

/* Hero cards and the tiny seat cards keep the flat treatment. */
.card {
  flex: 1 1 0;
  aspect-ratio: 5 / 7;
  border-radius: var(--radius);
  background-color: var(--card-face);
  background-image: var(--card-gloss);
  background-size: 320% 100%, auto;
  background-repeat: no-repeat, no-repeat;
  background-position: var(--card-gloss-at);
  color: var(--card-black);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  padding: 5px 6px;
  font-weight: 700;
  line-height: 1;
  user-select: none;
  overflow: hidden;
}

.card .rank { font-size: 21px; letter-spacing: -0.03em; }
.card .suit { font-size: 15px; }
.card.red { color: var(--card-red); }

.card.empty {
  background: transparent;
  border: 1px solid var(--line-soft);
}

/* Cards flying out from the middle of the table at the start of a hand. */
.handout { animation: handout 0.38s cubic-bezier(0.2, 0.85, 0.3, 1) both; }

@keyframes handout {
  from {
    opacity: 0;
    transform: translate3d(var(--deal-x, 0), var(--deal-y, 0), 0) scale(0.5) rotate(9deg);
  }
  to { opacity: 1; transform: translate3d(0, 0, 0) scale(1) rotate(0); }
}

.pot-box { text-align: right; min-width: 44px; flex: 0 0 auto; }
.pot-label {
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.pot-label .term { color: var(--ink-faint); text-decoration-color: rgba(61, 220, 151, 0.35); }
.pot-amount {
  font-size: 26px;
  transition: color 0.3s ease;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}

/* End of hand scoreboard. */
.hand-result {
  flex: 0 0 auto;
  margin-top: var(--v-step);
  padding: 11px 14px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--surface);
  animation: result-in 0.44s cubic-bezier(0.2, 0.9, 0.3, 1) both;
}
.hand-result[hidden] { display: none; }

@keyframes result-in {
  from { opacity: 0; transform: translate3d(0, 14px, 0) scale(0.97); }
  to { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}

.result-delta { animation: delta-in 0.5s cubic-bezier(0.2, 1.2, 0.35, 1) 0.12s both; }

@keyframes delta-in {
  from { opacity: 0; transform: scale(0.6); }
  to { opacity: 1; transform: scale(1); }
}
.hand-result.won { border-color: rgba(61, 220, 151, 0.4); background: rgba(61, 220, 151, 0.07); }
.hand-result.lost { border-color: rgba(255, 111, 97, 0.32); background: rgba(255, 111, 97, 0.06); }

.result-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.result-who { font-size: 18px; font-weight: 700; letter-spacing: -0.02em; }
.result-delta {
  font-size: 22px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  white-space: nowrap;
}
.hand-result.won .result-delta { color: var(--good); }
.hand-result.lost .result-delta { color: var(--mistake); }
.hand-result.even .result-delta { font-size: 15px; color: var(--ink-faint); }

.result-detail { margin-top: 3px; font-size: 13px; color: var(--ink-dim); }

/* Once the hand is settled the scoreboard is the headline, so the grade for
   the last decision gives up room rather than pushing the table off screen. */
#hand-result:not([hidden]) ~ #coach-banner { max-height: 26vh; }

.table-message:empty { min-height: 0; padding: 0; }

.table-message {
  flex: 0 0 auto;
  min-height: 17px;
  text-align: center;
  font-size: 12px;
  color: var(--ink-faint);
  padding: var(--v-step) 0 0;
}
.table-message .term { color: var(--ink-dim); }

/* --------------------------------------------------------- coach banner */

/* With nine seats the opponents take two rows, so the coach gives up its
   room sooner rather than pushing the controls off the bottom. The banner
   scrolls; the buttons cannot. */
body.many-seats .coach-banner { max-height: 26vh; }

.coach-banner {
  flex: 0 6 auto;
  margin: var(--v-step) 0 0;
  padding: 11px 13px;
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  animation: banner-in 0.34s cubic-bezier(0.2, 0.9, 0.3, 1) both;
  max-height: 40vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

@keyframes banner-in {
  from { opacity: 0; transform: translate3d(0, 10px, 0) scale(0.985); }
  to { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}

.coach-verdict {
  display: inline-block;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  margin-bottom: 7px;
}
.coach-banner.scrolls {
  -webkit-mask-image: linear-gradient(180deg, #000 0 calc(100% - 26px), transparent 100%);
  mask-image: linear-gradient(180deg, #000 0 calc(100% - 26px), transparent 100%);
}

.coach-banner.good .coach-verdict { color: var(--good); background: rgba(61, 220, 151, 0.13); }
.coach-banner.fine .coach-verdict { color: var(--fine); background: rgba(240, 192, 90, 0.13); }
.coach-banner.mistake .coach-verdict { color: var(--mistake); background: rgba(255, 111, 97, 0.13); }

.coach-text { font-size: 14px; color: var(--ink); line-height: 1.45; }

/* Points floating up when a decision earns them. */
.coach-banner { position: relative; }

.reward {
  position: absolute;
  top: 9px;
  right: 12px;
  font-size: 15px;
  font-weight: 800;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  animation: reward-up 1.4s ease-out both;
}
.reward.level-up {
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--chip);
}
.reward.milestone {
  font-size: 13px;
  letter-spacing: 0.03em;
  color: var(--chip);
  text-shadow: 0 0 12px rgba(245, 196, 81, 0.4);
}

@keyframes reward-up {
  0% { opacity: 0; transform: translateY(6px); }
  18% { opacity: 1; transform: translateY(0); }
  70% { opacity: 1; transform: translateY(-4px); }
  100% { opacity: 0; transform: translateY(-14px); }
}

.coach-better {
  margin-top: 7px;
  padding-top: 7px;
  border-top: 1px solid var(--line-soft);
  font-size: 12px;
  color: var(--ink-faint);
}
.coach-better strong { color: var(--ink); font-weight: 600; }

/* Tappable jargon. */
.term {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: rgba(61, 220, 151, 0.45);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  cursor: pointer;
}
.term:active { background: var(--accent-soft); border-radius: 3px; }

/* --------------------------------------------------------- hero and keys */

.hero-zone { flex: 0 0 auto; padding: var(--v-block) 0 var(--pad); }

.action-area { min-height: var(--tap); margin-top: var(--pad); }
/* The swipe hint sits above the cards, and the cards are now the top of this
   block, so the room it needs comes off the top of the whole zone rather than
   out of the gap under the buttons. */
body.can-fold .hero-zone { padding-top: 30px; }
.action-row { display: flex; gap: 8px; align-items: stretch; }

.action-row.enter > * { animation: act-in 0.34s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.action-row.enter > *:nth-child(2) { animation-delay: 0.045s; }
.action-row.enter > *:nth-child(3) { animation-delay: 0.09s; }
.action-row.enter > *:nth-child(4) { animation-delay: 0.135s; }

@keyframes act-in {
  from { opacity: 0; transform: translate3d(0, 10px, 0); }
  to { opacity: 1; transform: translate3d(0, 0, 0); }
}

.act-btn {
  flex: 1 1 0;
  min-height: var(--tap);
  border-radius: var(--radius);
  background: transparent;
  border: 1px solid var(--line);
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 4px 2px;
}
.act-btn small { font-size: 12px; font-weight: 500; color: var(--ink-dim); }
.act-btn { transition: background 0.15s ease, transform 0.12s ease, border-color 0.2s ease; }
.act-btn:active { background: var(--surface-high); transform: scale(0.97); }
.act-btn.fold { color: var(--ink-dim); }
.act-btn.primary { border-color: rgba(61, 220, 151, 0.45); color: var(--accent); }
.act-btn.primary small { color: rgba(61, 220, 151, 0.75); }
.act-btn.primary:active { background: var(--accent-soft); }

.sizer-btn {
  flex: 0 0 54px;
  min-height: var(--tap);
  border-radius: var(--radius);
  border: 1px solid var(--line);
  color: var(--ink-dim);
  font-size: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.sizer-btn:active { background: var(--surface-high); color: var(--ink); }

.next-btn {
  width: 100%;
  flex: 1 1 0;
  min-height: var(--tap);
  border-radius: var(--radius);
  border: 1px solid rgba(61, 220, 151, 0.45);
  color: var(--accent);
  font-size: 15px;
  font-weight: 600;
}
.next-btn:active { background: var(--accent-soft); }

.waiting.grow { flex: 1 1 auto; }

.act-btn.skip { flex: 0 0 96px; color: var(--ink-dim); font-size: 13px; }
/* .act-btn sets display:flex, which would win over the hidden attribute. */
.act-btn[hidden] { display: none; }

.waiting {
  min-height: var(--tap);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: var(--ink-faint);
}

/* bet sizer */

.bet-sizer {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
  padding: 10px 12px 12px;
}

.sizer-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.sizer-amount {
  font-size: 26px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}
.sizer-amount small { font-size: 12px; color: var(--ink-faint); font-weight: 500; margin-left: 7px; }

.sizer-cancel {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--line);
  color: var(--ink-dim);
  font-size: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
}

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 32px;
  background: transparent;
  margin: 0;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: var(--line);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 26px;
  height: 26px;
  margin-top: -11px;
  border-radius: 50%;
  background: var(--ink);
  border: none;
}
input[type="range"]::-moz-range-track { height: 4px; border-radius: 2px; background: var(--line); }
input[type="range"]::-moz-range-thumb {
  width: 24px; height: 24px; border-radius: 50%; background: var(--ink); border: none;
}

.sizer-presets { display: flex; gap: 6px; margin: 2px 0 10px; }

.preset-btn {
  flex: 1 1 0;
  min-height: 40px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-dim);
}
.preset-btn:active, .preset-btn.on { background: var(--surface-high); color: var(--ink); }

.sizer-confirm {
  width: 100%;
  min-height: var(--tap);
  border-radius: var(--radius);
  border: 1px solid rgba(61, 220, 151, 0.45);
  color: var(--accent);
  font-size: 15px;
  font-weight: 600;
}
.sizer-confirm:active { background: var(--accent-soft); }

/* hero cards and readout */

.hero-seat {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}

.hero-cards-wrap {
  position: relative;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: var(--v-tight);
  flex: 0 0 auto;
}

.hero-cards {
  display: flex;
  transition: opacity 0.25s ease;
}
.hero-cards.draggable { cursor: grab; touch-action: none; }
.hero-cards.draggable:active { cursor: grabbing; }

/* While the cards are in the air they belong on top of everything else, and
   the buttons underneath get out of the way. */
.hero-cards.dragging,
.hero-cards.mucked {
  position: relative;
  z-index: 40;
  filter: drop-shadow(0 16px 24px rgba(0, 0, 0, 0.75));
}
body.folding .action-area,
body.folding .table-message,
body.folding #coach-banner { opacity: 0.25; transition: opacity 0.16s ease; }
body.folding .hero-readout { opacity: 0.4; transition: opacity 0.16s ease; }
/* Only springs back when the finger is off, so the drag itself stays exact. */
.hero-cards:not(.dragging) { transition: transform 0.34s cubic-bezier(0.2, 1.1, 0.35, 1), opacity 0.25s ease; }
.hero-cards.mucked { animation: muck 0.24s ease-in both; }

@keyframes muck {
  from { transform: translate3d(0, -66px, 0) rotate(-3deg); opacity: 0.5; }
  to { transform: translate3d(0, -190px, 0) rotate(-12deg); opacity: 0; }
}

/* The label above the cards while they can be thrown away. */
.fold-hint {
  position: absolute;
  z-index: 41;
  top: -22px;
  left: 2px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
  transition: opacity 0.25s ease, color 0.2s ease;
}
.fold-hint.showing { opacity: 0.5; }
/* Folding is a gesture now, not a button, so the first few times it says so
   properly and then settles down. */
.fold-hint.loud {
  opacity: 1;
  color: var(--ink-dim);
  animation: hint-breathe 2.1s ease-in-out infinite;
}
.hero-cards.dragging ~ .fold-hint.loud { animation: none; }

@keyframes hint-breathe {
  0%, 100% { transform: translate3d(0, 0, 0); opacity: 0.55; }
  50% { transform: translate3d(0, -3px, 0); opacity: 1; }
}
.hero-cards:not(.dragging) ~ .fold-hint,
.fold-hint { will-change: transform; }
.fold-hint.ready { color: var(--mistake); opacity: 1; }
.hero-cards.folded { opacity: 0.28; }
.hero-cards:focus { outline: none; }
.hero-cards:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
  border-radius: var(--radius);
}

.hero-cards .card {
  flex: 0 0 auto;
  width: 78px;
  aspect-ratio: 5 / 7;
  border-radius: var(--radius-lg);
  padding: 8px 10px;
  box-shadow: -6px 0 14px rgba(0, 0, 0, 0.6);
}
.hero-cards .card:not(:first-child) {
  margin-left: -14px;
  box-shadow: -3px 0 0 0 var(--bg), -9px 0 16px rgba(0, 0, 0, 0.55);
}
.hero-cards .card .rank { font-size: 34px; }
.hero-cards .card .suit { font-size: 24px; }

.hero-stack {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  padding-left: 2px;
}
.hero-stack strong { color: var(--ink-dim); font-weight: 600; }

.hero-net { font-weight: 800; font-variant-numeric: tabular-nums; }
.hero-net.win { color: var(--good); }
.hero-net.lose { color: var(--mistake); }

.hero-marks { display: flex; gap: 4px; }

.hero-mark {
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  font-size: 9px;
  font-weight: 800;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  color: var(--ink-dim);
}
.hero-mark.dealer { background: var(--ink); color: #000; border-color: var(--ink); }
.hero-mark.big { color: var(--chip); border-color: rgba(245, 196, 81, 0.4); }

.hero-readout {
  flex: 1 1 auto;
  min-width: 0;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
  background: var(--surface);
  padding: 10px 12px;
  text-align: right;
  font-size: 14px;
  color: var(--ink);
  line-height: 1.35;
}
.hero-readout .readout-label {
  display: block;
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 3px;
}

/* ------------------------------------------------------- sheet / screens */

.sheet { position: fixed; inset: 0; z-index: 40; display: flex; align-items: flex-end; }
.sheet[hidden] { display: none; }
.sheet-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.7); }

.sheet-panel {
  position: relative;
  width: 100%;
  max-height: 78vh;
  background: var(--surface);
  border-top-left-radius: 22px;
  border-top-right-radius: 22px;
  border-top: 1px solid var(--line);
  padding: 8px 18px calc(20px + env(safe-area-inset-bottom));
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  animation: sheet-in 0.36s cubic-bezier(0.2, 0.9, 0.28, 1) both;
}

@keyframes sheet-in {
  from { transform: translate3d(0, 34px, 0); opacity: 0; }
  to { transform: translate3d(0, 0, 0); opacity: 1; }
}

.sheet-backdrop { animation: fade-in 0.28s ease both; }

@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.sheet-handle {
  width: 34px;
  height: 4px;
  border-radius: 2px;
  background: var(--line);
  margin: 0 auto 12px;
}

.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.sheet-title { margin: 0; font-size: 20px; font-weight: 600; letter-spacing: -0.02em; }

.sheet-close, .screen-close {
  min-height: 34px;
  padding: 6px 13px;
  border-radius: 999px;
  border: 1px solid var(--line);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-dim);
}
.sheet-close:active, .screen-close:active { background: var(--surface-high); color: var(--ink); }

.sheet-body { margin-top: 14px; }

/* ------------------------------------------------------------- diagrams */

.dg { margin-bottom: 14px; }

.dg-caption {
  font-size: 12px;
  color: var(--ink-faint);
  line-height: 1.4;
  margin-top: 7px;
}

/* The range grid. Thirteen by thirteen plus a row and column of headers,
   sized off the sheet width so it fills it exactly on any phone. */
.dg-range-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 9px;
}
.dg-range-head strong { font-size: 14px; font-weight: 600; color: var(--ink); }
.dg-range-pct {
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.dg-chart-wrap { position: relative; }

/* Which half of the grid you are in, written on the grid. Sat over a dark
   chip so it stays legible whether the squares under it are lit or not. */
.dg-region {
  position: absolute;
  pointer-events: none;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
  background: rgba(0, 0, 0, 0.72);
  padding: 2px 5px;
  border-radius: 4px;
  white-space: nowrap;
}
.dg-region.suited { top: 20%; right: 4%; }
.dg-region.offsuit { bottom: 12%; left: 10%; }

.dg-chart {
  display: grid;
  /* minmax(0, 1fr) rather than 1fr: a grid item will not shrink below its own
     content by default, and the rank headers would push the columns wide. */
  grid-template-columns: repeat(14, minmax(0, 1fr));
  gap: 1px;
}

.dg-chart .dg-gh {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  font-size: 9px;
  font-weight: 700;
  color: var(--ink-faint);
  letter-spacing: -0.05em;
  aspect-ratio: 1;
  overflow: hidden;
}
.dg-chart .dg-gh.corner { visibility: hidden; }

.dg-chart .dg-cell {
  min-width: 0;
  aspect-ratio: 1;
  border-radius: 2px;
  background: var(--surface-high);
}
.dg-chart .dg-cell.in { background: var(--accent); opacity: 0.85; }
/* The diagonal is where the pairs live, and seeing it is what makes the two
   halves either side of it mean anything. */
.dg-chart .dg-cell.pair { background: #2a2a30; }
.dg-chart .dg-cell.pair.in { background: var(--accent); opacity: 1; }
.dg-chart .dg-cell.mine {
  box-shadow: 0 0 0 2px var(--ink);
  position: relative;
  z-index: 1;
}
.dg-chart .dg-cell.picked {
  box-shadow: 0 0 0 2px var(--chip);
  position: relative;
  z-index: 2;
}
.dg-chart .dg-cell.mine.picked { box-shadow: 0 0 0 2px var(--chip); }

/* What the square you just tapped actually is. */
.dg-chart-readout {
  margin-top: 10px;
  min-height: 18px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink-faint);
}
.dg-chart-readout.read { color: var(--ink-dim); }
.dg-chart-readout strong { color: var(--mistake); font-weight: 600; }
.dg-chart-readout.yes strong { color: var(--accent); }

.dg-range-key {
  margin-top: 9px;
  font-size: 11px;
  color: var(--ink-faint);
  line-height: 1.4;
}

.dg-range-mine {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-top: 8px;
  font-size: 13px;
  color: var(--ink-dim);
  line-height: 1.4;
}
.dg-range-dot {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--surface-high);
  box-shadow: 0 0 0 2px var(--ink);
  transform: translateY(1px);
}
.dg-range-mine.in .dg-range-dot { background: var(--accent); }

/* Turn order, left to right. */
.dg-strip {
  display: flex;
  align-items: center;
  gap: 3px;
  flex-wrap: wrap;
}

.dg-strip.enter .dg-seat { animation: act-in 0.34s cubic-bezier(0.2, 0.9, 0.3, 1) both; }

.dg-seat {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 9px 5px 5px;
  border-radius: 999px;
  border: 1px solid var(--line-soft);
  background: var(--surface-high);
}
.dg-seat.me { border-color: rgba(61, 220, 151, 0.5); background: var(--accent-soft); }
.dg-seat.folded { opacity: 0.32; }
.dg-seat.acting { border-color: var(--ink-dim); }

.dg-num {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--line);
  color: var(--ink-dim);
  font-size: 10px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.dg-seat.me .dg-num { background: var(--accent); color: #000; }

/* The same dealer badge the table shows, so it reads without explaining. */
.dg-d {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--ink);
  color: #000;
  font-size: 8px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}

.dg-name { font-size: 12px; font-weight: 600; color: var(--ink); white-space: nowrap; }
.dg-seat.folded .dg-name { text-decoration: line-through; }
.dg-arrow { color: var(--ink-faint); font-size: 12px; }

/* The price against your chance of getting there. */
/* Two bars on one scale, one over the other, so their lengths compare. One
   grid holds both rows, which is what keeps the bars starting and ending on
   the same pixels. */
.dg-odds-grid {
  display: grid;
  grid-template-columns: max-content 1fr max-content;
  align-items: center;
  gap: 6px 9px;
}
.dg-odds-name { font-size: 12px; color: var(--ink-dim); white-space: nowrap; }
.dg-odds-bar {
  position: relative;
  display: block;
  height: 10px;
  border-radius: 5px;
  background: var(--surface-high);
  overflow: hidden;
}
.dg-odds-bar i {
  position: absolute;
  inset: 0 auto 0 0;
  display: block;
  border-radius: 5px;
  background: var(--ink-faint);
  transition: width 0.32s cubic-bezier(0.2, 0.9, 0.3, 1);
}
.dg-odds-bar.need i { background: var(--ink-dim); }
.dg-odds.good .dg-odds-bar.have i { background: var(--good); }
.dg-odds.bad .dg-odds-bar.have i { background: var(--mistake); }

.dg-odds-num {
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 30px;
  text-align: right;
  color: var(--ink-dim);
}
.dg-odds.good .dg-odds-num.have { color: var(--good); }
.dg-odds.bad .dg-odds-num.have { color: var(--mistake); }

.dg-odds-verdict {
  margin-top: 9px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.dg-odds.good .dg-odds-verdict { color: var(--good); }
.dg-odds.bad .dg-odds-verdict { color: var(--mistake); }
.dg-odds .dg-caption { margin-top: 4px; }


/* Every card nobody has seen, with the ones that save you filled in. */
.dg-grid { display: flex; flex-wrap: wrap; gap: 3px; }
.dg-card {
  width: 11px;
  height: 15px;
  border-radius: 2px;
  background: var(--surface-high);
  border: 1px solid var(--line-soft);
}
.dg-card.out {
  background: var(--accent);
  border-color: var(--accent);
  animation: out-in 0.28s ease-out both;
}

@keyframes out-in {
  from { opacity: 0.15; transform: scale(0.6); }
  to { opacity: 1; transform: scale(1); }
}

/* The nine things a hand can be, strongest first. */
.dg-ladder { display: flex; flex-direction: column; gap: 1px; }
.dg-rung {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 9px;
  border-radius: 6px;
  font-size: 12px;
  color: var(--ink-dim);
}
.dg-rung.beaten { color: var(--ink-faint); }
.dg-rung.current {
  background: var(--accent-soft);
  color: var(--ink);
  font-weight: 700;
}
.dg-rung-you {
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

/* Inside a coach banner the picture is a supporting detail, not the point. */
.coach-banner .dg { margin: 9px 0 0; }
.coach-banner .dg-caption { margin-top: 5px; }

/* What the word means for the hand in front of you. This is the main event,
   so it gets the size, and the general definition sits under it. */
.live-note {
  font-size: 17px;
  line-height: 1.4;
  color: var(--ink);
  margin-bottom: 14px;
}

.sense { margin-bottom: 12px; }
.sense-label {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 3px;
}
.sense-text { font-size: 15px; line-height: 1.45; }
.sense-text.secondary { font-size: 14px; color: var(--ink-dim); }
.sense-text.secondary .term { color: var(--ink-dim); text-decoration-color: rgba(141, 141, 149, 0.6); }
.sense-example {
  margin-top: 6px;
  font-size: 13px;
  color: var(--ink-faint);
  line-height: 1.45;
}
.sense-example .term { color: var(--ink-faint); }

.screen {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  animation: screen-in 0.32s cubic-bezier(0.2, 0.9, 0.28, 1) both;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
.screen[hidden] { display: none; }

@keyframes screen-in {
  from { opacity: 0; transform: translate3d(0, 16px, 0); }
  to { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* Rows arrive just behind the screen itself. */
.screen-body > * { animation: row-in 0.36s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.screen-body > *:nth-child(1) { animation-delay: 0.02s; }
.screen-body > *:nth-child(2) { animation-delay: 0.05s; }
.screen-body > *:nth-child(3) { animation-delay: 0.08s; }
.screen-body > *:nth-child(4) { animation-delay: 0.11s; }
.screen-body > *:nth-child(n+5) { animation-delay: 0.14s; }

@keyframes row-in {
  from { opacity: 0; transform: translate3d(0, 10px, 0); }
  to { opacity: 1; transform: translate3d(0, 0, 0); }
}

.screen-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 18px 14px;
}
.screen-title { margin: 0; font-size: 22px; font-weight: 600; letter-spacing: -0.02em; }

.screen-body {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 2px 18px calc(28px + env(safe-area-inset-bottom));
}

.search-input {
  width: 100%;
  min-height: 46px;
  padding: 11px 14px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  color: var(--ink);
  font-size: 16px;
  margin-bottom: 14px;
}
.search-input::placeholder { color: var(--ink-faint); }

.term-row {
  display: block;
  width: 100%;
  text-align: left;
  padding: 13px 14px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  margin-bottom: 8px;
  min-height: 50px;
}
.term-row:active { background: var(--surface-high); }
.term-row-title { font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 7px; }

.term-new {
  font-size: 8px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--accent);
  border: 1px solid rgba(61, 220, 151, 0.4);
  border-radius: 999px;
  padding: 1px 5px;
}
.term-row-text {
  font-size: 12px;
  color: var(--ink-faint);
  margin-top: 3px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.stat-grid { display: flex; gap: 8px; margin-bottom: 6px; }
.stat-grid + .stat-grid { margin-top: 14px; }
.stat-card {
  flex: 1 1 0;
  padding: 14px 8px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  text-align: center;
}
.stat-value {
  font-size: 26px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}
.stat-label { font-size: 11px; color: var(--ink-faint); margin-top: 3px; }

.level-wide {
  height: 6px;
  border-radius: 3px;
  background: var(--line);
  overflow: hidden;
  margin: 16px 0 9px;
}
.level-wide-fill { height: 100%; background: var(--accent); border-radius: 3px; }

/* The bar and the line under it are one thing, so they sit close together and
   keep their distance from the next block instead of the other way round. */
.level-note {
  margin: 0 0 20px;
  font-size: 13px;
  color: var(--ink-dim);
  line-height: 1.45;
}

.section-title {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 22px 0 9px;
}

.leak-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 13px 14px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  margin-bottom: 8px;
}
/* Long leak names wrap rather than crowding the count beside them. */
.leak-name { font-size: 14px; min-width: 0; }
.leak-count {
  font-size: 13px;
  font-weight: 700;
  color: var(--mistake);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.empty-note { font-size: 14px; color: var(--ink-dim); margin: 0; }

.setting-row {
  padding: 14px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  margin-bottom: 10px;
}
.setting-label { font-size: 15px; font-weight: 600; margin-bottom: 3px; }
.setting-note { font-size: 12px; color: var(--ink-faint); margin-bottom: 10px; line-height: 1.4; }

.choice-row { display: flex; gap: 6px; }
.choice-btn {
  flex: 1 1 0;
  min-height: 44px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-dim);
}
.choice-btn.on { background: var(--ink); color: #000; border-color: var(--ink); }

.danger-btn {
  width: 100%;
  min-height: 48px;
  border-radius: var(--radius);
  border: 1px solid rgba(255, 111, 97, 0.35);
  color: var(--mistake);
  font-size: 14px;
  font-weight: 600;
}
.danger-btn:active { background: rgba(255, 111, 97, 0.1); }

.bot-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 14px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  margin-bottom: 8px;
}
.bot-avatar { font-size: 28px; line-height: 1; }
.bot-info { flex: 1 1 auto; }
.bot-name { font-size: 15px; font-weight: 600; }
.bot-read { font-size: 12px; color: var(--ink-dim); margin-top: 3px; line-height: 1.45; }
.bot-locked { color: var(--ink-faint); }

/* Seven or more opponents share the same strip, so a seat gets smaller
   rather than pushing the board off the table. */
.opponents.many .seat { flex: 1 1 22%; min-width: 48px; max-width: 25%; padding: 8px 1px 2px; }
.opponents.many .seat-avatar { font-size: 26px; }
.opponents.many .seat-name { font-size: 11px; margin-top: 3px; }
.opponents.many .seat-stack { font-size: 12px; }
.opponents.many .seat-action { min-height: 10px; font-size: 8px; line-height: 10px; }
.opponents.many .seat-hole { min-height: 16px; }
.opponents.many .mini-card { width: 12px; height: 17px; }
.opponents.many .seat-meta { min-height: 13px; gap: 2px; }
.opponents.many .seat-tag { height: 13px; min-width: 13px; padding: 0 3px; font-size: 7px; }
.opponents.many .seat-action { font-size: 8px; line-height: 10px; }
.opponents.many .seat-bet { font-size: 10px; padding: 1px 7px; }

/* ------------------------------------------------------------------ runs */

/* A screen the run is waiting on has no way out of it. */
.screen.sticky .screen-close { display: none; }

.step-head { margin-bottom: 4px; }
.step-name { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; }
.step-focus {
  margin-top: 3px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
}
.step-brief { margin: 9px 0 0; font-size: 14px; color: var(--ink-dim); line-height: 1.45; }
.step-warn { margin: 9px 0 0; font-size: 13px; color: var(--mistake); line-height: 1.45; }

.step-facts { display: flex; gap: 8px; margin-top: 14px; }
.fact {
  flex: 1 1 0;
  padding: 11px 8px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  text-align: center;
}
.fact-value {
  font-size: 20px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.fact-label { margin-top: 3px; font-size: 10px; color: var(--ink-faint); }

.pick-card {
  display: block;
  width: 100%;
  text-align: left;
  padding: 14px;
  margin-bottom: 9px;
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--line);
}
.pick-card:active { background: var(--surface-high); border-color: rgba(61, 220, 151, 0.45); }
.pick-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.pick-top strong { font-size: 16px; font-weight: 600; }
.pick-seats { font-size: 12px; color: var(--accent); font-weight: 700; }
.pick-note { margin-top: 5px; font-size: 13px; color: var(--ink-dim); line-height: 1.45; }

.debrief {
  padding: 14px;
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--line-soft);
}
.debrief.mastered { border-color: rgba(61, 220, 151, 0.4); background: rgba(61, 220, 151, 0.06); }
.debrief-name { font-size: 17px; font-weight: 700; letter-spacing: -0.02em; }
.debrief-line { margin: 7px 0 0; font-size: 14px; color: var(--ink-dim); line-height: 1.45; }
.debrief-line.dim { color: var(--ink-faint); }
.debrief-badge {
  display: inline-block;
  margin-top: 10px;
  padding: 5px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-soft);
}
.debrief-badge.dim { color: var(--ink-dim); background: var(--surface-high); }

.runover {
  padding: 14px;
  border-radius: var(--radius-lg);
  background: rgba(255, 111, 97, 0.07);
  border: 1px solid rgba(255, 111, 97, 0.32);
}
.runover.won { background: rgba(61, 220, 151, 0.07); border-color: rgba(61, 220, 151, 0.4); }
.runover-line { font-size: 16px; line-height: 1.45; }

.step-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 14px;
  margin-bottom: 7px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line-soft);
}
.step-row.mastered { border-color: rgba(61, 220, 151, 0.35); }
.step-row.failed { border-color: rgba(255, 111, 97, 0.3); }
.step-row-name { font-size: 14px; }
.step-row-focus { margin-top: 2px; font-size: 11px; color: var(--ink-faint); }
.step-row-score {
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink-dim);
  white-space: nowrap;
}
.step-row.mastered .step-row-score { color: var(--accent); }
.step-row.failed .step-row-score { color: var(--mistake); }

.next-btn.wide { margin-top: 16px; padding: 0 16px; }

.danger-btn.quiet {
  color: var(--ink-dim);
  border-color: var(--line);
  margin-bottom: 4px;
}

/* One line per finished run, newest first. */
.run-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 13px;
  margin-bottom: 6px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line-soft);
}
.run-row.won { border-color: rgba(61, 220, 151, 0.35); }
.run-row-step { font-size: 13px; }
.run-row-when { margin-top: 2px; font-size: 11px; color: var(--ink-faint); }
.run-row-stat {
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink-dim);
  white-space: nowrap;
}
.run-row.won .run-row-stat { color: var(--accent); }

/* Larger screens get more room without changing the layout. */
@media (min-width: 600px) {
  .felt { max-width: 640px; margin: 0 auto; width: 100%; }
  .topbar { max-width: 640px; margin: 0 auto; width: 100%; }
  .board { max-width: 400px; }
  .hero-cards .card { width: 96px; }
  .hero-cards .card .rank { font-size: 40px; }
  .hero-cards .card .suit { font-size: 28px; }
  .seat { max-width: 100px; }
  .seat-avatar { font-size: 40px; }
  .coach-text { font-size: 15px; }
}

@media (max-height: 700px) {
  .board { max-width: 244px; }
  .card .rank { font-size: 18px; }
  .card .suit { font-size: 13px; }
  .hero-cards .card { width: 62px; }
  .hero-cards .card .rank { font-size: 26px; }
  .hero-cards .card .suit { font-size: 18px; }
  .hero-cards .card { padding: 6px 8px; }
  .seat-avatar { font-size: 26px; }
  .seat-name { font-size: 11px; margin-top: 3px; }
  .seat-stack { font-size: 12px; }
  .seat { padding: 8px 2px 2px; }
  .seat-hole { min-height: 17px; margin-top: 2px; }
  .mini-card { width: 12px; height: 17px; }
  .middle { min-height: 66px; }
  .coach-banner { max-height: 32vh; }

  /* With a scoreboard on screen the board gives up height first, then the
     grade for the last decision, so nothing runs off the bottom. */
  body.showing-result .middle { min-height: 48px; }
  body.showing-result .board { max-width: 200px; }
  #hand-result:not([hidden]) ~ #coach-banner { max-height: 16vh; }
  .hand-result { padding: 9px 12px; }
  .result-who { font-size: 16px; }
  .result-delta { font-size: 20px; }
  .result-detail { font-size: 12px; line-height: 1.35; }
  .coach-text { font-size: 13px; }
  .hero-readout { padding: 8px 10px; font-size: 13px; }
  .pot-amount { font-size: 22px; }

  /* Two rows of seats on a short screen need every pixel. */
  .opponents.many .seat { padding: 6px 1px 0; }
  .opponents.many .seat-avatar { font-size: 22px; }
  .opponents.many .seat-name { font-size: 10px; margin-top: 2px; }
  .opponents.many .seat-stack { font-size: 11px; }
  .opponents.many .seat-meta { min-height: 11px; margin-top: 1px; }
  .opponents.many .seat-tag { height: 11px; min-width: 11px; font-size: 6px; padding: 0 3px; }
  .opponents.many .seat-hole { min-height: 14px; margin-top: 1px; }
  .opponents.many .mini-card { width: 10px; height: 14px; }
  .opponents.many .seat-bet { margin-top: 2px; font-size: 9px; padding: 0 6px; }
}

/* Genuinely short screens, an SE and nothing taller. The spacing scale is
   trimmed here rather than collapsed: every gap keeps its shape, it just
   gets smaller. Tall-but-not-huge phones keep the full scale. */
@media (max-height: 620px) {
  :root { --tap: 48px; --v-tight: 4px; --v-step: 8px; --v-block: 13px; }
  /* A narrower board is a shorter board, and the height it gives back buys
     the coach a readable line instead of a clipped one. */
  .board { max-width: 208px; }
  .middle { min-height: 56px; }
  /* The banner is the one thing here that can grow without limit, so on the
     smallest screen it yields a little sooner and scrolls instead. */
  .coach-banner { max-height: 30vh; }
  .topbar { padding: 8px var(--pad) 10px; }
  .run-line { margin-top: 2px; font-size: 9px; gap: 6px; }
  .hero-zone { padding: var(--v-block) 0 9px; }
  .action-area { margin-top: 10px; }
  /* The hint keeps 6px clear on each side here instead of 8. */
  body.can-fold .hero-zone { padding-top: 24px; }
  .fold-hint { top: -18px; }
  /* Between hands the action row is a single Next button, so it needs less
     breathing room than a live decision does. */
  body.showing-result .hero-zone { padding-top: 8px; }
  body.showing-result .action-area { margin-top: 10px; }
}

/* Narrow phones. Everything in the top bar has to fit across 320px, and at
   nine seats the seat rows have to give the coach room to be readable. */
@media (max-width: 360px) {
  .topbar { padding: 8px 10px 10px; gap: 6px; }
  .nav-btn { padding: 6px 8px; font-size: 12px; }
  .level-track { width: 72px; }
  .felt { padding: 0 10px; }

  /* Face down cards say nothing a dimmed seat does not already say. */
  .opponents.many .seat-hole { display: none; }
  .opponents.many .seat-avatar { font-size: 20px; }
  .opponents.many .seat { padding: 5px 1px 0; }
  .opponents.many .seat-name { font-size: 9px; }
  .opponents.many .seat-stack { font-size: 11px; }

  .result-who { font-size: 15px; }
  .result-delta { font-size: 18px; }
  .result-detail { font-size: 11px; }
  .hand-result { padding: 8px 11px; }
}

@media (prefers-reduced-motion: reduce) {
  .coach-banner, .sheet-panel, .sheet-backdrop, .reward, .dg-card.out,
  .hand-result, .result-delta, .handout, .seat-bet.pop, .hero-cards.mucked,
  .action-row.enter > *, .seat.acting .seat-marker, .seat.winner,
  .screen, .screen-body > *, .dg-strip.enter .dg-seat,
  .fold-hint.loud, .streak-label.bump { animation: none; }
  .dg-odds-bar i, .slot-inner, .seat, .seat-bet, .seat-marker,
  .level-fill { transition: none; }
  .fold-hint.loud { opacity: 1; }
}
