* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: radial-gradient(ellipse at top, #1a3d2e 0%, #0b1f16 100%);
  color: #f1e9d2;
  min-height: 100vh;
}

.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 24px;
  background: rgba(0,0,0,0.35);
  border-bottom: 1px solid rgba(255,255,255,0.08);
}
.brand {
  font-weight: 700;
  letter-spacing: 0.05em;
  font-size: 18px;
  color: #f5d67a;
}
.topbar-right {
  display: flex;
  align-items: center;
  gap: 14px;
}
.topbar-btn {
  background: rgba(245, 214, 122, 0.12);
  border: 1px solid rgba(245, 214, 122, 0.4);
  color: #f5d67a;
  padding: 7px 14px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  font-family: inherit;
}
.topbar-btn:hover {
  background: rgba(245, 214, 122, 0.22);
  color: #fff0bf;
}
/* Hidden topbar button (e.g. admin link for non-admins) — must match the
   per-element .hidden pattern used elsewhere in this file since there is
   no global `.hidden` rule. Without this, ui.js toggling `hidden` on
   #admin-link wouldn't actually remove it from the layout. */
.topbar-btn.hidden { display: none; }
/* Sound toggle: muted appearance when OFF so the state is glanceable. */
#sound-btn[data-on="false"] {
  opacity: 0.55;
  text-decoration: line-through;
}

/* Demo / play-money banner shown when the current account is a throwaway
   demo user. Sits below the topbar, full-width strip. */
/* Maintenance / update banner. Two visual states (toggled by ui.js):
     .maintenance-active        red, pulsing  → "Update incoming, finish your hand"
     .maintenance-update-ready  green, calm   → "Update complete, click to reload"
   Default rule below covers shared layout; the two state classes set
   colours / animation. */
.maintenance-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 8px 18px;
  border-bottom-width: 1px;
  border-bottom-style: solid;
  font-size: 13px;
  font-weight: 500;
  text-align: center;
  flex-wrap: wrap;
}
.maintenance-banner.hidden { display: none; }
.maintenance-banner strong {
  color: #fff;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/* RED: window currently open, deploy in progress. */
.maintenance-banner.maintenance-active {
  background: linear-gradient(180deg, rgba(220, 88, 60, 0.30), rgba(220, 88, 60, 0.18));
  border-bottom-color: rgba(255, 170, 130, 0.55);
  color: #ffe0c8;
  animation: maintenancePulse 2.4s ease-in-out infinite;
}
@keyframes maintenancePulse {
  0%, 100% { background: linear-gradient(180deg, rgba(220, 88, 60, 0.30), rgba(220, 88, 60, 0.18)); }
  50%      { background: linear-gradient(180deg, rgba(220, 88, 60, 0.50), rgba(220, 88, 60, 0.30)); }
}

/* GREEN: window just closed — server may have new code, our cached JS/HTML
   is stale. Player clicks Refresh to grab it. No pulsing — calm prompt. */
.maintenance-banner.maintenance-update-ready {
  background: linear-gradient(180deg, rgba(88, 188, 120, 0.28), rgba(88, 188, 120, 0.16));
  border-bottom-color: rgba(166, 230, 184, 0.6);
  color: #d8f5dd;
}

.maintenance-refresh-btn {
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.5);
  color: #fff;
  padding: 4px 14px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s;
  font-family: inherit;
}
.maintenance-refresh-btn:hover { background: rgba(255, 255, 255, 0.22); }
.maintenance-refresh-btn:active { transform: scale(0.97); }
.maintenance-refresh-btn.hidden { display: none; }

@media (max-width: 480px) {
  .maintenance-banner { font-size: 11px; padding: 6px 10px; gap: 8px; }
  .maintenance-refresh-btn { font-size: 10px; padding: 3px 10px; }
}

/* ====================================================================
   Stale-version blocker — full-viewport overlay shown when any API call
   returns 426 CLIENT_VERSION_STALE. No dismiss, only Reload. This is
   the bulletproof block for users who somehow bypassed the maintenance
   banner / refresh prompt and ended up on stale JS.
   ==================================================================== */
