/**
 * Poker Table Layout
 *
 * Shared component CSS for the poker table, seats, cards, actions, and dealer button.
 * Canonical source of truth. Imported by:
 *   - E:\Apps\poker-tool (base.html)
 *   - E:\Apps\video-engine (via Vite alias for hand-recap feature)
 *
 * Variables use CSS custom properties with fallback defaults so the file
 * can render standalone even when variables.css is not loaded.
 */

/* =====================================================================
   POKER TABLE CONTAINER
   ===================================================================== */

.poker-table-container {
    position: relative;
    flex: 1;
    min-width: 280px;
    max-width: 360px;
    aspect-ratio: 16 / 9;
    margin: 0 auto;
}

.poker-table {
    position: absolute;
    top: 7%;
    left: 3%;
    right: 3%;
    bottom: 7%;
    background: linear-gradient(145deg, #181822 0%, #252535 50%, #181822 100%);
    border-radius: 50% / 50%;
    border: 8px solid #3a3a5a;
    box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.3);
    margin: 0 auto;
}

.poker-table::before {
    content: '';
    position: absolute;
    top: 8px;
    left: 8px;
    right: 8px;
    bottom: 8px;
    border: 2px solid rgba(255, 255, 255, 0.1);
    border-radius: 50% / 50%;
}

/* =====================================================================
   POT & COMMUNITY CARDS
   ===================================================================== */

.table-pot {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: rgba(0, 0, 0, 0.7);
    padding: 5px 10px;
    border-radius: 10px;
    font-size: 0.7rem;
    color: #fff;
    font-weight: 700;
    letter-spacing: 0.02em;
    z-index: 6;
    white-space: nowrap;
}

.community-cards-center {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) translateY(-45px);
    display: flex;
    gap: 4px;
    z-index: 3;
}

.community-cards-center .playing-card {
    --card-width: 51px;
    --card-height: 66px;
    --card-font: 20px;
}

/* =====================================================================
   SEAT WRAPPERS
   ===================================================================== */

.seat-wrapper {
    position: absolute;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    z-index: 11;
}

.seat-wrapper:has(.villain-cards-revealed-on-seat) {
    z-index: 20;
}

.seat-wrapper:has(.seat-action) {
    z-index: 25;
}

.seat-wrapper:has(.seat-action.villain-action) {
    z-index: 26;
}

/* =====================================================================
   SEAT CIRCLES
   ===================================================================== */

.table-seat {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--bg-tooltip, #161636);
    border: 2px solid rgba(255, 255, 255, 0.14);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-size: 0.65rem;
    font-weight: 600;
    transition: all 0.2s;
}