.version-blocker {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0, 0, 0, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.version-blocker.hidden { display: none; }

.version-blocker-panel {
  background: linear-gradient(180deg, #1a2f22 0%, #102619 100%);
  border: 1px solid rgba(245, 214, 122, 0.5);
  border-radius: 16px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.7), 0 0 80px rgba(245, 214, 122, 0.15);
  padding: 36px 44px;
  max-width: 480px;
  width: 100%;
  text-align: center;
  color: #fff0bf;
  font-family: inherit;
}
.version-blocker-icon {
  font-size: 56px;
  color: #f5d67a;
  line-height: 1;
  margin-bottom: 12px;
  animation: blockerSpin 2s linear infinite;
  display: inline-block;
}
@keyframes blockerSpin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
.version-blocker-panel h2 {
  margin: 0 0 12px;
  color: #f5d67a;
  font-size: 22px;
  letter-spacing: 0.04em;
}
.version-blocker-panel p {
  margin: 0 0 20px;
  font-size: 14px;
  line-height: 1.55;
  color: rgba(255, 240, 191, 0.9);
}
.version-blocker-reload {
  background: linear-gradient(180deg, #f5d67a 0%, #c59c3a 100%);
  color: #2c1f00;
  border: none;
  padding: 12px 28px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform 0.1s, box-shadow 0.15s;
  box-shadow: 0 4px 14px rgba(245, 214, 122, 0.35);
  font-family: inherit;
}
.version-blocker-reload:hover {
  box-shadow: 0 6px 20px rgba(245, 214, 122, 0.55);
}
.version-blocker-reload:active { transform: scale(0.97); }
.version-blocker-fineprint {
  margin-top: 18px !important;
  font-size: 11px !important;
  color: rgba(255, 240, 191, 0.55) !important;
}

.demo-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 8px 18px;
  background: linear-gradient(180deg, rgba(184, 138, 44, 0.18), rgba(184, 138, 44, 0.10));
  border-bottom: 1px solid rgba(245, 214, 122, 0.4);
  color: #f5d67a;
  font-size: 12px;
  text-align: center;
  flex-wrap: wrap;
}
.demo-banner.hidden { display: none; }
.demo-banner strong {
  color: #fff0bf;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.demo-banner-link {
  color: #ffe899;
  text-decoration: underline;
  font-weight: 600;
  white-space: nowrap;
}
.demo-banner-link:hover { color: #fff6d5; }
@media (max-width: 480px) {
  .demo-banner { font-size: 10px; padding: 6px 10px; gap: 8px; }
}
@media (max-width: 480px) {
  .bets-area { flex-wrap: wrap; }
}

/* --- Rules modal --------------------------------------------------------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal.hidden { display: none; }
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.78);
  backdrop-filter: blur(3px);
  animation: modalFadeIn 0.2s ease-out forwards;
}
.modal-panel {
  position: relative;
  width: min(760px, 92vw);
  max-height: 88vh;
  overflow-y: auto;
  background: linear-gradient(180deg, #1a3d2e 0%, #0f271d 100%);
  border: 2px solid rgba(245, 214, 122, 0.5);
  border-radius: 12px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.7);
  padding: 28px 34px 32px;
  color: #f1e9d2;
  font-size: 14px;
  line-height: 1.55;
  animation: modalSlideIn 0.25s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
}
@keyframes modalFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes modalSlideIn {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.modal-close {
  position: absolute;
  top: 10px;
  right: 14px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid rgba(245, 214, 122, 0.4);
  background: rgba(0, 0, 0, 0.35);
  color: #f5d67a;
  font-size: 22px;
  font-weight: 700;
  cursor: pointer;
  line-height: 1;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal-close:hover {
  background: rgba(245, 214, 122, 0.2);
  color: #fff0bf;
}

.modal-panel h2 {
  margin: 0 0 18px;
  font-size: 22px;
  color: #f5d67a;
  letter-spacing: 0.02em;
  border-bottom: 1px dashed rgba(245, 214, 122, 0.35);
  padding-bottom: 10px;
}
.modal-panel section { margin-bottom: 22px; }
.modal-panel section:last-child { margin-bottom: 0; }
.modal-panel h3 {
  margin: 0 0 8px;
  font-size: 13px;
  color: #f5d67a;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.modal-panel p { margin: 0 0 8px; }
.modal-panel ul, .modal-panel ol {
  margin: 0 0 4px;
  padding-left: 20px;
}
.modal-panel li { margin-bottom: 4px; }
.modal-panel .note {
  margin-top: 8px;
  font-size: 12px;
  font-style: italic;
  color: rgba(241, 233, 210, 0.7);
}
.paytable-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 20px;
}
.paytable-list li { list-style: none; padding: 3px 0; }
.paytable-list strong { color: #f5d67a; font-variant-numeric: tabular-nums; }

.rules-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 10px;
  font-size: 13px;
}
.rules-table th, .rules-table td {
  border: 1px solid rgba(245, 214, 122, 0.22);
  padding: 6px 10px;
  text-align: left;
}
.rules-table th {
  background: rgba(245, 214, 122, 0.1);
  color: #f5d67a;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
}
.rules-table td.win  { color: #7ef5a0; font-weight: 600; }
.rules-table td.lose { color: #ff7a7a; font-weight: 600; }
.rules-table td.push { color: #f5d67a; font-weight: 600; }

@media (max-width: 640px) {
  .topbar { padding: 8px 12px; }
  .topbar-right { gap: 8px; }
  .topbar-btn { padding: 6px 9px; font-size: 10px; }
  .bankroll { font-size: 13px; }
  .modal-panel { padding: 22px 18px 24px; font-size: 13px; }
  .modal-panel h2 { font-size: 18px; }
  .paytable-list { grid-template-columns: 1fr; }
}

.game-layout {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 16px;
  max-width: 1440px;
  margin: 20px auto;
  padding: 0 16px;
}

.side-panel {
  flex: 0 0 220px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  position: sticky;
  top: 14px;
}

.pt-card {
  background: rgba(0, 0, 0, 0.38);
  border: 1px solid rgba(245, 214, 122, 0.25);
  border-radius: 10px;
  padding: 14px 16px;
  font-size: 12.5px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
}
.pt-card h3 {
  margin: 0 0 8px;
  font-size: 12px;
  color: #f5d67a;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  text-align: center;
  border-bottom: 1px solid rgba(245, 214, 122, 0.25);
  padding-bottom: 6px;
}
.pt-card ul {
  margin: 0;
  padding-left: 16px;
  line-height: 1.65;
}

.table {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  max-width: 1000px;
  padding: 24px 30px 28px;
  background: radial-gradient(ellipse at center, #1e5b3f 0%, #123624 70%, #0a1f14 100%);
  border: 6px solid #4a2b16;
  border-radius: 200px / 60px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.6), inset 0 0 80px rgba(0,0,0,0.4);
  display: grid;
  grid-template-rows: auto auto auto auto auto auto auto;
  gap: 18px;
}

/* Player area is a 3-column row: left paytable | player cards | right paytable.
   This replaces the old bottom-corner absolute positioning, eliminating the
   big wasted vertical gap that used to be reserved for the overlays. The
   middle column has a min-width so it holds space for the player cards
   even before they're dealt. */
.player-area {
  display: grid;
  grid-template-columns: 190px minmax(320px, 1fr) 190px;
  align-items: center;
  gap: 24px;
  justify-content: center;
}
.player-cards-col {
  text-align: center;
  min-width: 0;
}
.player-area .paytable-overlay.pt-play  { justify-self: end; }
.player-area .paytable-overlay.pt-trips { justify-self: start; }

/* Golden Joker paytable lives in the empty left strip of the bets row.
   position:absolute keeps it out of the .bet-row flex flow so it never
   pushes the chips when the row wraps on narrow widths. */
.bets-area .paytable-overlay.pt-joker {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
}
@media (max-width: 1100px) {
  /* Below the breakpoint where the side panel collapses, the bets row
     starts wrapping and there's no longer a reliable empty-left strip.
     Hide the joker overlay there — the side-panel "Joker Paytable" card
     already shows the same info. */
  .bets-area .paytable-overlay.pt-joker { display: none; }
}

/* --- Felt-integrated paytables ------------------------------------------
   Printed directly onto the felt as gold-on-green text (no box), flanking
   the player-cards column. A subtle text-shadow keeps them legible without
   adding a visible container so they feel like ink on the felt.
*/
.paytable-overlay {
  width: 190px;
  font-size: 12px;
  color: rgba(241, 233, 210, 0.9);
  pointer-events: none;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
}
.paytable-overlay h3 {
  margin: 0 0 6px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: #f5d67a;
  text-align: center;
  padding-bottom: 4px;
  border-bottom: 1px dashed rgba(245, 214, 122, 0.28);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}
.paytable-overlay ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
.paytable-overlay li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  padding: 2px 0;
  line-height: 1.35;
}
.paytable-overlay li span {
  opacity: 0.92;
}
.paytable-overlay li strong {
  color: #f5d67a;
  font-variant-numeric: tabular-nums;
  font-size: 12px;
}
.paytable-overlay li.pt-bonus {
  margin-top: 3px;
  padding-top: 4px;
  border-top: 1px dashed rgba(245, 214, 122, 0.28);
}
.paytable-overlay li.pt-bonus span,
.paytable-overlay li.pt-bonus strong {
  color: #f5d67a;
  text-shadow: 0 0 6px rgba(245, 214, 122, 0.4),
               0 1px 3px rgba(0, 0, 0, 0.7);
}

@media (max-width: 1100px) {
  .game-layout { flex-direction: column; align-items: center; }
  .side-panel {
    flex: 0 0 auto;
    width: 100%;
    max-width: 960px;
    flex-direction: row;
    flex-wrap: wrap;
    position: static;
  }
  .side-panel .pt-card { flex: 1 1 220px; }
  .paytable-overlay { width: 150px; font-size: 11px; }
  .paytable-overlay li strong { font-size: 11px; }
  .player-area { gap: 16px; }
}

/* On narrow screens the 3-column player area doesn't fit side-by-side.
   Collapse to a single column: paytables stack below the player cards,
   rendered as translucent cards so they're readable without the felt glow. */
@media (max-width: 820px) {
  .player-area {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .player-area .paytable-overlay.pt-play,
  .player-area .paytable-overlay.pt-trips {
    justify-self: center;
  }
  .paytable-overlay {
    width: auto;
    max-width: 360px;
    padding: 12px 16px;
    background: rgba(0, 0, 0, 0.38);
    border: 1px solid rgba(245, 214, 122, 0.3);
    border-radius: 10px;
    font-size: 12px;
    text-shadow: none;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.35);
    pointer-events: auto;
  }
  .paytable-overlay h3 { text-shadow: none; }
  .paytable-overlay li strong { font-size: 12px; }
}

.label {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: rgba(245,214,122,0.8);
  margin-bottom: 6px;
  text-align: center;
}

.dealer-area, .community-area, .player-area {
  text-align: center;
}

.cards {
  display: flex;
  justify-content: center;
  gap: 12px;
  min-height: 146px;       /* matches card height below — no layout shift on deal */
  perspective: 1600px;
}

.card {
  /* Compacting the bet area to a single row freed ~170px of vertical space,
     letting the cards grow well past their original 96x134 size. Cards
     reserve their full size at all times so dealing never shifts layout. */
  width: 104px;
  height: 146px;
  position: relative;
  user-select: none;
  transform-style: preserve-3d;
}

/* Dealing entrance: slide in from the top-center "deck" position */
@keyframes cardDeal {
  0% {
    transform: translate(-45%, -130%) rotate(-16deg) scale(0.78);
    opacity: 0;
  }
  55% { opacity: 1; }
  100% {
    transform: translate(0, 0) rotate(0) scale(1);
    opacity: 1;
  }
}
.card.dealing { animation: cardDeal 0.55s cubic-bezier(0.2, 0.8, 0.25, 1); }

/* Flipper holds the front and back faces in a 3D pair */
.flipper {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.75s cubic-bezier(0.2, 0.8, 0.25, 1);
}
.card.face-down .flipper { transform: rotateY(180deg); }

.face {
  position: absolute;
  inset: 0;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  border-radius: 10px;
  overflow: hidden;
  box-shadow:
    0 5px 14px rgba(0,0,0,0.55),
    0 1px 3px rgba(0,0,0,0.45);
}
.face.back { transform: rotateY(180deg); }

.face > svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ----- Golden Joker card styling ------------------------------------------
   A card tagged .golden gets:
     - an animated gold border / box-shadow pulse
     - a semi-transparent gold tint over the front face
     - a traveling diagonal shimmer that sweeps across the face
   Together they make the card visibly "alive" as a wildcard.
*/
.card.golden .face.front {
  box-shadow:
    0 5px 14px rgba(0, 0, 0, 0.55),
    0 0 0 2px #f5d67a,
    0 0 18px 4px rgba(245, 214, 122, 0.85);
  animation: goldPulse 2s ease-in-out infinite;
}
@keyframes goldPulse {
  0%, 100% {
    box-shadow:
      0 5px 14px rgba(0, 0, 0, 0.55),
      0 0 0 2px #f5d67a,
      0 0 14px 3px rgba(245, 214, 122, 0.7);
  }
  50% {
    box-shadow:
      0 5px 14px rgba(0, 0, 0, 0.55),
      0 0 0 2px #ffe899,
      0 0 26px 8px rgba(255, 215, 100, 1);
  }
}

.face.front.golden-face {
  position: relative;
}
/* The gold card artwork is already warm — no extra tint overlay needed.
   Only the traveling shimmer sits above it. */

/* The shimmer — a diagonal band of highlight that sweeps across the card. */
.gold-shimmer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  border-radius: inherit;
}
.gold-shimmer::before {
  content: "";
  position: absolute;
  top: -50%;
  left: -60%;
  width: 60%;
  height: 200%;
  background: linear-gradient(115deg,
    transparent 0%,
    rgba(255, 255, 255, 0) 30%,
    rgba(255, 255, 255, 0.55) 50%,
    rgba(255, 255, 255, 0) 70%,
    transparent 100%);
  transform: rotate(0deg);
  animation: goldShimmer 2.4s ease-in-out infinite;
}
@keyframes goldShimmer {
  0%   { left: -60%; opacity: 0; }
  25%  { opacity: 1; }
  60%  { left: 110%; opacity: 1; }
  100% { left: 110%; opacity: 0; }
}

/* ============================================================================
   LIGHTNING STRIKE — fires ONCE when the wildcard lands on the board
   (community card). Three layers of drama:
     1. Fullscreen flash overlay (`.lightning-flash`) — whites out the entire
        viewport for ~80ms, then strobes a few times over ~1.6s.
     2. Per-card lightning burst (`.lightning-burst`) — bright halo that
        radiates well beyond the card edge.
     3. Per-card jagged bolt SVG — bigger, brighter, with a fork.
   All three auto-clean after the animation completes (ui.js handles removal).
   ============================================================================ */

/* (1) FULLSCREEN FLASH — fixed-positioned, tops the entire viewport.
   Sits at very high z-index so it overlays modals, banners, everything.
   Multiple sharp opacity pulses simulate the staccato of a real strike. */
.lightning-flash {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 10000;
  background: radial-gradient(ellipse at center,
    rgba(255, 255, 255, 1)    0%,
    rgba(220, 235, 255, 0.95) 25%,
    rgba(170, 200, 255, 0.7)  50%,
    rgba(110, 160, 255, 0.3)  75%,
    rgba(60,  100, 200, 0)    100%);
  mix-blend-mode: screen;
  opacity: 0;
  animation: fullscreenFlash 1600ms cubic-bezier(0.15, 0.8, 0.3, 1) forwards;
}
@keyframes fullscreenFlash {
  0%   { opacity: 0; }
  3%   { opacity: 0.95; }    /* Initial whiteout */
  8%   { opacity: 0.55; }
  12%  { opacity: 0.95; }    /* Second flash */
  18%  { opacity: 0.30; }
  24%  { opacity: 0.85; }    /* Third flash */
  35%  { opacity: 0.20; }
  50%  { opacity: 0.45; }    /* Lingering glow */
  70%  { opacity: 0.15; }
  100% { opacity: 0; }
}

/* (2) PER-CARD BURST — a bright halo that radiates well beyond the card edge.
   inset: -50px so the glow pours out around the card. */
.lightning-burst {
  position: absolute;
  inset: -50px;
  pointer-events: none;
  border-radius: 50%;
  z-index: 50;
  overflow: visible;
}
.lightning-burst::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(ellipse at center,
    rgba(255, 255, 255, 1)    0%,
    rgba(210, 230, 255, 0.85) 25%,
    rgba(160, 200, 255, 0.55) 50%,
    rgba(100, 160, 255, 0.2)  75%,
    rgba(60,  100, 200, 0)    100%);
  mix-blend-mode: screen;
  opacity: 0;
  animation: cardHaloFlash 1600ms cubic-bezier(0.15, 0.8, 0.3, 1) forwards;
}
.lightning-burst svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  /* Strong glow + slight bloom for an electrical look */
  filter:
    drop-shadow(0 0 8px rgba(220, 235, 255, 1))
    drop-shadow(0 0 18px rgba(170, 210, 255, 0.85))
    drop-shadow(0 0 36px rgba(110, 170, 255, 0.55));
  opacity: 0;
  animation: lightningBolt 1600ms cubic-bezier(0.15, 0.8, 0.3, 1) forwards;
}
@keyframes cardHaloFlash {
  0%   { opacity: 0; transform: scale(0.6); }
  4%   { opacity: 1; transform: scale(1.0); }
  10%  { opacity: 0.55; transform: scale(1.05); }
  14%  { opacity: 1; transform: scale(1.08); }
  22%  { opacity: 0.4; transform: scale(1.10); }
  30%  { opacity: 0.85; transform: scale(1.13); }
  50%  { opacity: 0.35; transform: scale(1.18); }
  75%  { opacity: 0.15; transform: scale(1.22); }
  100% { opacity: 0; transform: scale(1.25); }
}
@keyframes lightningBolt {
  0%   { opacity: 0; transform: scale(0.5); }
  4%   { opacity: 1; transform: scale(1.0); }
  10%  { opacity: 0.5; transform: scale(1.02); }
  14%  { opacity: 1; transform: scale(1.04); }
  22%  { opacity: 0.4; transform: scale(1.06); }
  30%  { opacity: 0.95; transform: scale(1.08); }
  50%  { opacity: 0.5; transform: scale(1.12); }
  100% { opacity: 0; transform: scale(1.18); }
}

/* Joker substitution overlay: sits on top of the golden card and alternates
   between invisible (showing the joker beneath) and fully visible (showing
   the card the wildcard "became" at showdown). */
.joker-sub-overlay {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  animation: jokerSubAlternate 2.4s ease-in-out infinite;
  /* Warm gold glow around the substitution card so it still reads as the
     magical wildcard rather than a normal card on top of a joker. */
  box-shadow:
    inset 0 0 0 2px rgba(245, 214, 122, 0.85),
    inset 0 0 14px rgba(245, 214, 122, 0.35);
}
.joker-sub-overlay svg {
  display: block;
  width: 100%;
  height: 100%;
}
@keyframes jokerSubAlternate {
  0%, 30%   { opacity: 0; }
  45%, 75%  { opacity: 1; }
  90%, 100% { opacity: 0; }
}

/* Gold-tinted label wherever we want to call out the feature in the UI. */
.gold-text {
  color: #f5d67a;
  text-shadow: 0 0 6px rgba(245, 214, 122, 0.5);
}

/* ----- Winning-hand card highlights ---------------------------------------
   Cards that are part of the winning side's best 5-card hand lift forward
   with a modest scale + translateY and a stronger drop shadow. Cards NOT
   part of the winning hand fade back with reduced opacity so the contrast
   is clear without requiring big scale values that would clip neighbours.

   The dim is gated on .cards:has() a used card so it only applies after
   showdown, not during normal dealing.
*/
.card.used-by-player,
.card.used-by-dealer {
  transform: scale(1.07) translateY(-18px);
  z-index: 10;
  transition:
    transform 0.45s cubic-bezier(0.2, 0.8, 0.3, 1.15),
    opacity 0.4s ease;
}
.card.used-by-player .face.front,
.card.used-by-dealer .face.front {
  box-shadow:
    0 18px 32px rgba(0, 0, 0, 0.8),
    0 5px 12px rgba(0, 0, 0, 0.55),
    0 0 0 1px rgba(245, 214, 122, 0.45);
}
/* Fade unused cards in any row that has at least one used card. Uses :has()
   which is well-supported in modern browsers. */