.table-seat.hero {
    border-color: var(--action-call, #00e676);
    background: var(--bg-tooltip, #161636);
}

.table-seat.villain {
    border-color: var(--accent, #ff1a5e);
    background: var(--bg-tooltip, #161636);
    box-shadow: 0 0 8px rgba(var(--accent-rgb, 255, 26, 94), 0.5);
    animation: pulse-villain 1.5s infinite;
}

@keyframes pulse-villain {
    0%, 100% { box-shadow: 0 0 8px rgba(var(--accent-rgb, 255, 26, 94), 0.5); }
    50%       { box-shadow: 0 0 16px rgba(var(--accent-rgb, 255, 26, 94), 0.8), 0 0 24px rgba(var(--accent-rgb, 255, 26, 94), 0.3); }
}

.table-seat.active {
    border-color: var(--action-raise, #aa00ff);
    box-shadow: 0 0 0 3px rgba(var(--action-raise-rgb, 170, 0, 255), 0.3);
    animation: pulse-seat 1.5s infinite;
}

@keyframes pulse-seat {
    0%, 100% { box-shadow: 0 0 0 3px rgba(var(--action-raise-rgb, 170, 0, 255), 0.3); }
    50%       { box-shadow: 0 0 0 6px rgba(var(--action-raise-rgb, 170, 0, 255), 0.15); }
}

.table-seat.folded {
    opacity: 1;
    animation: none;
}

.table-seat.villain.folded {
    animation: none;
    box-shadow: none;
}

.table-seat.allin-persisted {
    border-color: #ff1744;
    animation: pulse-allin 2s ease-in-out infinite;
}

@keyframes pulse-allin {
    0%, 100% { box-shadow: 0 0 8px rgba(255, 23, 68, 0.5); }
    50%       { box-shadow: 0 0 16px rgba(255, 23, 68, 0.8), 0 0 24px rgba(255, 23, 68, 0.3); }
}

/* Hand-over state: at showdown / villain_reveal / result, suppress all seat
   glow/pulse animations so the final state reads as static. Renderers add
   `.hand-over` to the page-level wrapper (replay sets it on .replay-v2; quiz
   sets it on its quiz card when applicable). */
.hand-over .table-seat.allin-persisted,
.hand-over .table-seat.villain {
    animation: none;
    box-shadow: none;
    border-color: rgba(255, 255, 255, 0.15);
}

/* Hero seat must out-stack villain action seats (z-index 26) so the pulse
   ring renders on top of them when the hero is acting. */
.seat-wrapper:has(.hero-action-above.action-current) {
    z-index: 27;
}

.table-seat.seat-empty {
    border: 2px dashed rgba(255, 255, 255, 0.25) !important;
    background: rgba(255, 255, 255, 0.04) !important;
}

.seat-position {
    color: var(--text-muted, #8080a8);
    font-size: 0.8rem;
    text-transform: uppercase;
}

.table-seat.hero .seat-position,
.table-seat.villain .seat-position {
    color: inherit;
}

.seat-label {
    font-size: 0.55rem;
    color: var(--text, #f0f0f0);
    margin-top: 1px;
}

.table-seat.hero .seat-label {
    color: var(--action-call, #00e676);
}

.table-seat.villain .seat-label {
    color: var(--accent, #ff1a5e);
}

/* =====================================================================
   DEALER BUTTON
   ===================================================================== */

.dealer-button {
    position: absolute;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: linear-gradient(145deg, #ffffff, #e0e0e0);
    border: 2px solid #888;
    color: #333;
    font-size: 0.7rem;
    font-family: 'Arial Black', 'Arial Bold', Arial, sans-serif;
    font-weight: 900;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    padding-bottom: 1px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
    z-index: 30;
}

/* =====================================================================
   SEAT ACTION FILLS
   Replaces pill overlays. The seat circle itself becomes the action indicator.
   Intensity hierarchy: check (grey) → call (green) → bet (amber) → raise (bright amber) → all-in (red)
   All border colors sourced from existing variables.css tokens.
   ===================================================================== */

/* Base fill: same dimensions as .table-seat (44px default) */
.seat-action {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 2px solid #303050;
    background: #2a2a3c;
    color: #8080a0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    padding: 4px;
    text-align: center;
    line-height: 1.15;
    z-index: 12;
}

/* Check — muted grey, passive, no money moved */
.seat-action.action-check {
    --action-color: #9090b8;
    background: #1e1e30;
    border-color: #9090b8;
    color: rgba(220,220,240,0.75);
}

/* Call — green, --action-call / --winner-green */
.seat-action.action-call {
    --action-color: #00e676;
    background: #0a2818;
    border-color: #00e676;
    color: white;
    box-shadow: 0 0 12px rgba(0,230,118,0.55), 0 0 22px rgba(0,230,118,0.2);
}

/* Bet — amber, --warning-alt #ffa000 */
.seat-action.action-bet {
    --action-color: #ffa000;
    background: #2e1800;
    border-color: #ffa000;
    color: white;
    box-shadow: 0 0 12px rgba(255,160,0,0.65), 0 0 24px rgba(255,160,0,0.25);
}

.seat-action.action-bet.action-current {
    animation: pulse-bet 1.6s infinite;
}

@keyframes pulse-bet {
    0%, 100% { box-shadow: 0 0 12px rgba(255,160,0,0.65), 0 0 24px rgba(255,160,0,0.25); }
    50%       { box-shadow: 0 0 20px rgba(255,160,0,0.9),  0 0 38px rgba(255,160,0,0.4); }
}

/* Raise — same amber as bet */
.seat-action.action-raise {
    --action-color: #ffa000;
    background: #2e1800;
    border-color: #ffa000;
    color: white;
    box-shadow: 0 0 12px rgba(255,160,0,0.65), 0 0 24px rgba(255,160,0,0.25);
}

.seat-action.action-raise.action-current {
    animation: pulse-raise 1.4s infinite;
}

@keyframes pulse-raise {
    0%, 100% { box-shadow: 0 0 12px rgba(255,160,0,0.65), 0 0 24px rgba(255,160,0,0.25); }
    50%       { box-shadow: 0 0 22px rgba(255,160,0,0.9),  0 0 40px rgba(255,160,0,0.4); }
}

/* All-in — red, --loser-red / --error #ff1744 */
.seat-action.action-allin {
    --action-color: #ff1744;
    background: #2e0a10;
    border-color: #ff1744;
    color: white;
    box-shadow: 0 0 12px rgba(255,23,68,0.7), 0 0 24px rgba(255,23,68,0.3);
    animation: pulse-allin 1.3s infinite;
}

.seat-action.action-allin.action-current {
    animation: pulse-allin 1.3s infinite;
}

@keyframes pulse-allin {
    0%, 100% { box-shadow: 0 0 12px rgba(255,23,68,0.7),  0 0 24px rgba(255,23,68,0.3); }
    50%       { box-shadow: 0 0 22px rgba(255,23,68,0.95), 0 0 42px rgba(255,23,68,0.5); }
}

/* Ripple ring: fires once on the current action seat when a step advances.
   --action-color is set per action type and inherited by ::before. */
@keyframes action-enter-ripple {
    0%   { transform: scale(1);   opacity: 0.85; }
    100% { transform: scale(1.8); opacity: 0; }
}

.seat-action.action-current::before {
    content: '';
    position: absolute;
    inset: -2px;
    border-radius: 50%;
    border: 2px solid var(--action-color, #ffa000);
    pointer-events: none;
    animation: action-enter-ripple 0.9s ease-out forwards;
}

/* Fold — dark grey, uses --action-fold #646464 border */
.seat-action.fold,
.seat-action.action-fold {
    --action-color: #646464;
    background: #111118;
    border-color: #646464;
    color: rgba(150,150,165,0.75);
    animation: none;
}

/* In step-by-step replay, suppress glow on previous (non-current) actions.
   All-in is excluded — it always glows to signal a player is committed. */
.playback-card .seat-action.action-call:not(.action-current),
.playback-card .seat-action.action-bet:not(.action-current),
.playback-card .seat-action.action-raise:not(.action-current) {
    box-shadow: none;
}
.playback-card .layout-full-table .hero-action-above.call:not(.action-current),
.playback-card .layout-full-table .hero-action-above.action-call:not(.action-current),
.playback-card .layout-full-table .hero-action-above.bet:not(.action-current),
.playback-card .layout-full-table .hero-action-above.action-bet:not(.action-current),
.playback-card .layout-full-table .hero-action-above.raise:not(.action-current),
.playback-card .layout-full-table .hero-action-above.action-raise:not(.action-current) {
    box-shadow: none;
}

/* Fallback: villain-action without a recognised action-type class (excludes fold) */
.seat-action.villain-action:not(.action-check):not(.action-call):not(.action-bet):not(.action-raise):not(.action-allin):not(.fold):not(.action-fold) {
    background: #2e1800;
    border-color: #ffca28;
    color: white;
}

/* Hero action: no separate color rule — hero fills use action-type colors.
   Hero identity is signaled by the green border on .table-seat.hero, not the fill. */

/* Showdown result — WON */
.seat-action.action-won {
    --action-color: #00e676;
    background: #061c10;
    border-color: #00e676;
    color: white;
    box-shadow: 0 0 14px rgba(0,230,118,0.55), 0 0 26px rgba(0,230,118,0.2);
}

.seat-action.action-won .action-verb {
    font-size: 1rem;
    font-weight: 800;
    opacity: 1;
    color: #00e676;
    letter-spacing: 0.5px;
}

/* Showdown result — LOST */
.seat-action.action-lost {
    --action-color: #404058;
    background: #111118;
    border-color: #404058;
    color: rgba(150,150,165,0.6);
    box-shadow: none;
}

.seat-action.action-lost .action-verb {
    font-size: 1rem;
    font-weight: 800;
    opacity: 1;
    color: #9090b8;
    letter-spacing: 0.5px;
}

/* Suppress the villain ring glow when an action fill is covering the seat.
   The fill itself provides the color signal — the red ring underneath is noise. */
.seat-wrapper:has(.seat-action:not(.fold)) .table-seat.villain {
    animation: none;
    border-color: transparent;
    box-shadow: none;
}

/* Suppress hero seat border when hero-action-above provides its own colored border */
.seat-wrapper:has(.hero-action-above) .table-seat.hero {
    border-color: transparent;
}

/* =====================================================================
   ACTION TEXT — two-line layout (verb stacked above amount)
   ===================================================================== */

.action-verb {
    font-size: 0.48rem;
    font-weight: 700;
    opacity: 0.85;
    line-height: 1;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    display: block;
}

.action-amount {
    font-size: 0.74rem;
    font-weight: 800;
    line-height: 1.1;
    display: block;
}

/* Folded villain seat — blends into table background */
.table-seat.folded:not(.hero) {
    background: #111118;
    border-color: #1c1c28;
    box-shadow: none;
}

.table-seat.folded:not(.hero) .seat-position,
.table-seat.folded:not(.hero) .seat-label {
    visibility: hidden;
}

/* =====================================================================
   9-SEAT POSITION LAYOUT (default)
   Arc-length equalized on the table border ellipse
   rx=46.8% ry=41.9% measured from the brown border ring midpoint
   ===================================================================== */

.seat-wrapper-btn  { top: 91.9%; left: 50%;   transform: translate(-50%, -50%); }
.seat-wrapper-sb   { top: 85.5%; left: 25.1%; transform: translate(-50%, -50%); }
.seat-wrapper-bb   { top: 60.8%; left: 4.8%;  transform: translate(-50%, -50%); }
.seat-wrapper-utg  { top: 23.6%; left: 13.6%; transform: translate(-50%, -50%); }
.seat-wrapper-utg1 { top: 9.6%;  left: 37.5%; transform: translate(-50%, -50%); }
.seat-wrapper-mp   { top: 9.6%;  left: 62.6%; transform: translate(-50%, -50%); }
.seat-wrapper-lj   { top: 23.6%; left: 86.4%; transform: translate(-50%, -50%); }
.seat-wrapper-hj   { top: 60.8%; left: 95.2%; transform: translate(-50%, -50%); }
.seat-wrapper-co   { top: 85.5%; left: 74.9%; transform: translate(-50%, -50%); }

/* Dealer button now lives inside its seat-wrapper as a child element so it
   travels with the seat. Per-slot positioning sits D at a sensible spot on
   the felt that doesn't overlap the chip pile, hero cards, or villain backs.
   !important wins over the legacy data-seats and media-query rules elsewhere
   in this file (which still target .btn-dealer-* with higher specificity)
   without requiring a sweeping delete of those rules. */
.seat-wrapper > .dealer-button {
    top: auto !important;
    left: auto !important;
    right: auto !important;
    bottom: auto !important;
    transform: none !important;
}

/* Each slot places D on the seat's INWARD side (toward the felt centre, so
   it always lands on the felt) and offset clear of the chip pile direction.
   Offset is ~15px (8-10px farther than the seat edge) so D never sits on the
   table border. Scales up slightly on larger viewports via the desktop media
   block lower in the file. */

/* Top seats (chip pile sits below the seat) — D pushed to the lower-inward
   corner so the chip stack clears it laterally and vertically. */
.seat-wrapper-utg1 > .dealer-button { bottom: -5px !important; right: -15px !important; top: auto !important; left: auto !important; transform: none !important; }
.seat-wrapper-mp   > .dealer-button { bottom: -5px !important; left: -15px !important; top: auto !important; right: auto !important; transform: none !important; }

/* Upper-side seats (chip diagonal inward toward centre) — D directly below
   the seat to clear the diagonal chip path while staying on the felt. */
.seat-wrapper-utg  > .dealer-button { bottom: -15px !important; left: 50% !important; transform: translateX(-50%) !important; }
.seat-wrapper-lj   > .dealer-button { bottom: -15px !important; left: 50% !important; transform: translateX(-50%) !important; }

/* Mid-side seats (BB left:4.8%, HJ left:95.2%) — D directly below the seat.
   Chips for these seats travel nearly horizontally toward the centre (up-left for HJ,
   up-right for BB), so any inward or corner position falls inside the chip path.
   Bottom-centre sits clear below the chip trajectory and below villain card stubs. */
.seat-wrapper-bb   > .dealer-button { bottom: -15px !important; left: 50% !important; transform: translateX(-50%) !important; }
.seat-wrapper-hj   > .dealer-button { bottom: -15px !important; left: 50% !important; transform: translateX(-50%) !important; }

/* Bottom-corner seats (chip up-and-inward) — D to the inward lateral side. */
.seat-wrapper-sb   > .dealer-button { top: 50% !important; right: -15px !important; transform: translateY(-50%) !important; }
.seat-wrapper-co   > .dealer-button { top: 50% !important; left: -15px !important; transform: translateY(-50%) !important; }

/* Hero (BTN slot) — D tucked behind the hero cards on the upper-right.
   Cards (z-index: 4) sit above the pill and extend slightly past its right edge.
   D goes BEHIND the cards (z-index: 2) and is pushed far enough right that the
   button peeks out past the right card. This keeps D on the felt without ever
   sitting on top of the hero hand. */
.seat-wrapper-btn  > .dealer-button {
    top: 0 !important;
    right: -28px !important;
    bottom: auto !important;
    left: auto !important;
    transform: translateY(-50%) !important;
    z-index: 2 !important;
}

/* Mobile: BTN sits at the very bottom of the felt where the table curves inward,
   so the desktop -28px offset pushes D off the felt edge. Pull D inward and
   slightly higher up onto the wider felt. Cards on mobile are smaller and barely
   extend past the pill, so D still peeks out cleanly past the right card. */
@media (max-width: 768px) {
    .layout-full-table .seat-wrapper-btn > .dealer-button {
        top: -8px !important;
        right: -16px !important;
    }
}

/* Top-centre seat dealer button — the single seat sitting at top:~8%, left:50%
   in layouts that have one (4-max BB, 6-max UTG, 8-max MP). Its bet chips
   travel straight DOWN toward the pot (the very-top branch in
   applyChipPileDeltas aims chipX=0, chipY=+offset), so the generic below-seat
   D position (bottom-centre) lands right on top of the chip pile. Nudge D to
   the seat's front-right corner instead — down toward the felt (table side)
   and offset right, clear of the straight-down bet lane. This mirrors how the
   hero button sits toward the felt (up-and-right) at the bottom, so the button
   always reads as resting in front of the player rather than out to the side.
   Specificity (0,4,0 + !important) beats the shared
   `.seat-wrapper-<slot> > .dealer-button` child rules (0,2,0). */
.poker-table-container[data-seats="4"] .seat-wrapper-bb  > .dealer-button,
.poker-table-container[data-seats="6"] .seat-wrapper-utg > .dealer-button,
.poker-table-container[data-seats="8"] .seat-wrapper-mp  > .dealer-button {
    top: auto !important;
    bottom: -4px !important;
    left: auto !important;
    right: -14px !important;
    transform: none !important;
}

/* =====================================================================
   6-SEAT LAYOUT
   ===================================================================== */

/* 6-seat ellipse: rx=46.8% ry=41.9% center=(50%,50%). SB/CO pulled toward hero (~222°/318°), BB/MP pulled toward UTG (~138°/42°) */
.poker-table-container[data-seats="6"] .seat-wrapper-btn { top: 91.9%; left: 50%;   }
.poker-table-container[data-seats="6"] .seat-wrapper-sb  { top: 78.0%; left: 15.2%; }
.poker-table-container[data-seats="6"] .seat-wrapper-bb  { top: 22.0%; left: 15.2%; }
.poker-table-container[data-seats="6"] .seat-wrapper-utg { top: 8.1%;  left: 50%;   }
.poker-table-container[data-seats="6"] .seat-wrapper-mp  { top: 22.0%; left: 84.8%; }
.poker-table-container[data-seats="6"] .seat-wrapper-co  { top: 78.0%; left: 84.8%; }

.poker-table-container[data-seats="6"] .btn-dealer-btn { top: 83%;  left: 57%;   }
.poker-table-container[data-seats="6"] .btn-dealer-sb  { top: 72%;  left: 23%;   }
.poker-table-container[data-seats="6"] .btn-dealer-bb  { top: 28%;  left: 23%;   }
.poker-table-container[data-seats="6"] .btn-dealer-utg { top: 17%;  left: 43%;   }
.poker-table-container[data-seats="6"] .btn-dealer-mp  { top: 28%;  left: 77%;   }
.poker-table-container[data-seats="6"] .btn-dealer-co  { top: 72%;  left: 77%;   }

/* =====================================================================
   2-SEAT LAYOUT
   ===================================================================== */

.poker-table-container[data-seats="2"] .seat-wrapper-btn { top: 90%; left: 50%; }
.poker-table-container[data-seats="2"] .seat-wrapper-bb  { top: 10%; left: 50%; }
.poker-table-container[data-seats="2"] .btn-dealer-btn   { top: 82%; left: 57%; }
.poker-table-container[data-seats="2"] .btn-dealer-bb    { top: 18%; left: 43%; }

/* =====================================================================
   3-SEAT LAYOUT
   ===================================================================== */

/* 3-seat ellipse: rx=46.8% ry=41.9% center=(50%,50%), 120° intervals from hero at bottom */
.poker-table-container[data-seats="3"] .seat-wrapper-btn { top: 91.9%; left: 50.0%; }
.poker-table-container[data-seats="3"] .seat-wrapper-sb  { top: 29.1%; left: 9.5%;  }
.poker-table-container[data-seats="3"] .seat-wrapper-bb  { top: 29.1%; left: 90.5%; }

.poker-table-container[data-seats="3"] .btn-dealer-btn { top: 83.0%; left: 57.0%; }
.poker-table-container[data-seats="3"] .btn-dealer-sb  { top: 33.7%; left: 18.4%; }
.poker-table-container[data-seats="3"] .btn-dealer-bb  { top: 33.7%; left: 81.6%; }

/* =====================================================================
   4-SEAT LAYOUT
   ===================================================================== */

/* 4-seat ellipse: rx=46.8% ry=41.9% center=(50%,50%), 90° intervals from hero at bottom */
.poker-table-container[data-seats="4"] .seat-wrapper-btn { top: 91.9%; left: 50.0%; }
.poker-table-container[data-seats="4"] .seat-wrapper-sb  { top: 50.0%; left: 3.2%;  }
.poker-table-container[data-seats="4"] .seat-wrapper-bb  { top:  8.1%; left: 50.0%; }
.poker-table-container[data-seats="4"] .seat-wrapper-co  { top: 50.0%; left: 96.8%; }

.poker-table-container[data-seats="4"] .btn-dealer-btn { top: 83.0%; left: 57.0%; }
.poker-table-container[data-seats="4"] .btn-dealer-sb  { top: 50.0%; left: 13.5%; }
.poker-table-container[data-seats="4"] .btn-dealer-bb  { top: 17.3%; left: 43.0%; }
.poker-table-container[data-seats="4"] .btn-dealer-co  { top: 50.0%; left: 86.5%; }

/* =====================================================================
   5-SEAT LAYOUT
   ===================================================================== */

/* 5-seat ellipse: rx=46.8% ry=41.9% center=(50%,50%), 72° intervals from hero at bottom */
.poker-table-container[data-seats="5"] .seat-wrapper-btn { top: 91.9%; left: 50.0%; }
.poker-table-container[data-seats="5"] .seat-wrapper-sb  { top: 62.9%; left:  5.5%; }
.poker-table-container[data-seats="5"] .seat-wrapper-bb  { top: 16.1%; left: 22.5%; }
.poker-table-container[data-seats="5"] .seat-wrapper-utg { top: 16.1%; left: 77.5%; }
.poker-table-container[data-seats="5"] .seat-wrapper-co  { top: 62.9%; left: 94.5%; }

.poker-table-container[data-seats="5"] .btn-dealer-btn { top: 83.0%; left: 57.0%; }
.poker-table-container[data-seats="5"] .btn-dealer-sb  { top: 60.1%; left: 15.3%; }
.poker-table-container[data-seats="5"] .btn-dealer-bb  { top: 23.6%; left: 28.6%; }
.poker-table-container[data-seats="5"] .btn-dealer-utg { top: 23.6%; left: 71.4%; }
.poker-table-container[data-seats="5"] .btn-dealer-co  { top: 60.1%; left: 84.7%; }

/* =====================================================================
   7-SEAT LAYOUT
   ===================================================================== */

/* 7-seat ellipse: rx=46.8% ry=41.9% center=(50%,50%), ~51.4° intervals from hero at bottom */
.poker-table-container[data-seats="7"] .seat-wrapper-btn { top: 91.9%; left: 50.0%; }
.poker-table-container[data-seats="7"] .seat-wrapper-sb  { top: 76.1%; left: 13.4%; }
.poker-table-container[data-seats="7"] .seat-wrapper-bb  { top: 40.7%; left:  4.4%; }
.poker-table-container[data-seats="7"] .seat-wrapper-utg { top: 12.2%; left: 29.7%; }
.poker-table-container[data-seats="7"] .seat-wrapper-mp  { top: 12.2%; left: 70.3%; }
.poker-table-container[data-seats="7"] .seat-wrapper-hj  { top: 40.7%; left: 95.6%; }
.poker-table-container[data-seats="7"] .seat-wrapper-co  { top: 76.1%; left: 86.6%; }

.poker-table-container[data-seats="7"] .btn-dealer-btn { top: 83.0%; left: 57.0%; }
.poker-table-container[data-seats="7"] .btn-dealer-sb  { top: 70.4%; left: 21.5%; }
.poker-table-container[data-seats="7"] .btn-dealer-bb  { top: 42.7%; left: 14.4%; }
.poker-table-container[data-seats="7"] .btn-dealer-utg { top: 20.5%; left: 34.2%; }
.poker-table-container[data-seats="7"] .btn-dealer-mp  { top: 20.5%; left: 65.8%; }
.poker-table-container[data-seats="7"] .btn-dealer-hj  { top: 42.7%; left: 85.6%; }
.poker-table-container[data-seats="7"] .btn-dealer-co  { top: 70.4%; left: 78.5%; }

/* =====================================================================
   8-SEAT LAYOUT
   ===================================================================== */

/* 8-seat ellipse: rx=45.2% ry=41.9% center=(50%,50%), 45° intervals from
   hero at bottom. Without these overrides an 8-max table borrows the 9-max
   coordinates for its 8 used slots, which drops the second top seat and
   leaves the top-centre seat off to one side (unbalanced). rx is held at
   45.2% (not the 46.8% of the other sizes) so the mid-side BB/HJ seats land
   at 4.8%/95.2% — the same horizontal envelope the 9-max layout already uses
   and renders safely — rather than the more extreme 3.2%/96.8% that clips at
   the container edge on narrow mobile widths. */
.poker-table-container[data-seats="8"] .seat-wrapper-btn { top: 91.9%; left: 50.0%; }
.poker-table-container[data-seats="8"] .seat-wrapper-sb  { top: 79.6%; left: 18.0%; }
.poker-table-container[data-seats="8"] .seat-wrapper-bb  { top: 50.0%; left:  4.8%; }
.poker-table-container[data-seats="8"] .seat-wrapper-utg { top: 20.4%; left: 18.0%; }
.poker-table-container[data-seats="8"] .seat-wrapper-mp  { top:  8.1%; left: 50.0%; }
.poker-table-container[data-seats="8"] .seat-wrapper-lj  { top: 20.4%; left: 82.0%; }
.poker-table-container[data-seats="8"] .seat-wrapper-hj  { top: 50.0%; left: 95.2%; }
.poker-table-container[data-seats="8"] .seat-wrapper-co  { top: 79.6%; left: 82.0%; }

/* Dealer button for every 8-max slot is handled by the shared
   `.seat-wrapper-<slot> > .dealer-button` rules; the top-centre MP slot gets a
   dedicated override in the top-centre-seat block near the BTN dealer rules
   above. No legacy `.btn-dealer-*` rules are needed (they are overridden by
   those !important child rules everywhere). */

/* =====================================================================
   FULL-TABLE LAYOUT (layout-full-table)
   Used by quiz and video recap for larger table with hero cards on seat
   ===================================================================== */

.layout-full-table .table-seat {
    width: clamp(48px, 10vw, 76px);
    height: clamp(48px, 10vw, 76px);
    font-size: clamp(0.55rem, 1.5vw, 0.75rem);
    position: relative;
    z-index: 10; /* above villain-cards (z-index: 1) and hero-cards-on-seat (z-index: 4) */
}

/* Scale fill circle and text to match seat clamp size */
.layout-full-table .seat-action {
    width: clamp(48px, 10vw, 76px);
    height: clamp(48px, 10vw, 76px);
}

.layout-full-table .action-verb {
    font-size: clamp(0.5rem, 1.5vw, 0.75rem);
}

.layout-full-table .action-amount {
    font-size: clamp(0.6rem, 1.6vw, 0.85rem);
}

/* On mobile the vw preferred value is too small — the circle is 48px but text shrinks
   to the clamp floor. Use larger rem values so action text is readable at small sizes. */
@media (max-width: 768px) {
    .layout-full-table .action-verb   { font-size: 0.65rem; }
    .layout-full-table .action-amount { font-size: 0.8rem; }
}

/* Hero fill uses the same clamp font sizes as villain fills.
   "Raises" is the longest verb — the clamp is sized so it fits at minimum seat width. */

.layout-full-table .table-seat.hero {
    width: clamp(96px, 26vw, 125px);
    height: clamp(38px, 10vw, 50px);
    border-radius: 12px;
    background: var(--bg-tooltip, #161636);
    border-width: 2px;
    border-style: solid;
    /* border-color inherits from .table-seat.hero base rule */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-size: 0.65rem;
    font-weight: 600;
    z-index: 15;
    transform: translateZ(0); /* own compositing layer — renders above filter-promoted hero cards */
}

.layout-full-table .table-seat.hero .hero-action-inside {
    font-size: 0.7rem;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 6px;
    margin-bottom: 2px;
    display: flex;
    align-items: center;
    gap: 3px;
    background: rgba(var(--action-call-rgb, 0, 230, 118), 0.9);
    color: white;
}

.layout-full-table .seat-label {
    font-size: clamp(0.42rem, 1.2vw, 0.6rem);
    letter-spacing: -0.2px;
    color: var(--text-muted, #8080a8);
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: clamp(38px, 8vw, 56px);
    white-space: nowrap;
}

.layout-full-table .table-seat.hero .seat-label {
    font-size: 0.65rem;
    max-width: none;
}

/* Hero action: fills the hero rectangle on desktop, circle on mobile.
   Width/height match .table-seat.hero (125px × 50px) explicitly — calc(100%) would
   reference the seat-wrapper height which includes the hero cards above. */
.layout-full-table .hero-action-above {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 125px;
    height: 50px;
    border-radius: 10px;
    border: 2px solid #9090b8;
    background: #1e1e30;
    color: white;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    padding: 4px;
    z-index: 16;
}

.layout-full-table .hero-action-above.check,
.layout-full-table .hero-action-above.action-check {
    --action-color: #9090b8;
    background: #1e1e30;
    border-color: #9090b8;
    color: rgba(220,220,240,0.75);
    box-shadow: none;
}

.layout-full-table .hero-action-above.call,
.layout-full-table .hero-action-above.action-call {
    --action-color: #00e676;
    background: #0a2818;
    border-color: #00e676;
    box-shadow: 0 0 8px rgba(0,230,118,0.4);
}

.layout-full-table .hero-action-above.bet,
.layout-full-table .hero-action-above.action-bet {
    --action-color: #ffa000;
    background: #2e1800;
    border-color: #ffa000;
    box-shadow: 0 0 8px rgba(255,160,0,0.4);
}

.layout-full-table .hero-action-above.raise,
.layout-full-table .hero-action-above.action-raise {
    --action-color: #ffa000;
    background: #2e1800;
    border-color: #ffa000;
    box-shadow: 0 0 8px rgba(255,160,0,0.4);
}

.layout-full-table .hero-action-above.allin,
.layout-full-table .hero-action-above.action-allin {
    --action-color: #ff1744;
    background: #2e0a10;
    border-color: #ff1744;
    box-shadow: 0 0 12px rgba(255,23,68,0.7), 0 0 24px rgba(255,23,68,0.3);
    animation: pulse-allin 1.3s infinite;
}

.layout-full-table .hero-action-above.fold,
.layout-full-table .hero-action-above.action-fold {
    --action-color: #646464;
    background: #111118;
    border-color: #646464;
    color: rgba(150,150,165,0.75);
    box-shadow: none;
}

/* Showdown result — hero rectangle WON */
.layout-full-table .hero-action-above.action-won {
    --action-color: #00e676;
    background: #061c10;
    border-color: #00e676;
    box-shadow: 0 0 10px rgba(0,230,118,0.5);
}

.layout-full-table .hero-action-above.action-won .action-verb {
    font-size: 1rem;
    font-weight: 800;
    opacity: 1;
    color: #00e676;
    letter-spacing: 1px;
}

/* Showdown result — hero rectangle LOST */
.layout-full-table .hero-action-above.action-lost {
    --action-color: #404058;
    background: #111118;
    border-color: #404058;
    box-shadow: none;
}

.layout-full-table .hero-action-above.action-lost .action-verb {
    font-size: 1rem;
    font-weight: 800;
    opacity: 1;
    color: #9090b8;
    letter-spacing: 1px;
}

/* Ripple ring on current hero action — matches the rectangle shape on desktop,
   inherits --action-color set on each .hero-action-above.action-* rule above. */
.layout-full-table .hero-action-above.action-current::before {
    content: '';
    position: absolute;
    inset: -2px;
    border-radius: 12px;
    border: 2px solid var(--action-color, #ffa000);
    pointer-events: none;
    animation: action-enter-ripple 0.9s ease-out forwards;
}

@media (max-width: 768px) {
    .layout-full-table .hero-action-above.action-current::before {
        border-radius: 50%;
    }
}

/*
   BACKUP — previous hero card layout (flat, above seat):
   .layout-full-table .seat-wrapper-btn .hero-cards-on-seat {
       position: absolute;
       top: auto;
       bottom: calc(100% - 5px);
       left: 50%;
       transform: translateX(-50%);
       display: flex;
       align-items: flex-start;
       height: 66px;
       gap: 6px;
       z-index: 4;
   }
   .layout-full-table .hero-cards-on-seat .playing-card {
       --card-width: 51px;
       --card-height: 66px;
       --card-font: 20px;
   }
*/

/* Hero cards — centered group anchored to seat center (approach C).
   --card-width drives all sizing; left offsets are proportional fractions so the
   pair stays centered at every card size without mobile-specific overrides. */
/* Variables on the wrapper so both cards and chip pile reference the same math.
   Multiplier 1.5 (not 1.294) accounts for the card tilt bounding-box overhang. */
.layout-full-table .seat-wrapper-btn {
    --hero-card-bottom: 44px;
    --hero-card-h: calc(51px * 1.5); /* ≈77px */
}

.layout-full-table .seat-wrapper-btn .hero-cards-on-seat {
    position: absolute;
    top: auto; /* cancels top: 65% bleed from ranges.css */
    bottom: var(--hero-card-bottom);
    left: 50%;
    transform: none;
    display: block;
    width: 0;
    height: 0;
    z-index: 4;
    --card-width: 51px;
}

.layout-full-table .hero-cards-on-seat .cards-group {
    position: absolute;
    left: 0;
    bottom: 0;
    width: calc(var(--card-width) * 1.667);
    height: calc(var(--card-width) * 1.294);
    transform: translateX(-50%);
}

.layout-full-table .hero-cards-on-seat .cards-group .playing-card {
    --card-height: calc(var(--card-width) * 1.294);
    --card-font: calc(var(--card-width) * 0.39);
    position: absolute;
    bottom: 0;
    transform-origin: bottom center;
}

.layout-full-table .hero-cards-on-seat .cards-group .playing-card:nth-child(1) {
    left: 0;
    transform: rotate(-8deg);
    z-index: 1;
}

.layout-full-table .hero-cards-on-seat .cards-group .playing-card:nth-child(2) {
    left: calc(var(--card-width) * 0.667);
    transform: rotate(5deg);
    z-index: 2;
    filter: drop-shadow(-1px 1px 2px rgba(0, 0, 0, 0.4)) drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.4));
}


/* Hero cards go muted when hero folds -- add .folded to .hero-cards-on-seat.
   Use grayscale + brightness to dim the cards while keeping them fully opaque --
   transparency caused overlap artifacts between the two cards.
   The two card-specific rules above set their own filter (drop-shadow) on
   :nth-child(2) and would otherwise win on specificity, so override both
   nth-child variants explicitly here. */
.layout-full-table .hero-cards-on-seat.folded .cards-group .playing-card:nth-child(1),
.layout-full-table .hero-cards-on-seat.folded .cards-group .playing-card:nth-child(2) {
    filter: grayscale(1) brightness(0.5);
    opacity: 1;
}

.layout-full-table .community-cards-center {
    position: absolute;
    top: 46%;
    left: 50%;
    transform: translate(-50%, -50%) translateY(clamp(-15px, calc(12px - 2.5vw), 8px));
    display: flex;
    gap: 4px;
    z-index: 5;
}

.layout-full-table .community-cards-center .playing-card {
    --card-width: clamp(24px, min(51px, calc(100vw * 0.07)), 51px);
    --card-height: calc(var(--card-width) * 1.294);
    --card-font: calc(var(--card-width) * 0.392);
}

/* Preflop: no community cards — raise pot above hero's cards */
.layout-full-table .table-pot {
    top: 37%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 0.85rem;
}

/* Flop+ (community cards present): nudge pot down so it doesn't crowd the
   board cards. Single source of truth — used to live under .replay-v2. */
.layout-full-table .poker-table:has(.community-cards-center) .table-pot {
    top: 30%;
}

/* Flop+: pot and community cards are wrapped together in .table-center-stack
   so they're guaranteed attached. Layout shifts together at all viewport widths. */
.layout-full-table .poker-table .table-center-stack {
    position: absolute;
    top: 46%;
    left: 50%;
    transform: translate(-50%, -50%) translateY(clamp(-15px, calc(12px - 2.5vw), 8px));
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    z-index: 5;
}

/* On the 3:2 (mobile) breakpoint, lift the pot/community cards stack higher
   so it sits well above the hero cards and uses the extra vertical room of
   the taller table. */
@media (max-width: 768px) {
    .layout-full-table .poker-table .table-center-stack {
        top: 40%;
    }
}

/* Inside the stack, pot and community cards use static positioning so the
   flex column controls layout. Overrides the absolute positioning above.
   Tripled selectors boost specificity (0,6,0) to beat .replay-v2 rules in
   sessions-v2.css that hit (0,5,0) via :has(.community-cards-center) and
   would otherwise win on cascade order, leaving the pot transform-shifted
   off-centre at the 1:1 mobile breakpoint. */
.layout-full-table .poker-table .table-center-stack > .table-pot.table-pot.table-pot,
.layout-full-table .poker-table .table-center-stack > .community-cards-center.community-cards-center.community-cards-center {
    position: static;
    top: auto;
    left: auto;
    transform: none;
}

/* 9-seat positions for full-table layout */
.layout-full-table .seat-wrapper-btn  { top: 91.9%; left: 50%;   transform: translate(-50%, -50%); }
.layout-full-table .seat-wrapper-sb   { top: 85.5%; left: 25.1%; transform: translate(-50%, -50%); }
.layout-full-table .seat-wrapper-bb   { top: 60.8%; left: 4.8%;  transform: translate(-50%, -50%); }
.layout-full-table .seat-wrapper-utg  { top: 23.6%; left: 13.6%; transform: translate(-50%, -50%); }
.layout-full-table .seat-wrapper-utg1 { top: 9.6%;  left: 37.5%; transform: translate(-50%, -50%); }
.layout-full-table .seat-wrapper-mp   { top: 9.6%;  left: 62.6%; transform: translate(-50%, -50%); }
.layout-full-table .seat-wrapper-lj   { top: 23.6%; left: 86.4%; transform: translate(-50%, -50%); }
.layout-full-table .seat-wrapper-hj   { top: 60.8%; left: 95.2%; transform: translate(-50%, -50%); }
.layout-full-table .seat-wrapper-co   { top: 85.5%; left: 74.9%; transform: translate(-50%, -50%); }

/* =====================================================================
   VILLAIN CARD BACKS
   Two face-down cards peeking from behind active villain seats.
   The anchor point (bottom: 70%) sits inside the seat circle so the
   seat's opaque background occludes the lower portion of the cards.
   Only the rotated tops are visible above the rim.

   Toggle off: add class "no-villain-cards" to the .layout-full-table element.
   ===================================================================== */

.layout-full-table .villain-cards {
    position: absolute;
    left: 50%;
    width: 0;
    height: 0;
    bottom: 70%;
    z-index: 1;
    --card-width: 32px;
}

.layout-full-table .villain-cards .cards-group {
    position: absolute;
    left: 0;
    bottom: 0;
    width: calc(var(--card-width) * 1.667);
    height: calc(var(--card-width) * 1.294);
    transform: translateX(-50%);
}

.layout-full-table .villain-cards .cards-group .card-back {
    position: absolute;
    bottom: 0;
    transform-origin: bottom center;
    width: var(--card-width);
    height: calc(var(--card-width) * 1.294);
    min-width: unset;
    border-radius: 3px;
    overflow: hidden;
}

.layout-full-table .villain-cards .cards-group .card-back:nth-child(1) {
    left: 0;
    transform: rotate(-8deg);
}

.layout-full-table .villain-cards .cards-group .card-back:nth-child(2) {
    left: calc(var(--card-width) * 0.667);
    transform: rotate(5deg);
    box-shadow: -2px 5px 14px rgba(0, 0, 0, 0.6);
}

/* Toggle: add "no-villain-cards" to the .layout-full-table element to hide */
.layout-full-table.no-villain-cards .villain-cards {
    display: none;
}

/*
   Blue-edge style: dark blue card back with a 1px light-blue border.
   Overrides background/border from practice.css .card-back.
*/
.card-back.card-back-blue-edge {
    background: #a8c4e0;
    border: none;
}

/* Dark interior inset 1px — leaves 1px of light-blue background visible as the edge */
.card-back.card-back-blue-edge::before {
    content: '';
    position: absolute;
    top: 1px; left: 1px; right: 1px; bottom: 1px;
    background: linear-gradient(135deg, #1a365d 0%, #2d4a6f 50%, #1a365d 100%);
    border-radius: 2px;
    border: none;
}

/* Diagonal crosshatch pattern layered over the dark interior */
.card-back.card-back-blue-edge::after {
    content: '';
    position: absolute;
    top: 1px; left: 1px; right: 1px; bottom: 1px;
    background-image:
        repeating-linear-gradient(45deg, rgba(255,255,255,0.05) 0px, rgba(255,255,255,0.05) 1px, transparent 1px, transparent 6px),
        repeating-linear-gradient(-45deg, rgba(255,255,255,0.05) 0px, rgba(255,255,255,0.05) 1px, transparent 1px, transparent 6px);
    pointer-events: none;
}

/* =====================================================================
   END VILLAIN CARD BACKS
   ===================================================================== */

/* Villain revealed cards at showdown — same centered-group pattern as hero.
   Single source of truth for all consumers (quiz, replay, hand library,
   video engine). Replay-v2 used to override `bottom` to +10px; that override
   has been unified here so every context shows the cards in the same place. */
.layout-full-table .villain-cards-revealed-on-seat {
    position: absolute;
    left: 50%;
    width: 0;
    height: 0;
    bottom: calc(75% + 10px);
    /* Above the seat's bet chip pile (.seat-bet-chips z-index: 12) so showdown
       cards always read on top of the chips that committed them. */
    z-index: 14;
    --card-width: 51px;
}

.layout-full-table .villain-cards-revealed-on-seat .cards-group {
    position: absolute;
    left: 0;
    bottom: 0;
    width: calc(var(--card-width) * 1.667);
    height: calc(var(--card-width) * 1.294);
    transform: translateX(-50%);
}

.layout-full-table .villain-cards-revealed-on-seat .cards-group .playing-card {
    --card-height: calc(var(--card-width) * 1.294);
    --card-font: calc(var(--card-width) * 0.39);
    position: absolute;
    bottom: 0;
    transform-origin: bottom center;
}

.layout-full-table .villain-cards-revealed-on-seat .cards-group .playing-card:nth-child(1) {
    left: 0;
    transform: rotate(-8deg);
    z-index: 1;
}

.layout-full-table .villain-cards-revealed-on-seat .cards-group .playing-card:nth-child(2) {
    left: calc(var(--card-width) * 0.667);
    transform: rotate(5deg);
    z-index: 2;
    filter: drop-shadow(-1px 1px 2px rgba(0, 0, 0, 0.4)) drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.4));
}

/* Fluid sizing -- fills the parent container up to 750px.
   Each context (sessions-table-outer, quiz-left-column) provides its own cap via max-width.
   container-type: size enables cqw/cqh inside descendants — used by .seat-bet-chips
   to translate raw % deltas into pixel offsets that respect the actual aspect ratio. */
.layout-full-table .poker-table-container {
    width: 100%;
    max-width: 750px;
    min-width: 280px;
    margin: 0 auto;
    container-type: size;
}

/* Dealer button: sit beside the BTN seat (not above it, where hero cards peek).
   Desktop hero is a 125x50 box. Match the 1200px-specific rule so position is
   consistent regardless of whether the Q&A column is stacked or side-by-side. */
@media (min-width: 769px) {
    .layout-full-table .btn-dealer-btn { top: 80%; left: 60%; }
}

/* Mobile: ≤768px */
@media (max-width: 768px) {
    .layout-full-table .poker-table-container {
        width: 100%;
        margin: 0 auto;
        aspect-ratio: 3 / 2;
    }

    /* Mobile hero: shared across quiz, replay, hand library and video engine.
       Cards stay lifted above the seat pill so they're the visual focal point,
       and the card-width clamp matches the community-card scale so the hero
       hand reads at the same size as the board on every breakpoint. */
    .layout-full-table .seat-wrapper-btn {
        --hero-card-bottom: clamp(38px, 8.5vw, 68px);
        --hero-card-h: calc(clamp(30px, 7vw, 51px) * 1.5);
    }
    .layout-full-table .seat-wrapper-btn .hero-cards-on-seat {
        display: block;
        left: 50%;
        --card-width: clamp(30px, 7vw, 51px);
    }

    /* Villain backs: smaller than hero cards */
    .layout-full-table .villain-cards {
        --card-width: clamp(20px, 4.5vw, 32px);
    }

    /* Villain revealed: match hero card size */
    .layout-full-table .villain-cards-revealed-on-seat {
        --card-width: clamp(30px, 7vw, 40px);
    }
}


@media (max-width: 768px) {
    /* Hero seat keeps the wider pill geometry on mobile (set in the base
       .layout-full-table .table-seat.hero rule above). Hero-action overlay
       (action-call / action-raise pill that floats above the seat during
       hero turns) matches the seat dimensions exactly so the action chip
       fills the seat outline cleanly. */
    .layout-full-table .hero-action-above {
        width: clamp(96px, 26vw, 125px);
        height: clamp(38px, 10vw, 50px);
        border-radius: 12px;
    }
    /* Pulse ring around the active hero pill keeps a rectangular shape on
       mobile to match the pill itself (default ::before is 50% to fit the
       circle pattern this file used to enforce). */
    .layout-full-table .hero-action-above.action-current::before {
        border-radius: 12px;
    }
    /* Villain revealed cards: smaller on mobile to match the smaller hero hand. */
    .layout-full-table .villain-cards-revealed-on-seat {
        --card-width: clamp(30px, 7vw, 40px);
    }

    /* Dealer button beside the BTN seat on mobile, matching desktop approach */
    .layout-full-table .btn-dealer-btn {
        top: 77%;
        left: 63%;
    }
}

@media (max-width: 1199px) {
    .btn-dealer-btn {
        top: 77%;
        left: 56%;
    }
}

@media (min-width: 769px) {
    .layout-full-table .table-pot { font-size: 0.85rem; }
}

/* Tablet/mid: tighten pot padding */
@media (max-width: 768px) and (min-width: 481px) {
    .table-pot {
        padding: 4px 10px;
    }
}

/* Small mobile: reduce pot size; seat fills and text use clamp so no override needed */
@media (max-width: 480px) {
    .table-pot {
        padding: 3px 8px;
        font-size: 0.72rem;
    }
    /* With community cards: pot was crowding the cards — push it higher */
    .layout-full-table .poker-table:has(.community-cards-center) .table-pot {
        top: 23%;
        font-size: 0.68rem;
        transform: translate(-50%, -50%);
    }
    .layout-full-table .community-cards-center .playing-card {
        --card-width: clamp(22px, 8vw, 38px);
    }
    /* Pull dealer button further into the table so it doesn't overlap the BTN seat */
    .btn-dealer-btn {
        top: 70%;
    }
}

@media (max-width: 600px) {
    .layout-full-table .poker-table-container .btn-dealer-btn {
        top: 81%;
        left: 66%;
    }
}

@media (min-width: 1200px) {
    .quiz-hand-card.layout-full-table .btn-dealer-btn { top: 80%; left: 62%; }
}

/* On desktop the leftmost seats (BB at left:4.8%, UTG at left:13.6%) extend slightly
   past the container edge and crowd the quiz card's padding boundary. Shrink the
   container by 40px and let margin:auto re-centre it so every seat has ~20px of
   clearance from the column edge without breaking the percentage-based positions. */
@media (min-width: 769px) {
    .quiz-hand-card.layout-full-table .poker-table-container {
        width: calc(100% - 40px);
    }
}

/* Session table outer wrapper -- centres the table in all session contexts */
.sessions-table-outer {
    display: flex;
    justify-content: center;
    width: 100%;
}

/* Cap sessions table at the same effective width as the quiz left column (660px)
   so seat-to-ring proportions look identical in both contexts. */
@media (min-width: 769px) {
    .sessions-table-outer .poker-table-container {
        max-width: 660px;
    }
}

/* Hide community cards in non-full-table quiz layout (they live in the mobile card row instead) */
.quiz-hand-card:not(.layout-full-table) .community-cards-center {
    display: none;
}

/* =====================================================================
   SHARED MOBILE CARD GROUPS
   ===================================================================== */

.hand-cards-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    text-align: center;
    padding: 10px 14px;
    border-radius: 8px;
}

.hand-cards-group--hero {
    background: rgba(var(--action-call-rgb, 0, 230, 118), 0.1);
    border: 1px solid rgba(var(--action-call-rgb, 0, 230, 118), 0.35);
    display: none;
}

.hand-cards-group--board {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.12);
}

.hand-cards-group__label {
    font-size: 0.55rem;
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-muted, #8080a8);
    margin-bottom: 2px;
}

.hand-cards-group--hero .hand-cards-group__label {
    color: var(--action-call, #00e676);
}

.hand-cards-group__cards {
    display: flex;
    gap: 4px;
    justify-content: center;
}

/* =====================================================================
   EVENT-DRIVEN TRANSITION ANIMATIONS

   Trigger classes added by applyEventAnimations() in seat-state-render.js
   after each render, only on the elements affected by the event that just
   fired. CSS-side keyframes are pure additions — base styles are unchanged.

   Class map:
     .seat-action.show, .hero-action-above.show   action chip reveal (Option A)
     .community-cards-center .playing-card.show   board card flip (Option B)
     .table-pot.bump                              pot bounce pulse (Option A)
     .seat-wrapper.folding                        snappy fold tuck (Variant A)
   ===================================================================== */

/* ---- Action chip reveal: glow fade + text pop ----

   The chip itself fades opacity only — both .seat-action and .hero-action-above
   are absolutely positioned with `transform: translate(-50%, -50%)` for
   centering, and any scale on the chip would clobber that translate, causing a
   visible jump. The "scale-in" feel comes from the inner text-pop instead. */

@keyframes action-chip-fade-in {
    0%   { opacity: 0; }
    100% { opacity: 1; }
}
@keyframes action-chip-text-pop {
    0%   { opacity: 0; transform: scale(0.55); }
    65%  { opacity: 1; transform: scale(1.08); }
    80%  {              transform: scale(0.97); }
    100% { opacity: 1; transform: scale(1); }
}

.seat-action.show,
.hero-action-above.show {
    animation: action-chip-fade-in 0.28s ease-out both;
}

.seat-action.show .action-verb,
.seat-action.show .action-amount,
.hero-action-above.show .action-verb,
.hero-action-above.show .action-amount {
    display: inline-block;
    animation: action-chip-text-pop 0.36s cubic-bezier(0.34, 1.5, 0.64, 1) 0.06s both;
}

/* ---- Community card reveal: 3D flip ---- */

.layout-full-table .community-cards-center { perspective: 600px; }

@keyframes community-card-flip {
    0%   { transform: rotateY(90deg) scale(0.92); opacity: 0; }
    100% { transform: rotateY(0deg)  scale(1);    opacity: 1; }
}

.community-cards-center .playing-card.show {
    transform-origin: left center;
    animation: community-card-flip 0.36s cubic-bezier(0.22, 1, 0.36, 1) both;
    animation-delay: var(--deal-delay, 0s);
    backface-visibility: hidden;
}

/* ---- Board card deal: slide-in + 3D back/face flip (flop, turn, river) ---- */

@keyframes deal-card-arrive {
    from { opacity: 1; transform: translateY(-28px); }
    to   { opacity: 1; transform: translateY(0);     }
}

@keyframes deal-back-rotate-out {
    from { transform: rotateY(0deg);   }
    to   { transform: rotateY(-90deg); }
}

@keyframes deal-face-rotate-in {
    from { opacity: 0; transform: rotateY(45deg); }
    to   { opacity: 1; transform: rotateY(0deg);  }
}

@keyframes flop-c2-fan {
    0%   { opacity: 0; transform: translateX(calc(-1 * var(--flop-dx2))); }
    1%   { opacity: 1; transform: translateX(calc(-1 * var(--flop-dx2))); }
    100% { opacity: 1; transform: translateX(0); }
}

@keyframes flop-c3-fan {
    0%   { opacity: 0; transform: translateX(calc(-1 * var(--flop-dx3))); }
    1%   { opacity: 1; transform: translateX(calc(-1 * var(--flop-dx3))); }
    100% { opacity: 1; transform: translateX(0); }
}

/* Wrapper carries the arrive slide; perspective provides 3D context for back/face children */
.community-cards-center .deal-flip-wrapper {
    display: inline-flex;
    position: relative;
    perspective: 180px;
    z-index: 3;
    animation: deal-card-arrive 0.32s cubic-bezier(0.22,1,0.36,1) 0s both;
}

/* Card back: absolute overlay that rotates to edge-on then is removed by JS */
.community-cards-center .deal-flip-back {
    position: absolute;
    inset: 0;
    border-radius: 6px;
    background-color: #1a4a8a;
    background-image: repeating-linear-gradient(
        45deg,
        rgba(255,255,255,0.05) 0, rgba(255,255,255,0.05) 2px,
        transparent 2px, transparent 8px
    );
    z-index: 1;
    animation: deal-back-rotate-out 0.22s ease-in 0.32s both;
}

/* Card face: hidden while back is rotating (opacity set via JS inline style) */
.community-cards-center .deal-flip-face {
    opacity: 0;
}

/* Added by JS after back has fully departed; triggers the reveal rotation */
.community-cards-center .deal-flip-face-active {
    animation: deal-face-rotate-in 0.22s ease-out 0s forwards;
}

/* Flop fan: cards 2 and 3 start at card 1's position and fan to their natural slots */
.community-cards-center.flop-deal .flop-c2 {
    animation: flop-c2-fan 0.38s cubic-bezier(0.22,1,0.36,1) 0.82s both;
}

.community-cards-center.flop-deal .flop-c3 {
    animation: flop-c3-fan 0.38s cubic-bezier(0.22,1,0.36,1) 0.82s both;
}

/* ---- Pot bounce pulse ---- */

@keyframes pot-bounce {
    0%   { transform: translate(-50%, -50%) scale(1); }
    30%  { transform: translate(-50%, -50%) scale(1.16); color: #ffe082; }
    55%  { transform: translate(-50%, -50%) scale(0.96); }
    75%  { transform: translate(-50%, -50%) scale(1.04); }
    100% { transform: translate(-50%, -50%) scale(1); }
}

/* When community cards are present the pot also has a translateY offset.
   Provide a parallel keyframe that preserves it. */
@keyframes pot-bounce-with-board {
    0%   { transform: translate(-50%, -50%) translateY(clamp(-15px, calc(12px - 2.5vw), 8px)) scale(1); }
    30%  { transform: translate(-50%, -50%) translateY(clamp(-15px, calc(12px - 2.5vw), 8px)) scale(1.16); color: #ffe082; }
    55%  { transform: translate(-50%, -50%) translateY(clamp(-15px, calc(12px - 2.5vw), 8px)) scale(0.96); }
    75%  { transform: translate(-50%, -50%) translateY(clamp(-15px, calc(12px - 2.5vw), 8px)) scale(1.04); }
    100% { transform: translate(-50%, -50%) translateY(clamp(-15px, calc(12px - 2.5vw), 8px)) scale(1); }
}

.layout-full-table .table-pot.bump {
    animation: pot-bounce 0.5s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.layout-full-table .poker-table:has(.community-cards-center) .table-pot.bump {
    animation: pot-bounce-with-board 0.5s cubic-bezier(0.34, 1.4, 0.64, 1);
}
/* Pot inside the center stack is statically positioned — bump animation uses
   plain scale without translate so it doesn't shift off the flex layout. */
.layout-full-table .poker-table .table-center-stack > .table-pot.bump {
    animation: pot-bounce-static 0.5s cubic-bezier(0.34, 1.4, 0.64, 1);
}

@keyframes pot-bounce-static {
    0%   { transform: scale(1); }
    30%  { transform: scale(1.16); color: #ffe082; }
    55%  { transform: scale(0.96); }
    75%  { transform: scale(1.04); }
    100% { transform: scale(1); }
}

/* ---- Fold: snappy tuck (Variant A) ----

   Cards fan out very slightly, then scale-to-zero in place behind the seat.
   Existing base rotations on .villain-cards / .hero-cards-on-seat are
   nth-child(1) -8deg, nth-child(2) +5deg — keyframes preserve those angles
   so the resting position is identical to the un-animated state. */

@keyframes fold-tuck-left {
    0%   { transform: rotate(-8deg)  scale(1);    opacity: 1; }
    25%  { transform: rotate(-11deg) scale(1.04); opacity: 1; }
    100% { transform: rotate(-8deg)  scale(0);    opacity: 0; }
}
@keyframes fold-tuck-right {
    0%   { transform: rotate(5deg)  scale(1);    opacity: 1; }
    25%  { transform: rotate(8deg)  scale(1.04); opacity: 1; }
    100% { transform: rotate(5deg)  scale(0);    opacity: 0; }
}
@keyframes fold-seat-dim {
    0%   { opacity: 1; }
    60%  { opacity: 1; }
    100% { opacity: 0.55; }
}

/* Villain cards (face-down backs) */
.layout-full-table .seat-wrapper.folding .villain-cards .cards-group .card-back:nth-child(1) {
    animation: fold-tuck-left 0.38s cubic-bezier(0.55, 0, 0.7, 1) forwards;
}
.layout-full-table .seat-wrapper.folding .villain-cards .cards-group .card-back:nth-child(2) {
    animation: fold-tuck-right 0.38s cubic-bezier(0.55, 0, 0.7, 1) forwards;
}

/* Hero cards (when the hero is the folder) */
.layout-full-table .seat-wrapper.folding .hero-cards-on-seat .cards-group .playing-card:nth-child(1) {
    animation: fold-tuck-left 0.38s cubic-bezier(0.55, 0, 0.7, 1) forwards;
}
.layout-full-table .seat-wrapper.folding .hero-cards-on-seat .cards-group .playing-card:nth-child(2) {
    animation: fold-tuck-right 0.38s cubic-bezier(0.55, 0, 0.7, 1) forwards;
}

/* Subtle seat dim during the tuck so the seat reads as "out of the hand".
   Runs slightly longer than the tuck so the dim lands on a still card. */
.layout-full-table .seat-wrapper.folding .table-seat {
    animation: fold-seat-dim 0.42s ease forwards;
}

/* ---- Un-fold: reverse tuck (backward navigation) ----

   Cards start at scale(0)/opacity(0) and ease smoothly back to their resting
   rotations. No keyframe bounce — clean ease-out only.
   Base rotations preserved: nth-child(1) = -8deg, nth-child(2) = +5deg. */

@keyframes unfold-tuck-left {
    0%   { transform: rotate(-8deg) scale(0); opacity: 0; }
    100% { transform: rotate(-8deg) scale(1); opacity: 1; }
}
@keyframes unfold-tuck-right {
    0%   { transform: rotate(5deg) scale(0); opacity: 0; }
    100% { transform: rotate(5deg) scale(1); opacity: 1; }
}

.layout-full-table .seat-wrapper.unfolding .villain-cards .cards-group .card-back:nth-child(1) {
    animation: unfold-tuck-left 0.35s cubic-bezier(0.2, 0, 0.3, 1) both;
}
.layout-full-table .seat-wrapper.unfolding .villain-cards .cards-group .card-back:nth-child(2) {
    animation: unfold-tuck-right 0.35s cubic-bezier(0.2, 0, 0.3, 1) both;
}
.layout-full-table .seat-wrapper.unfolding .hero-cards-on-seat .cards-group .playing-card:nth-child(1) {
    animation: unfold-tuck-left 0.35s cubic-bezier(0.2, 0, 0.3, 1) both;
}
.layout-full-table .seat-wrapper.unfolding .hero-cards-on-seat .cards-group .playing-card:nth-child(2) {
    animation: unfold-tuck-right 0.35s cubic-bezier(0.2, 0, 0.3, 1) both;
}

/* Villain card reveal — showdown flip.
   Cards start at back-card scale (~0.63 = 32/51 = back-width / face-width)
   and grow to full face size while flipping in 3D, landing at the same -8°
   / +5° tilt the static rule sets. The tilt MUST be preserved in every
   keyframe step; otherwise the animation's final transform overrides the
   static `rotate(...)` and the cards land flat. */
@keyframes villain-flip-in-left {
    0%   {
        transform: rotateY(-90deg) rotate(-8deg) scale(0.63);
        opacity: 0.4;
    }
    50%  { opacity: 1; }
    65%  {
        transform: rotateY(8deg) rotate(-8deg) scale(1.04);
    }
    82%  {
        transform: rotateY(-2deg) rotate(-8deg) scale(1);
    }
    100% {
        transform: rotateY(0deg) rotate(-8deg) scale(1);
        opacity: 1;
    }
}

@keyframes villain-flip-in-right {
    0%   {
        transform: rotateY(-90deg) rotate(5deg) scale(0.63);
        opacity: 0.4;
    }
    50%  { opacity: 1; }
    65%  {
        transform: rotateY(8deg) rotate(5deg) scale(1.04);
    }
    82%  {
        transform: rotateY(-2deg) rotate(5deg) scale(1);
    }
    100% {
        transform: rotateY(0deg) rotate(5deg) scale(1);
        opacity: 1;
    }
}

.villain-cards-revealed-on-seat {
    perspective: 600px;
}
.villain-cards-revealed-on-seat.flip-reveal .cards-group > *:nth-child(1) {
    animation: villain-flip-in-left 0.42s cubic-bezier(0.34, 1.3, 0.64, 1) both;
    transform-origin: bottom center;
}
.villain-cards-revealed-on-seat.flip-reveal .cards-group > *:nth-child(2) {
    animation: villain-flip-in-right 0.42s cubic-bezier(0.34, 1.3, 0.64, 1) 0.14s both;
    transform-origin: bottom center;
}

/* =====================================================================
   BET CHIP PILES (seat-state-render.js renderer only)

   General math: each seat-wrapper carries (--chip-dx, --chip-dy), the raw
   percentage delta (in container-% units) from the seat's centre to the
   pot's centre. JS computes these once per render by reading the actual
   rendered positions, so it works for any seat in any layout at any
   aspect ratio. The chip pile is then translated --chip-pull (a fraction)
   of the way toward the pot using container-query units — cqw/cqh
   automatically respect the container's true aspect ratio.
   ===================================================================== */

.seat-bet-chips {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%)
               translate(var(--chip-x-px, 0px), var(--chip-y-px, -56px));
    display: flex;
    flex-direction: column;
    align-items: center;
    pointer-events: none;
    z-index: 12; /* above .table-seat (z-index: 10) so chips render on top of any seat they overlap */
}

/* Lift a seat-wrapper above its neighbours when it carries a chip pile, so
   the pile renders on top of any neighbouring seat it lands on (relevant in
   the 1:1 mobile layout where chips travel further toward the centre).
   Z-index is intentionally above the dealer button (z-index 30) so a chip
   pile that lands near the dealer button always reads on top of it. */
.seat-wrapper:has(.seat-bet-chips) {
    z-index: 35;
}

/* Hero (btn): chip pile + cards share a flex stack so the gap between them
   is fixed regardless of card tilt overhang. The stack is anchored by
   `bottom` so it sits directly above where the cards used to live. */
.layout-full-table .seat-wrapper-btn .hero-stack {
    position: absolute;
    left: 50%;
    bottom: var(--hero-card-bottom);
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
    z-index: 4;
    pointer-events: none;
}

.layout-full-table .seat-wrapper-btn .hero-stack > * {
    pointer-events: auto;
}

/* Inside the stack: chip pile uses static positioning, sized by content.
   Hero pile is laid out horizontally (chips left, amount right) since the
   hero seat already takes more vertical space than other seats — keeps the
   pile compact above the cards. */
.layout-full-table .seat-wrapper-btn .hero-stack > .seat-bet-chips {
    position: static;
    top: auto;
    left: auto;
    bottom: auto;
    transform: none;
    flex-direction: row;
    align-items: center;
    gap: 6px;
}

.layout-full-table .seat-wrapper-btn .hero-stack > .seat-bet-chips .chip-amount-label {
    margin-top: 0;
}

/* Inside the stack: cards-on-seat gets real dimensions so flex can lay it out.
   Width is the cards-group width; height is card-width × 1.5 (the same multiplier
   used by --hero-card-h) so the visual tilt overhang is included in the box.
   Doubled selector boosts specificity to win over .replay-v2's bottom override. */
.layout-full-table .seat-wrapper-btn .hero-stack > .hero-cards-on-seat.hero-cards-on-seat {
    position: relative;
    bottom: auto;
    top: auto;
    left: auto;
    width: calc(var(--card-width) * 1.667);
    height: calc(var(--card-width) * 1.5);
}

/* Inside the stack the cards-group anchors to its parent's centre via 50%/50%
   instead of the legacy left:0 + translateX(-50%) anchor that depended on the
   old zero-width parent. */
.layout-full-table .seat-wrapper-btn .hero-stack > .hero-cards-on-seat .cards-group {
    left: 50%;
}

/* 1:1 square table on narrow phones — both quiz/practice and session replay.
   Angle-equalized seat positions: rx=46.8% ry=41.9%, t = i*(2π/N) from south CCW.
   Villain-reveal bottom override stays in sessions-v2.css (replay-only). */
@media (max-width: 500px) {
    .layout-full-table .poker-table-container {
        aspect-ratio: 1 / 1;
    }

    /* Bigger seats on the square table — villain circles and action fills only;
       hero seat keeps its pill geometry (set in the .layout-full-table
       .table-seat.hero rule). The :not(.hero) guard prevents this size from
       overriding the hero pill, which is taller and wider than these squares. */
    .layout-full-table .table-seat:not(.hero),
    .layout-full-table .seat-action:not(.hero) {
        width: clamp(56px, 13vw, 84px);
        height: clamp(56px, 13vw, 84px);
    }

    /* Scale action text to match the larger seats. */
    .layout-full-table .action-verb   { font-size: 0.58rem; }
    .layout-full-table .action-amount { font-size: 0.84rem; }

    /* Playing cards on 1:1 — community, hero hole cards, and villain
       revealed-at-showdown cards all use the same clamp. */
    .layout-full-table .community-cards-center .playing-card,
    .layout-full-table .seat-wrapper-btn .hero-cards-on-seat,
    .layout-full-table .villain-cards-revealed-on-seat {
        --card-width: clamp(32px, 10vw, 50px);
    }

    /* Villain reveal sits 5px lower at 1:1 — the +10px from the universal
       rule pushes too far up when the table goes square. */
    .layout-full-table .villain-cards-revealed-on-seat {
        bottom: calc(75% + 5px);
    }

    .layout-full-table .community-cards-center .playing-card {
        --card-height: calc(var(--card-width) * 1.294);
        --card-font: calc(var(--card-width) * 0.392);
    }
    .layout-full-table .villain-cards {
        --card-width: clamp(24px, 6.5vw, 36px);
    }

    /* Pot well above community cards at all 1:1 viewports. */
    .layout-full-table .poker-table:has(.community-cards-center) .table-pot {
        top: 30%;
        font-size: 0.85rem;
        transform: translate(-50%, -50%);
    }

    /* Dealer button beside the hero seat, not above it. */
    .layout-full-table .btn-dealer-btn {
        top: 91%;
        left: 73%;
    }

    /* 6-seat angle-equalized at 1:1 */
    .layout-full-table .poker-table-container[data-seats="6"] .seat-wrapper-btn { top: 91.90%; left: 50.00%; }
    .layout-full-table .poker-table-container[data-seats="6"] .seat-wrapper-sb  { top: 70.95%; left:  9.47%; }
    .layout-full-table .poker-table-container[data-seats="6"] .seat-wrapper-bb  { top: 29.05%; left:  9.47%; }
    .layout-full-table .poker-table-container[data-seats="6"] .seat-wrapper-utg { top:  8.10%; left: 50.00%; }
    .layout-full-table .poker-table-container[data-seats="6"] .seat-wrapper-mp  { top: 29.05%; left: 90.53%; }
    .layout-full-table .poker-table-container[data-seats="6"] .seat-wrapper-co  { top: 70.95%; left: 90.53%; }

    /* 9-seat angle-equalized at 1:1 */
    .layout-full-table .poker-table-container[data-seats="9"] .seat-wrapper-btn  { top: 91.50%; left: 50.00%; }
    .layout-full-table .poker-table-container[data-seats="9"] .seat-wrapper-sb   { top: 81.79%; left: 20.75%; }
    .layout-full-table .poker-table-container[data-seats="9"] .seat-wrapper-bb   { top: 57.20%; left:  5.19%; }
    .layout-full-table .poker-table-container[data-seats="9"] .seat-wrapper-utg  { top: 29.25%; left: 10.60%; }
    .layout-full-table .poker-table-container[data-seats="9"] .seat-wrapper-utg1 { top: 11.00%; left: 34.44%; }
    .layout-full-table .poker-table-container[data-seats="9"] .seat-wrapper-mp   { top: 11.00%; left: 65.56%; }
    .layout-full-table .poker-table-container[data-seats="9"] .seat-wrapper-lj   { top: 29.25%; left: 89.40%; }
    .layout-full-table .poker-table-container[data-seats="9"] .seat-wrapper-hj   { top: 57.20%; left: 94.81%; }
    .layout-full-table .poker-table-container[data-seats="9"] .seat-wrapper-co   { top: 81.79%; left: 79.25%; }

    /* Hero stack gap: flush so chip pile sits directly above cards. */
    .layout-full-table .seat-wrapper-btn .hero-stack {
        gap: 0;
    }
}

.chips-stack {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 0;
}

/* SVG chip disc — 22×22 matches the chip symbol viewBox */
.chip-disc {
    display: block;
    width: 22px;
    height: 22px;
    position: relative;
    flex-shrink: 0;
}

.chip-disc:not(:first-child) {
    margin-top: -18px;
}

/* Top chip (first child) renders in front of chips below it */
.chips-stack .chip-disc:nth-child(1) { z-index: 4; }
.chips-stack .chip-disc:nth-child(2) { z-index: 3; }
.chips-stack .chip-disc:nth-child(3) { z-index: 2; }
.chips-stack .chip-disc:nth-child(4) { z-index: 1; }

/* Amount label — styled like the pot label, shown below the chip stack */
.chip-amount-label {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--action-call, #00e676);
    background: rgba(0, 0, 0, 0.7);
    border-radius: 5px;
    padding: 2px 5px;
    white-space: nowrap;
    margin-top: 3px;
    letter-spacing: 0.02em;
}

/* Slide-in: chips start at the seat centre (no transform offset) and slide
   to their resting position along the direction-to-pot vector. The resting
   transform mirrors the .seat-bet-chips rule above so the keyframe lands on
   exactly the resting position — same math, same units. */
@keyframes chip-slide-from-seat {
    0%   {
        transform: translate(-50%, -50%) translate(0, 0) scale(0.65);
        opacity: 0;
    }
    100% {
        transform: translate(-50%, -50%)
                   translate(var(--chip-x-px, 0px), var(--chip-y-px, -56px))
                   scale(1);
        opacity: 1;
    }
}

/* Hero variant: chips rest above the cards in a flex stack — the chip pile
   is statically positioned now, so the slide animation uses plain translateY
   without the legacy translateX(-50%) anchor. Slides up from below the cards. */
@keyframes chip-slide-from-seat-hero {
    0%   {
        transform: translateY(calc(var(--hero-card-h) + 14px)) scale(0.65);
        opacity: 0;
    }
    100% {
        transform: translateY(0) scale(1);
        opacity: 1;
    }
}

.seat-bet-chips.chip-slide-from-seat {
    animation: chip-slide-from-seat 0.32s cubic-bezier(0.22, 1, 0.36, 1) 0.15s both;
}
.layout-full-table .seat-wrapper-btn .seat-bet-chips.chip-slide-from-seat {
    animation: chip-slide-from-seat-hero 0.32s cubic-bezier(0.22, 1, 0.36, 1) 0.15s both;
}

/* =====================================================================
   OMAHA (PLO) 4-CARD VARIANT
   =====================================================================
   Self-contained. Everything here is scoped under
   `.poker-table-container.is-omaha`, which the renderer adds only when
   hand.game.variant === 'PLO'. Hold'em (2-card) rendering is never touched.

   Omaha deals 4 hole cards. Hero, villain card backs, and villain showdown
   cards each show four cards instead of two.

   Card sizes are INHERITED from the matching Hold'em rules -- nothing here sets
   a card-width. Hero and showdown cards stay at the Hold'em hero scale (the same
   size as the community cards); the backs stay at the Hold'em back size. No
   Omaha-specific sizes are invented and no card is shrunk below the board.

   Only the LAYOUT changes for four cards: each card gets an even horizontal step
   plus a gentle symmetric tilt, rotating about its own bottom edge (the base
   `transform-origin: bottom center`). The even step is what keeps every rank and
   suit readable -- our cards carry a single centered index, so neighbours must
   not cover past their middle. The tilt is kept small so the spread reads as a
   hand without curving enough to hide cards behind each other.
     step      = 0.6 * card-width (hero / showdown), 0.45 (backs)
     tilt      = -8, -3, 3, 8 deg (symmetric, gentle)
     z-index   = 1, 2, 3, 4       (right card on top)
   The group box widens to card-width * 2.8 (a container dimension, not a card
   size) so the four-card spread stays centered and the hero chip pile stays
   centered above it. Because the fan is no taller than the Hold'em hand, it sits
   at the inherited --hero-card-bottom and clears both the seat and the board.
   ===================================================================== */

/* ---- Hero hole cards (on the BTN seat) ----
   The outer .hero-cards-on-seat box (inside .hero-stack) and the inner
   .cards-group both widen so the four-card spread is centered. */
.layout-full-table .poker-table-container.is-omaha .seat-wrapper-btn .hero-stack > .hero-cards-on-seat.hero-cards-on-seat {
    width: calc(var(--card-width) * 2.8);
}
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat .cards-group {
    width: calc(var(--card-width) * 2.8);
}
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat .cards-group .playing-card:nth-child(1) {
    left: 0;
    transform: rotate(-8deg);
    z-index: 1;
}
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat .cards-group .playing-card:nth-child(2) {
    left: calc(var(--card-width) * 0.6);
    transform: rotate(-3deg);
    z-index: 2;
    filter: drop-shadow(-1px 1px 2px rgba(0, 0, 0, 0.4)) drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.4));
}
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat .cards-group .playing-card:nth-child(3) {
    left: calc(var(--card-width) * 1.2);
    transform: rotate(3deg);
    z-index: 3;
    filter: drop-shadow(-1px 1px 2px rgba(0, 0, 0, 0.4)) drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.4));
}
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat .cards-group .playing-card:nth-child(4) {
    left: calc(var(--card-width) * 1.8);
    transform: rotate(8deg);
    z-index: 4;
    filter: drop-shadow(-1px 1px 2px rgba(0, 0, 0, 0.4)) drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.4));
}
/* Tilting about the bottom edge lifts the end cards' outer top corners above
   the middle pair. Drop the two ends a touch so the top line arcs the natural
   way -- middle highest, ends lower -- like a held hand. */
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat .cards-group .playing-card:first-child,
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat .cards-group .playing-card:last-child {
    bottom: calc(var(--card-width) * -0.12);
}

/* Hero folds: gray all four cards, beating the per-card drop-shadow above.
   The fan offset/tilt is kept; only the filter changes. */
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat.folded .cards-group .playing-card:nth-child(1),
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat.folded .cards-group .playing-card:nth-child(2),
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat.folded .cards-group .playing-card:nth-child(3),
.layout-full-table .poker-table-container.is-omaha .hero-cards-on-seat.folded .cards-group .playing-card:nth-child(4) {
    filter: grayscale(1) brightness(0.5);
    opacity: 1;
}

/* ---- Villain card backs (peeking from behind seats) ----
   Backs inherit the Hold'em back size; a tighter 0.45 step keeps four of them
   from crowding the neighbouring seats (no ranks to read here). */
.layout-full-table .poker-table-container.is-omaha .villain-cards .cards-group {
    width: calc(var(--card-width) * 2.35);
}
.layout-full-table .poker-table-container.is-omaha .villain-cards .cards-group .card-back:nth-child(1) {
    left: 0;
    transform: rotate(-8deg);
    z-index: 1;
}
.layout-full-table .poker-table-container.is-omaha .villain-cards .cards-group .card-back:nth-child(2) {
    left: calc(var(--card-width) * 0.45);
    transform: rotate(-3deg);
    z-index: 2;
}
.layout-full-table .poker-table-container.is-omaha .villain-cards .cards-group .card-back:nth-child(3) {
    left: calc(var(--card-width) * 0.9);
    transform: rotate(3deg);
    z-index: 3;
    box-shadow: -2px 5px 14px rgba(0, 0, 0, 0.6);
}
.layout-full-table .poker-table-container.is-omaha .villain-cards .cards-group .card-back:nth-child(4) {
    left: calc(var(--card-width) * 1.35);
    transform: rotate(8deg);
    z-index: 4;
    box-shadow: -2px 5px 14px rgba(0, 0, 0, 0.6);
}
.layout-full-table .poker-table-container.is-omaha .villain-cards .cards-group .card-back:first-child,
.layout-full-table .poker-table-container.is-omaha .villain-cards .cards-group .card-back:last-child {
    bottom: calc(var(--card-width) * -0.12);
}

/* ---- Villain showdown cards (revealed face-up) ----
   Inherit the Hold'em showdown size; same 0.6 step as the hero so all four
   ranks read. */
.layout-full-table .poker-table-container.is-omaha .villain-cards-revealed-on-seat .cards-group {
    width: calc(var(--card-width) * 2.8);
}
.layout-full-table .poker-table-container.is-omaha .villain-cards-revealed-on-seat .cards-group .playing-card:nth-child(1) {
    left: 0;
    transform: rotate(-8deg);
    z-index: 1;
}
.layout-full-table .poker-table-container.is-omaha .villain-cards-revealed-on-seat .cards-group .playing-card:nth-child(2) {
    left: calc(var(--card-width) * 0.6);
    transform: rotate(-3deg);
    z-index: 2;
    filter: drop-shadow(-1px 1px 2px rgba(0, 0, 0, 0.4)) drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.4));
}
.layout-full-table .poker-table-container.is-omaha .villain-cards-revealed-on-seat .cards-group .playing-card:nth-child(3) {
    left: calc(var(--card-width) * 1.2);
    transform: rotate(3deg);
    z-index: 3;
    filter: drop-shadow(-1px 1px 2px rgba(0, 0, 0, 0.4)) drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.4));
}
.layout-full-table .poker-table-container.is-omaha .villain-cards-revealed-on-seat .cards-group .playing-card:nth-child(4) {
    left: calc(var(--card-width) * 1.8);
    transform: rotate(8deg);
    z-index: 4;
    filter: drop-shadow(-1px 1px 2px rgba(0, 0, 0, 0.4)) drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.4));
}
.layout-full-table .poker-table-container.is-omaha .villain-cards-revealed-on-seat .cards-group .playing-card:first-child,
.layout-full-table .poker-table-container.is-omaha .villain-cards-revealed-on-seat .cards-group .playing-card:last-child {
    bottom: calc(var(--card-width) * -0.12);
}

/* =====================================================================
   END OMAHA (PLO) 4-CARD VARIANT
   ===================================================================== */