.cards:has(.card.used-by-player, .card.used-by-dealer)
  .card:not(.used-by-player):not(.used-by-dealer) {
  opacity: 0.35;
  filter: saturate(0.6);
  transition: opacity 0.4s ease, filter 0.4s ease;
}

.hand-name {
  margin-top: 8px;
  min-height: 20px;
  font-style: italic;
  color: #f5d67a;
  font-size: 14px;
}

.bets-area {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 8px 0;
  border-top: 1px dashed rgba(245,214,122,0.25);
  border-bottom: 1px dashed rgba(245,214,122,0.25);
}

/* Single-row bet strip:
     [Joker]  [−Big Hand+]  [−Ante Blind+]  [Play]
   Top-level children are either:
     * a solo .bet-spot (Joker, Play) — a vertical column: label on top, chip below
     * a .bet-stepper.stepper-inline pill containing one or more .bet-spots
       flanked by [−] / [+] buttons
   align-items: flex-end so every chip's bottom edge lines up across the row,
   regardless of whether the item is wrapped in a stepper or not. Labels
   naturally float upward above the chips. */
.bet-row {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 8px 24px;
  margin: 0 auto;
}
.bet-row > .bet-spot,
.bet-row > .bet-stepper {
  align-items: center;      /* center each column on its own chip axis */
}

/* Read-only Play chip is always $0 in idle — hide to reduce noise. Kept
   visible as soon as body.in-hand is applied. */
body.idle .bet-row .bet-play-cell {
  visibility: hidden;
}
/* ...but keep its slot so the row width doesn't reshuffle between idle and
   in-hand. `visibility: hidden` preserves layout. */

/* Stepper-inline: one or more .bet-spot chips sit INSIDE the stepper,
   flanked by ± step buttons on the left and right edges of the per-bet
   coloured pill. Pair variant (Ante+Blind) has TWO bet-spots between the
   buttons. `align-items: flex-end` puts step buttons flush with the chip
   bottoms so they sit on the same baseline as the chip, with the labels
   floating upward above only the chips. */
.bet-stepper.stepper-inline {
  display: flex;
  flex-direction: row;
  align-items: flex-end;
  gap: 8px;
  padding: 3px 8px 5px;
  position: relative;
}
/* Inside a stepper, the step button must vertically align with the CHIP
   (not the whole column label+chip). Adding a bottom margin equal to ~half
   the chip height centers the button visually against the chip. */
.bet-stepper.stepper-inline .step-btn {
  margin-bottom: 18px;    /* nudge up so the button center sits at chip center */
}
.bet-stepper.stepper-inline .bet-spot {
  gap: 4px;
}

/* Hidden input — keeps the JS contract for bindBetInput / value sync without
   taking any visual space. Accessible technologies can still interact with
   it if we ever un-hide it, though tabindex=-1 keeps it out of tab order. */
.bet-input-hidden {
  position: absolute !important;
  left: -9999px !important;
  width: 1px !important;
  height: 1px !important;
  opacity: 0 !important;
  pointer-events: none !important;
}
/* "Place your bets" speech-bubble tip. Sits above the bet grid in idle
   state; hidden once the player places a valid Ante. The little triangle
   tail at the bottom centre points down at the bet area. Pulses gently
   so it draws the eye without being annoying. */
.bet-help-bubble {
  position: relative;
  display: inline-block;
  align-self: center;
  margin: 0 auto 14px;
  padding: 8px 16px;
  background: rgba(245, 214, 122, 0.18);
  border: 1.5px solid rgba(245, 214, 122, 0.7);
  border-radius: 18px;
  color: #fff0bf;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: center;
  box-shadow: 0 2px 14px rgba(245, 214, 122, 0.18);
  animation: bet-help-pulse 1.8s ease-in-out infinite;
}
.bet-help-bubble::after {
  /* Down-pointing triangle "tail" centred at the bottom of the bubble.
     Used by the bonus-prompt state (which sits right above row 1's chips). */
  content: '';
  position: absolute;
  left: 50%;
  bottom: -10px;
  transform: translateX(-50%);
  width: 0; height: 0;
  border-left:  9px solid transparent;
  border-right: 9px solid transparent;
  border-top:  10px solid rgba(245, 214, 122, 0.7);
  filter: drop-shadow(0 1px 0 rgba(0,0,0,0.4));
}
/* When the bubble is anchored to a specific element, JS sets
   --anchor-x / --anchor-y to the target's top-center coordinates (relative
   to the bubble's offsetParent, which is the .bets-area).
   The bubble's BOTTOM-CENTER sits --bubble-offset pixels above that anchor
   point, with a stem of --arrow-length connecting it to the target.

   Two presets:
     * default        → small offset, short stem (used for row-1 targets:
                        joker chip, big-hand stepper input)
     * .long-arrow    → big offset so the bubble clears row 1 entirely,
                        long stem reaching down to the row-2 target
                        (used for the ante helper, whose target is the ante
                        stepper input in row 2). Without this, the bubble
                        body would visually cover the row-1 bonus stepper. */
.bet-help-bubble.anchored {
  position: absolute;
  margin: 0;
  z-index: 5;
  /* All bubbles use the same close-to-target placement: bubble bottom
     sits 12px above the anchor point, with just a small downward triangle
     tail that visually touches the target. No gold stem. */
  --bubble-offset: 12px;
  left: var(--anchor-x, 50%);
  top:  var(--anchor-y, 0);
  transform: translate(-50%, calc(-100% - var(--bubble-offset)));
  scale: 1;
  animation: bet-help-pulse-scale 1.8s ease-in-out infinite;
}
@keyframes bet-help-pulse-scale {
  0%, 100% { scale: 1; }
  50%      { scale: 1.02; }
}
/* Anchored bubbles override the default bottom-of-bubble triangle so we
   can size and colour it consistently across all three helpers. */
.bet-help-bubble.anchored::after {
  background: transparent;
  width: 0;
  height: 0;
  border: none;
  border-left:  9px solid transparent;
  border-right: 9px solid transparent;
  border-top:  10px solid rgba(245, 214, 122, 0.85);
  bottom: -10px;
  border-radius: 0;
  filter: drop-shadow(0 1px 0 rgba(0,0,0,0.4));
}
.bet-help-bubble.anchored::before {
  /* No separate arrowhead — the ::after triangle is the only tail. */
  display: none;
}
.bet-help-bubble.hidden { display: none; }
.bet-help-link {
  margin-left: 8px;
  color: #ffe899;
  text-decoration: underline;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}
.bet-help-link:hover { color: #fff6d5; }
.bet-help-link.hidden { display: none; }

/* Bonus bubble variant — narrower so the two of them (Big Hand + Joker)
   can sit side-by-side above their respective targets without colliding.
   Text wraps naturally to two lines inside the pill. */
.bet-help-bubble.bonus-bubble {
  max-width: 130px;
  font-size: 11px;
  padding: 6px 10px;
  text-align: center;
  line-height: 1.25;
  /* Allow the tooltip below to escape the pill bounds. */
  overflow: visible;
}
.bet-help-bubble.bonus-bubble .bet-help-text { display: block; }
.bet-help-bubble.bonus-bubble .bet-help-link { margin-left: 0; font-size: 11px; }

/* Inline tooltip on the "Learn" word in each bonus bubble. Shown on
   hover (desktop) or focus (touch — tapping the span gives it focus).
   Click outside to dismiss on mobile. */
.bet-help-tip {
  display: inline-block;
  margin-top: 2px;
  position: relative;
  cursor: help;
  font-weight: 700;
  color: #ffe899;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
  outline: none;
}
.bet-help-tip:hover, .bet-help-tip:focus { color: #fff6d5; }
.bet-help-tip-content {
  display: none;
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: 200px;
  padding: 8px 10px;
  background: #0f1a11;
  color: #f5d67a;
  border: 1px solid rgba(245, 214, 122, 0.55);
  border-radius: 6px;
  font-size: 11px;
  font-weight: 500;
  font-style: normal;
  text-align: left;
  text-decoration: none;
  line-height: 1.35;
  letter-spacing: 0;
  white-space: normal;
  z-index: 20;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.55);
}
/* Tooltip arrow — small triangle below the tooltip body. */
.bet-help-tip-content::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -7px;
  transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-top: 7px solid rgba(245, 214, 122, 0.55);
}
.bet-help-tip:hover .bet-help-tip-content,
.bet-help-tip:focus .bet-help-tip-content,
.bet-help-tip:focus-within .bet-help-tip-content {
  display: block;
}
@keyframes bet-help-pulse {
  0%, 100% { transform: translateY(0)    scale(1); }
  50%      { transform: translateY(-2px) scale(1.02); }
}

/* ----- Inline "i" info badge next to a bet label ---------------------------
   Always-visible reference tip (as opposed to .bet-help-bubble which pulses
   and then hides once the bet is placed). Used next to Joker and Big Hand
   labels so players can read the rules at any time during setup, not just
   when the pulsing helper bubble is up.
   Hover or focus reveals the tooltip body; focus-within keeps it open on
   touch after tapping. */
.info-tip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: rgba(245, 214, 122, 0.18);
  border: 1px solid rgba(245, 214, 122, 0.5);
  color: #f5d67a;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 10px;
  font-style: italic;
  font-weight: 700;
  line-height: 1;
  margin-left: 4px;
  position: relative;
  cursor: help;
  letter-spacing: 0;
  text-transform: none;
  vertical-align: middle;
  outline: none;
  user-select: none;
}
.info-tip:hover,
.info-tip:focus {
  background: rgba(245, 214, 122, 0.32);
  border-color: rgba(245, 214, 122, 0.85);
  color: #fff6d5;
}

.info-tip-content {
  display: none;
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: 220px;
  padding: 9px 11px;
  background: #0f1a11;
  color: #f5d67a;
  border: 1px solid rgba(245, 214, 122, 0.55);
  border-radius: 6px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  font-style: normal;
  text-align: left;
  line-height: 1.4;
  letter-spacing: 0;
  text-transform: none;
  white-space: normal;
  z-index: 30;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.55);
}
.info-tip-content::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -7px;
  transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-top: 7px solid rgba(245, 214, 122, 0.55);
}
.info-tip:hover .info-tip-content,
.info-tip:focus .info-tip-content,
.info-tip:focus-within .info-tip-content {
  display: block;
}
@media (max-width: 480px) {
  .bet-help-bubble { font-size: 11px; padding: 6px 12px; margin-bottom: 10px; }
  .bet-help-link { margin-left: 6px; }
}

/* Each bet "slot" is a small label + the chip beneath, stacked vertically. */
.bet-row .bet-spot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
/* When a help-bubble is anchored to this spot's chip, hide the chip label
   so the bubble's arrow doesn't overlay the gold text. The bubble already
   says "Try the Golden Joker" / etc. so the short label is redundant. */
.bet-row .bet-spot.helper-active .bet-label {
  visibility: hidden;
}
.bet-row .bet-label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: rgba(245, 214, 122, 0.75);
  font-weight: 700;
  line-height: 1;
}
.bet-row .bet-stepper {
  /* Steppers sit at the bottom of their row, aligned with the chip. */
  align-self: end;
  padding-bottom: 0;
}
.bet-row .bet-stepper {
  display: flex;
  align-items: center;
  gap: 4px;
  /* Subtle pill background hints which chip family this stepper belongs to.
     The colour is overridden per-row below (purple for Big Hand, red for
     Ante) so the eye groups stepper + chip together at a glance. */
  padding: 3px 5px;
  border-radius: 18px;
  border: 1px solid transparent;
  background: rgba(0, 0, 0, 0.18);
}
.bet-row .bet-stepper .step-btn {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(245, 214, 122, 0.12);
  border: 1px solid rgba(245, 214, 122, 0.4);
  color: #f5d67a;
  cursor: pointer;
  font-weight: 700;
  font-size: 16px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
  padding: 0;
  transition: background 0.15s, border-color 0.15s;
}
.bet-row .bet-stepper .step-btn:hover {
  background: rgba(245, 214, 122, 0.28);
  border-color: rgba(245, 214, 122, 0.7);
}
.bet-row .bet-stepper .step-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.bet-row .bet-stepper .bet-input-num {
  width: 60px;
  padding: 4px 6px;
  background: #0f1a11;
  border: 1px solid #38432c;
  border-radius: 5px;
  color: #f5d67a;
  font-family: inherit;
  font-weight: 700;
  font-size: 13px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  outline: none;
  /* Hide the native spinner — we have our own +/- buttons. */
  -moz-appearance: textfield;
}
.bet-row .bet-stepper .bet-input-num::-webkit-outer-spin-button,
.bet-row .bet-stepper .bet-input-num::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.bet-row .bet-stepper .bet-input-num:focus {
  border-color: #b88a2c;
  box-shadow: 0 0 0 1px rgba(184, 138, 44, 0.4);
}

/* Per-row colour-coding so it's obvious which chip the stepper drives.
   The Big Hand stepper picks up the purple bet-trips palette; the Ante
   stepper picks up the red ante palette. Joker has no stepper — it's a
   single click-to-toggle chip — so it can never be confused with these.
   The +/- buttons stay gold for legibility. */
.bet-row .bet-stepper[data-bet="trips"] {
  background: rgba(152, 93, 204, 0.14);
  border-color: rgba(183, 94, 220, 0.45);
  box-shadow: 0 0 0 1px rgba(183, 94, 220, 0.10);
}
.bet-row .bet-stepper[data-bet="trips"] .bet-input-num {
  border-color: rgba(183, 94, 220, 0.55);
  color: #e8c4ff;
  background: rgba(40, 12, 56, 0.55);
}
.bet-row .bet-stepper[data-bet="trips"] .bet-input-num:focus {
  border-color: #c874e6;
  box-shadow: 0 0 0 1px rgba(200, 116, 230, 0.5);
}
.bet-row .bet-stepper[data-bet="ante"] {
  background: rgba(197, 26, 26, 0.10);
  border-color: rgba(197, 26, 26, 0.40);
}
.bet-row .bet-stepper[data-bet="ante"] .bet-input-num {
  border-color: rgba(197, 26, 26, 0.55);
  color: #ffd3d3;
  background: rgba(46, 8, 8, 0.55);
}
.bet-row .bet-stepper[data-bet="ante"] .bet-input-num:focus {
  border-color: #e54545;
  box-shadow: 0 0 0 1px rgba(229, 69, 69, 0.5);
}

/* Joker chip is clickable (it's a <button>); strip the default look. */
.chips.chip-gj {
  background: radial-gradient(circle at 30% 30%, #333 0%, #111 70%);
  cursor: pointer;
  font-family: inherit;
  padding: 0;
}
.chips.chip-gj.active {
  /* Override the generic .active = red so GJ stays gold. */
  background: radial-gradient(circle at 30% 30%, #ffe899 0%, #8b6914 75%);
  border-color: #fff6d5;
  box-shadow: 0 0 16px rgba(245, 214, 122, 0.7);
  color: #2a1a05;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
}

/* Play chip spans the full width of the grid and centres itself. */
.bet-play-cell {
  grid-column: 1 / -1;
  justify-self: center;
}

/* Balance display at the right end of the bet row.
   Mimics a chip's label-above-value layout but with a pill shape instead
   of a circle so it reads as a DISPLAY not a wager. Visual intent: glanceable
   running stack next to the bet area. In the future this will mirror the
   top-right balance button once that gets its wallet menu. */
.bet-balance-cell .bet-balance {
  min-width: 78px;
  padding: 10px 14px;
  border-radius: 24px;
  background: linear-gradient(180deg, rgba(245, 214, 122, 0.18), rgba(245, 214, 122, 0.08));
  border: 1.5px solid rgba(245, 214, 122, 0.55);
  color: #fff0bf;
  font-weight: 800;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
  box-shadow:
    0 0 10px rgba(245, 214, 122, 0.18),
    inset 0 0 10px rgba(245, 214, 122, 0.10);
  letter-spacing: 0.02em;
  /* Subtle pulse when the amount changes (added/removed by ui.js). */
  transition: transform 180ms ease, box-shadow 180ms ease;
}
.bet-balance-cell .bet-balance.flash {
  transform: scale(1.08);
  box-shadow:
    0 0 20px rgba(245, 214, 122, 0.55),
    inset 0 0 14px rgba(245, 214, 122, 0.20);
}

/* While a hand is in progress, hide the +/- controls (bets are committed)
   and stop the joker chip from looking interactive.
   Note: the chip itself lives INSIDE the .bet-stepper pill with the new
   inline layout, so we target .step-btn specifically — hiding the whole
   stepper would also hide the chip which we still want visible. */
.bets-area.in-hand .bet-row .bet-stepper .step-btn { visibility: hidden; }
/* Also fade the per-bet pill background during a hand so the chip stands
   alone visually — it's showing the committed wager, not an editable one. */
.bets-area.in-hand .bet-row .bet-stepper {
  background: transparent !important;
  border-color: transparent !important;
  box-shadow: none !important;
}
.bets-area.in-hand .chips.chip-gj { cursor: default; }
.bets-area.in-hand .chips.chip-gj:hover { filter: none; }

/* Balance is rendered in the topbar (.topbar-balance variant). The base
   .balance-inline class just centres its content; the topbar variant adds
   the topbar sizing. */
.balance-inline {
  text-align: center;
}

/* Topbar variant: small label + bold amount, sits between the brand and
   the action buttons. Uses the same gold palette as the topbar buttons
   so it reads as part of the same row of UI. */
.topbar-balance {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-left: auto;       /* push self + topbar-right to the right of brand */
  margin-right: 14px;
  padding: 3px 12px 4px;
  border: 1px solid rgba(245, 214, 122, 0.4);
  border-radius: 8px;
  background: rgba(245, 214, 122, 0.10);
  line-height: 1;
}
.topbar-balance .balance-label {
  font-size: 9px;
  letter-spacing: 0.18em;
  color: rgba(245, 214, 122, 0.7);
  margin-bottom: 2px;
  text-transform: uppercase;
}
.topbar-balance .balance-amount {
  font-size: 17px;
  font-weight: 700;
  color: #f5d67a;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 10px rgba(245, 214, 122, 0.4);
}
@media (max-width: 640px) {
  .topbar-balance { margin-right: 8px; padding: 2px 8px 3px; }
  .topbar-balance .balance-amount { font-size: 14px; }
  .topbar-balance .balance-label { font-size: 8px; }
}
@media (max-width: 480px) {
  .topbar-balance { padding: 1px 6px 2px; }
  .topbar-balance .balance-amount { font-size: 13px; }
}
/* Older bets-area balance styles removed — balance now lives in the topbar
   via .topbar-balance. See above. */
.bet-spot {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 80px;
}
.bet-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(245,214,122,0.7);
  margin-bottom: 6px;
}
.chips {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, #333 0%, #111 70%);
  border: 3px dashed rgba(245,214,122,0.4);
  color: #f5d67a;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 13px;
  position: relative;
  overflow: visible;
}
.chips.active {
  background: radial-gradient(circle at 30% 30%, #c51a1a 0%, #7a0e0e 70%);
  border-color: #fdfdfb;
  border-style: solid;
  box-shadow: 0 0 12px rgba(245,214,122,0.4);
  color: #fff;
}

/* Per-bet accent colors: Trips = purple, Golden Joker = gold */
#bet-trips {
  border-color: rgba(183, 94, 220, 0.5);
  color: #e8c4ff;
}
#bet-trips.active {
  background: radial-gradient(circle at 30% 30%, #c874e6 0%, #4a1170 75%);
  border-color: #f1d9ff;
  box-shadow: 0 0 14px rgba(183, 94, 220, 0.55);
  color: #fff;
}

#bet-gj {
  border-color: rgba(245, 214, 122, 0.55);
  color: #f5d67a;
}
#bet-gj.active {
  background: radial-gradient(circle at 30% 30%, #ffe899 0%, #8b6914 75%);
  border-color: #fff6d5;
  box-shadow: 0 0 16px rgba(245, 214, 122, 0.7);
  color: #2a1a05;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
}

/* ----- Win-chip animation -------------------------------------------------
   When the player wins on a bet spot, a stack of coloured chips drops in
   from above and settles onto the spot. Each chip's --stack-offset (0..N)
   raises it a few px so the stack feels piled, and its animation-delay is
   staggered so they land in sequence.
*/
.win-chip {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, #ff3a3a 0%, #7a0e0e 75%);
  border: 3px dashed rgba(255, 255, 255, 0.55);
  box-shadow:
    0 4px 10px rgba(0, 0, 0, 0.6),
    inset 0 0 0 4px rgba(255, 255, 255, 0.08),
    inset 0 -4px 6px rgba(0, 0, 0, 0.25);
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%);
  animation: chipDropIn 0.55s cubic-bezier(0.2, 0.7, 0.25, 1.1) forwards;
}
.win-chip.chip-play  { background: radial-gradient(circle at 30% 30%, #ff5252 0%, #6a0c0c 75%); }
.win-chip.chip-trips {
  background: radial-gradient(circle at 30% 30%, #d87aee 0%, #3c0d5a 75%);
  border-color: rgba(255, 235, 255, 0.7);
}
.win-chip.chip-gold {
  background: radial-gradient(circle at 30% 30%, #fff1a8 0%, #8b6914 75%);
  border-color: rgba(255, 250, 220, 0.8);
}

@keyframes chipDropIn {
  0% {
    transform: translate(calc(-50% - 18px), -210%) scale(0.55) rotate(-35deg);
    opacity: 0;
  }
  55% { opacity: 1; }
  80% {
    transform: translate(-50%, calc(-50% - var(--stack-offset, 0) * 4px + 3px)) scale(1.04) rotate(2deg);
  }
  100% {
    transform: translate(-50%, calc(-50% - var(--stack-offset, 0) * 4px)) scale(1) rotate(0);
    opacity: 1;
  }
}

.status-area { text-align: center; }
.status { font-size: 16px; color: #f1e9d2; min-height: 22px; }
.result {
  margin-top: 6px;
  font-weight: 700;
  font-size: 18px;
  min-height: 26px;
}
.result.win { color: #7ef5a0; }
.result.lose { color: #ff7a7a; }
.result.push { color: #f5d67a; }

/* When the result contains both a main outcome and a Trips-bonus call-out,
   the main text keeps its win/lose/push colour (inherited from the parent
   .result.* class) while the Trips line always reads as a win in purple. */
.result .result-main { display: inline-block; }
.result .result-trips {
  display: inline-block;
  margin-left: 12px;
  padding: 2px 10px;
  border-radius: 999px;
  background: rgba(152, 93, 204, 0.18);
  border: 1px solid rgba(200, 150, 240, 0.5);
  color: #d8b4f8;
  font-size: 0.85em;
  font-weight: 700;
  vertical-align: middle;
}
@media (max-width: 640px) {
  .result .result-trips { display: block; margin: 4px 0 0; }
}

/* ----- Result breakdown panel --------------------------------------------
   Shown at showdown. Lists each component of the hand separately (Main Game
   bets, Trips bonus, Golden Joker) with wager, outcome pill, and net result.
*/
.result-breakdown {
  margin: 10px auto 0;
  max-width: 460px;
  padding: 12px 18px 14px;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(245, 214, 122, 0.3);
  border-radius: 10px;
  text-align: left;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
}
.result-breakdown.hidden { display: none; }
.rb-header {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: #f5d67a;
  padding: 4px 0 6px;
  margin: 0 0 8px;
  border-bottom: 1px dashed rgba(245, 214, 122, 0.3);
  background: none;
  border-left: none;
  border-right: none;
  border-top: none;
  cursor: pointer;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-weight: 700;
  font-family: inherit;
}
.rb-header:hover { color: #fff0bf; }
.rb-chevron {
  display: inline-block;
  font-size: 10px;
  transition: transform 0.22s ease;
  color: rgba(245, 214, 122, 0.75);
}
.result-breakdown.collapsed .rb-chevron { transform: rotate(-90deg); }
.result-breakdown.collapsed .rb-header {
  border-bottom: none;
  padding-bottom: 2px;
  margin-bottom: 0;
}
.result-breakdown.collapsed .rb-section,
.result-breakdown.collapsed .rb-total { display: none; }
.result-breakdown.collapsed { padding-bottom: 8px; }
.rb-section { margin-bottom: 8px; }
.rb-section:last-of-type { margin-bottom: 0; }
.rb-section-title {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: rgba(245, 214, 122, 0.75);
  margin: 2px 0 4px;
}
.rb-line {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  gap: 10px;
  align-items: center;
  padding: 4px 0;
  font-size: 13px;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.rb-line:first-child { border-top: none; }
.rb-name { color: #f1e9d2; font-weight: 600; }
.rb-wager {
  color: rgba(241, 233, 210, 0.55);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.rb-outcome {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 2px 9px;
  border-radius: 10px;
  text-transform: uppercase;
  white-space: nowrap;
}
.rb-outcome.win  { background: rgba(126, 245, 160, 0.16); color: #7ef5a0; }
.rb-outcome.lose { background: rgba(255, 122, 122, 0.16); color: #ff7a7a; }
.rb-outcome.push { background: rgba(245, 214, 122, 0.16); color: #f5d67a; }
.rb-net {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 54px;
  text-align: right;
}
.rb-net.win  { color: #7ef5a0; }
.rb-net.lose { color: #ff7a7a; }
.rb-net.push { color: rgba(245, 214, 122, 0.7); }
.rb-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(245, 214, 122, 0.35);
  font-weight: 700;
  color: #f1e9d2;
}
.rb-total-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
}
.rb-total-amount {
  font-size: 17px;
  font-variant-numeric: tabular-nums;
}
.rb-total-amount.win  { color: #7ef5a0; }
.rb-total-amount.lose { color: #ff7a7a; }
.rb-total-amount.push { color: #f5d67a; }

@media (max-width: 640px) {
  .result-breakdown { padding: 10px 12px; }
  .rb-line { grid-template-columns: 1fr auto auto; gap: 8px; font-size: 12px; }
  .rb-wager { display: none; }
  .rb-outcome { font-size: 9px; padding: 1px 7px; }
  .rb-total-amount { font-size: 15px; }
}

.controls {
  text-align: center;
  /* The controls section now lives inside .bets-area, directly under the
     bet-grid, so action buttons sit next to the chips they affect.
     Bottom margin keeps them off the player cards in the next section. */
  margin-top: 12px;
  margin-bottom: 6px;
  width: 100%;
}
.control-group {
  display: inline-flex;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
}
.control-group.hidden { display: none; }

/* --- Win banner ----------------------------------------------------------
   Splashy showdown-win banner stacked vertically with up to three lines:
     * main          (gold) — e.g. "FLUSH! ×3 WIN"
     * trips (BHB)   (purple) — e.g. "BIG HAND BONUS ×6!"
     * gj (joker)    (gold)  — e.g. "GOLDEN JOKER ×2!"
   Extra lines only appear when their respective side bets actually won.
   Pop-in animation on reveal; hides on next hand. */
.win-banner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  margin: 0 auto 14px;
  padding: 10px 28px;
  background: linear-gradient(180deg, rgba(245, 214, 122, 0.22) 0%, rgba(245, 214, 122, 0.10) 100%);
  border: 2px solid rgba(245, 214, 122, 0.85);
  border-radius: 12px;
  box-shadow:
    0 0 26px rgba(245, 214, 122, 0.32),
    0 6px 18px rgba(0, 0, 0, 0.5),
    inset 0 0 18px rgba(245, 214, 122, 0.18);
  animation: win-banner-pop 0.55s cubic-bezier(0.2, 0.9, 0.3, 1.2) both;
  will-change: transform, opacity;
}
.win-banner.hidden { display: none; }
.win-banner > span { display: inline-block; }
.win-banner > span.hidden { display: none; }

/* Main line: big gold text with the hand name + play multiplier. */
.win-banner-main {
  font-size: 38px;
  font-weight: 900;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff0bf;
  text-shadow:
    0 0 14px rgba(245, 214, 122, 0.85),
    0 2px 0 rgba(0, 0, 0, 0.55);
}

/* Big Hand Bonus line — purple to match the chip-trips / stepper palette. */
.win-banner-trips {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: #e8c4ff;
  text-shadow:
    0 0 10px rgba(183, 94, 220, 0.85),
    0 2px 0 rgba(0, 0, 0, 0.5);
}

/* Golden Joker line — gold/amber to match the joker chip. */
.win-banner-gj {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: #ffe899;
  text-shadow:
    0 0 10px rgba(245, 214, 122, 0.85),
    0 2px 0 rgba(0, 0, 0, 0.5);
}

@keyframes win-banner-pop {
  0%   { transform: scale(0.4) translateY(-6px); opacity: 0; }
  55%  { transform: scale(1.12) translateY(0);   opacity: 1; }
  100% { transform: scale(1)    translateY(0);   opacity: 1; }
}
/* Subtle idle breathe on the main line so the banner feels alive. */
.win-banner:not(.hidden) .win-banner-main {
  animation: win-banner-breathe 2.2s ease-in-out 0.6s infinite;
}
@keyframes win-banner-breathe {
  0%, 100% { transform: scale(1);    }
  50%      { transform: scale(1.03); }
}

/* Narrow viewports: scale down. */
@media (max-width: 640px) {
  .win-banner { padding: 8px 18px; }
  .win-banner-main { font-size: 28px; }
  .win-banner-trips, .win-banner-gj { font-size: 17px; }
}
@media (max-height: 720px) {
  .win-banner { padding: 6px 20px; margin-bottom: 8px; }
  .win-banner-main { font-size: 30px; }
  .win-banner-trips, .win-banner-gj { font-size: 18px; }
}

.bet-input { display: flex; flex-direction: column; align-items: center; }
.bet-input label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(245,214,122,0.7);
  margin-bottom: 4px;
}
.stepper {
  display: flex;
  align-items: center;
  gap: 8px;
}
.stepper span {
  min-width: 60px;
  text-align: center;
  font-weight: 700;
  font-size: 16px;
  color: #f5d67a;
}
.stepper button {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: #1e5b3f;
  color: #fff;
  font-weight: 700;
  cursor: pointer;
}
.stepper button:hover { background: #2a7a54; }

.toggle {
  padding: 8px 18px;
  border-radius: 16px;
  border: 2px solid rgba(245, 214, 122, 0.4);
  background: #1a4d34;
  color: #f1e9d2;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.1em;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
}
.toggle:hover { background: #235e40; }
.toggle[data-on="true"] {
  background: linear-gradient(180deg, #f5d67a 0%, #c9a23f 100%);
  color: #2a1a05;
  border-color: #fffadf;
  box-shadow: 0 0 12px rgba(245, 214, 122, 0.6);
}

button.primary, button.action {
  padding: 12px 22px;
  border: none;
  border-radius: 8px;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform 0.1s, background 0.15s;
}
button.primary {
  background: linear-gradient(180deg, #f5d67a 0%, #c9a23f 100%);
  color: #2a1a05;
}
button.primary:hover { transform: translateY(-1px); }
button.action {
  background: linear-gradient(180deg, #2a7a54 0%, #1a4d34 100%);
  color: #fff;
}
button.action:hover { background: linear-gradient(180deg, #34946a 0%, #1e5b3f 100%); }
/* Secondary action — Repeat last bet. Quieter visual weight than primary
   so Deal still reads as the dominant call-to-action. */
button.secondary {
  background: rgba(245, 214, 122, 0.12);
  border: 1px solid rgba(245, 214, 122, 0.5);
  color: #f5d67a;
}
button.secondary:hover:not(:disabled) {
  background: rgba(245, 214, 122, 0.22);
  border-color: rgba(245, 214, 122, 0.8);
  color: #fff0bf;
}
button.action.danger {
  background: linear-gradient(180deg, #a82222 0%, #6a1212 100%);
}
button.action.danger:hover { background: linear-gradient(180deg, #c82a2a 0%, #821616 100%); }
button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none !important;
}

/* --- Responsive breakpoints ---------------------------------------------- */

/* Short viewports (laptop screens ≤ 1080px tall) — compact layout but
   keep the cards large. We claw back vertical space by shrinking the bet
   chips, paytables, and label/gap whitespace instead. */
@media (max-height: 1080px) {
  /* Card size is set globally now (96x134) so the layout never shifts on
     deal — don't override here. Just trim other padding/gap to recover
     vertical space on shorter laptops. */
  .cards { gap: 8px; perspective: 1300px; }
  .table { gap: 10px; padding: 14px 24px 18px; }
  .bets-area { padding: 6px 0; }
  .bet-row { gap: 6px 12px; }
  .bet-row .bet-stepper .step-btn { width: 22px; height: 22px; font-size: 13px; }
  .bet-row .bet-stepper .bet-input-num { width: 50px; font-size: 11px; padding: 2px 4px; }
  .label { font-size: 10px; margin-bottom: 2px; letter-spacing: 0.12em; }
  .hand-name { font-size: 12px; margin-top: 2px; min-height: 14px; }
  .chips { width: 46px; height: 46px; font-size: 10px; border-width: 2px; }
  .bet-label { font-size: 9px; margin-bottom: 2px; }
  .bet-spot { min-width: 48px; }
  .paytable-overlay { width: 160px; font-size: 11px; }
  .paytable-overlay h3 { font-size: 9px; padding-bottom: 3px; margin-bottom: 3px; }
  .paytable-overlay li strong { font-size: 11px; }
  .paytable-overlay li { padding: 1px 0; line-height: 1.25; }
  .player-area { gap: 14px; grid-template-columns: 160px minmax(280px, 1fr) 160px; }
  button.primary, button.action { padding: 9px 16px; font-size: 12px; }
  .stepper button { width: 26px; height: 26px; }
  .stepper span { min-width: 46px; font-size: 13px; }
  .toggle { padding: 6px 12px; font-size: 11px; }
  .status { font-size: 13px; }
  .result { font-size: 15px; min-height: 18px; }
}

/* Very short viewports (≤ 850px tall) — even smaller chips and labels,
   cards still meaningfully visible. */
@media (max-height: 850px) {
  /* On really short laptops, drop the card a touch below the global default
     (96x134) so the felt fits comfortably. Cards stay reserved at min-height
     so layout never shifts on deal. */
  .card { width: 84px; height: 118px; }
  .cards { min-height: 126px; gap: 6px; perspective: 1100px; }
  .table { gap: 8px; padding: 10px 20px 14px; border-radius: 150px / 44px; }
  .bets-area { padding: 4px 0; }
  .bet-row { gap: 4px 10px; }
  .bet-row .bet-stepper .step-btn { width: 20px; height: 20px; font-size: 12px; }
  .bet-row .bet-stepper .bet-input-num { width: 44px; font-size: 10px; }
  .label { font-size: 9px; margin-bottom: 1px; }
  .hand-name { font-size: 11px; margin-top: 1px; }
  .chips { width: 40px; height: 40px; font-size: 9px; border-width: 2px; }
  .bet-label { font-size: 8px; margin-bottom: 2px; }
  .bet-spot { min-width: 42px; }
  .paytable-overlay { width: 148px; font-size: 10px; }
  .paytable-overlay h3 { font-size: 8px; }
  .paytable-overlay li strong { font-size: 10px; }
  .player-area { gap: 12px; grid-template-columns: 148px minmax(240px, 1fr) 148px; }
  button.primary, button.action { padding: 7px 12px; font-size: 11px; }
}

/* Small desktop / large tablet: keep the global 96x134 default; just trim
   table padding/border. */
@media (max-width: 1100px) {
  .table { border-radius: 160px / 50px; padding: 20px; }
}

/* Tablet — drop the cards a touch below the global default to fit. */
@media (max-width: 800px) {
  .card { width: 88px; height: 123px; }
  .cards { min-height: 131px; gap: 8px; }
  .table { padding: 18px; gap: 14px; }
}

/* Phone landscape / small tablet */
@media (max-width: 640px) {
  .topbar { padding: 10px 14px; gap: 12px; flex-wrap: wrap; }
  .topbar-right { gap: 6px; }
  .topbar-btn { padding: 5px 9px; font-size: 10px; letter-spacing: 0.03em; }
  .brand { font-size: 15px; line-height: 1.15; }
  .bankroll { font-size: 14px; }
  .game-layout { padding: 0 8px; gap: 10px; margin: 10px auto; }
  .table { padding: 14px 12px; border-radius: 120px / 40px; gap: 12px; }

  .card { width: 80px; height: 112px; }
  .cards { min-height: 118px; gap: 6px; }

  .label { font-size: 10px; margin-bottom: 4px; }
  .hand-name { font-size: 12px; margin-top: 6px; }

  .bets-area { padding: 10px 0; }
  .bet-row { gap: 6px 12px; }
  .chips { width: 52px; height: 52px; font-size: 11px; border-width: 2px; }
  .bet-row .bet-stepper { gap: 3px; }
  .bet-row .bet-stepper .step-btn { width: 22px; height: 22px; font-size: 13px; }
  .bet-row .bet-stepper .bet-input-num { width: 44px; font-size: 11px; padding: 3px 4px; }

  .status { font-size: 14px; }
  .result { font-size: 16px; }

  .control-group { gap: 8px; flex-wrap: wrap; justify-content: center; }
  button.primary, button.action {
    padding: 10px 16px;
    font-size: 12px;
  }

  .pt-card { font-size: 12px; padding: 12px 14px; }
  .pt-card h3 { font-size: 11px; }
  .side-panel { gap: 10px; }
}

/* Phone portrait — iPhone-sized viewports.
   Stack the title + buttons in the topbar and pull the balance into its
   own line so the bet grid gets the full row width to itself. */
@media (max-width: 480px) {
  .topbar { padding: 8px 10px; flex-wrap: wrap; gap: 6px; }
  .brand { font-size: 13px; flex-basis: 100%; }
  .topbar-right { width: 100%; justify-content: flex-end; }
  .topbar-btn { padding: 4px 7px; font-size: 9px; }
  .bankroll { font-size: 13px; }
  .game-layout { padding: 0 4px; gap: 8px; margin: 8px auto; }
  .table { padding: 10px 8px; border-radius: 90px / 32px; gap: 10px; }

  .card { width: 62px; height: 87px; }
  .cards { min-height: 93px; gap: 4px; }

  .bets-area { padding: 8px 0; flex-direction: column; }
  .bet-row { gap: 4px 10px; }
  .chips { width: 44px; height: 44px; font-size: 10px; }
  .bet-row .bet-stepper { gap: 2px; }
  .bet-row .bet-stepper .step-btn { width: 20px; height: 20px; font-size: 12px; }
  .bet-row .bet-stepper .bet-input-num { width: 38px; font-size: 10px; padding: 2px 3px; }

  .label { font-size: 9px; letter-spacing: 0.1em; }
  .hand-name { font-size: 11px; }

  .status { font-size: 12px; }
  .result { font-size: 14px; }
  .result .result-trips { font-size: 0.78em; padding: 2px 8px; }

  button.primary, button.action {
    padding: 9px 12px;
    font-size: 11px;
    letter-spacing: 0.03em;
  }
  .control-group { gap: 6px; }
}

/* Very small phones (iPhone SE, older Androids in portrait). */
@media (max-width: 380px) {
  .topbar { padding: 6px 8px; }
  .brand { font-size: 12px; }
  .topbar-btn { padding: 3px 5px; font-size: 8px; }
  .card { width: 54px; height: 75px; }
  .cards { min-height: 81px; gap: 3px; }
  .table { padding: 8px 6px; }
  button.primary, button.action { padding: 8px 10px; font-size: 10px; }
  .chips { width: 40px; height: 40px; font-size: 9px; }
  .bet-row { gap: 4px 8px; }
  .bet-row .bet-stepper .bet-input-num { width: 34px; font-size: 9px; }
  .bet-row .bet-stepper .step-btn { width: 18px; height: 18px; font-size: 11px; }
}
