/* ============================================================
 * 鋤大D / Big Two — refined styling
 *
 * Design language (v0.22.42):
 *   - Sophisticated dark surface using plugin tokens (--mg-bg-2,
 *     --mg-line, etc.) so it stays consistent with the rest of
 *     the plugin. (Light mode removed in v0.22.42 — locked dark.)
 *   - Active turn / selection / "your turn" highlights use
 *     var(--mg-accent), which is whatever color the user picked
 *     for their site theme (blue by default, but customizable).
 *     No more hardcoded gold — gold was breaking customised themes.
 *   - Card faces stay ivory + red/black for poker readability;
 *     those colors are intrinsic to playing cards, not theme-driven.
 *
 * Naming: BEM-style .mg-bigtwo__*
 * ============================================================ */

.mg-bigtwo {
    --bigtwo-card-red: #c0392b;
    --bigtwo-card-black: #1a1a1a;
    --bigtwo-card-bg: #fefcf6;
    --bigtwo-card-border: #d8c896;
    /* Table surface — uses plugin's existing dark tokens for consistency
       with xiangqi/gomoku. Falls back to charcoal if tokens missing. */
    --bigtwo-table-bg: var(--mg-bg-2, #2c2c2e);
    --bigtwo-table-edge: var(--mg-bg, #1c1c1e);
    --bigtwo-table-line: var(--mg-line, #38383a);

    /* Responsive card sizing. clamp(min, preferred, max) scales smoothly
       with viewport width:
         - mobile (~375vw): card ~36×52
         - tablet (~768vw): card ~50×72
         - desktop (~1280vw+): card 64×92
       The aspect ratio (~1.43:1) matches a real poker card.
       Card-backs (opponent hands) use the SAME size as face-up cards
       so the table reads as one consistent set of cards rather than
       a player-vs-counters mismatch. */
    --bigtwo-card-w: clamp(36px, 4.0vw, 64px);
    --bigtwo-card-h: clamp(52px, 5.7vw, 92px);
    --bigtwo-back-w: var(--bigtwo-card-w);
    --bigtwo-back-h: var(--bigtwo-card-h);

    color: var(--mg-ink, #1f2937);
}

/* ============================================================
   Lobby
   ============================================================ */
/* v0.23.83: removed .mg-bigtwo__title / .mg-bigtwo__subtitle /
   .mg-bigtwo__lobby-actions — no HTML/JS references. The lobby
   uses .mg-bigtwo__header-actions (below) and .mg-title from the
   plugin's shared CSS. */

/* New lobby header (matches 2p-game pattern): title left, action
   buttons right, on a single row. Wraps gracefully on narrow screens. */
.mg-bigtwo__header-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-left: auto;
}
.mg-bigtwo__gate-msg {
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line);
    border-left: 3px solid var(--mg-accent);
    border-radius: var(--mg-radius, 10px);
    padding: 12px 16px;
    margin: 0 0 16px 0;
    color: var(--mg-ink-muted);
    font-size: 13px;
    line-height: 1.5;
    font-family: var(--mg-display);
}

/* Create-match modal — private checkbox row.
   v0.22.42: aligned with xiangqi/junglechess/gomoku. Boxed row with
   subtle border + hover state, matching the "private match" widget
   shape across all four PvP games. */
.mg-bigtwo__create-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px;
    margin: 0 0 4px 0;
    background: var(--mg-bg);
    border: 1px solid var(--mg-line);
    border-radius: var(--mg-radius-sm, 8px);
    cursor: pointer;
    font-size: 14px;
    color: var(--mg-ink);
    transition: border-color .12s;
}
.mg-bigtwo__create-row:hover {
    border-color: var(--mg-line-strong);
}
.mg-bigtwo__create-row input[type="checkbox"] {
    accent-color: var(--mg-accent);
    margin-top: 2px;
    flex: 0 0 auto;
}
.mg-bigtwo__create-row > span {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.mg-bigtwo__create-row .mg-bigtwo__create-hint {
    display: block;
    font-size: 12px;
    color: var(--mg-ink-muted);
    margin-top: 4px;
    line-height: 1.4;
    font-weight: normal;
}

/* Rules disclosure — uses plugin tokens. */
.mg-bigtwo__rules {
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line);
    border-radius: var(--mg-radius, 10px);
    padding: 14px 18px;
    margin-top: 16px;
    font-size: 13px;
    color: var(--mg-ink-muted);
}
.mg-bigtwo__rules summary {
    cursor: pointer;
    font-weight: 600;
    user-select: none;
    color: var(--mg-ink);
}
.mg-bigtwo__rules-body {
    margin-top: 14px;
    line-height: 1.6;
}
.mg-bigtwo__rules-body p { margin: 8px 0; }
.mg-bigtwo__rules-body strong { color: var(--mg-ink); }
.mg-bigtwo__rules-body ul { margin: 8px 0; padding-left: 20px; }
.mg-bigtwo__rules-body ul li { margin: 3px 0; }

/* ============================================================
   Practice modal — match xiangqi's pattern
   ============================================================ */
.mg-bigtwo__create-modal {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.55);
    z-index: 9000;
    padding: 16px;
}
.mg-bigtwo__create-modal[hidden] { display: none; }
.mg-bigtwo__create-card {
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line-strong);
    border-radius: var(--mg-radius, 10px);
    padding: 20px 22px;
    box-shadow: 0 12px 36px rgba(0, 0, 0, 0.5);
    width: 100%;
    max-width: 420px;
    color: var(--mg-ink);
}
.mg-bigtwo__create-title {
    margin: 0 0 14px;
    font-size: 16px;
    font-weight: 600;
    color: var(--mg-ink);
    font-family: var(--mg-display);
}
.mg-bigtwo__create-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 16px;
}
/* Standalone hint paragraph (used in practice modal as preamble).
   Inside .create-row spans, the nested rule above takes precedence. */
.mg-bigtwo__create-card > .mg-bigtwo__create-hint {
    font-size: 13px;
    color: var(--mg-ink-muted);
    line-height: 1.5;
    margin: 0 0 16px 0;
}

/* ============================================================
   Match header
   ============================================================ */
.mg-bigtwo__match-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}
.mg-bigtwo__practice-badge {
    background: var(--mg-accent-soft);
    color: var(--mg-accent);
    border: 1px solid var(--mg-accent-glow);
    padding: 4px 12px;
    border-radius: 999px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 700;
    display: inline-flex;
    gap: 6px;
    align-items: center;
}
.mg-bigtwo__practice-badge[hidden] { display: none; }
.mg-bigtwo__status {
    flex: 1 1 auto;
    text-align: right;
    font-size: 14px;
    color: var(--mg-ink-muted);
    min-height: 1.2em;
    word-break: break-all;
    font-weight: 500;
}
.mg-bigtwo__status.is-your-turn {
    color: var(--mg-accent);
    font-weight: 700;
}

/* v0.22.46: "I'm back — take over" reclaim button.
   Visually distinct from the play/pass row — sits alongside the
   status text. Compact so it doesn't dominate the toolbar; gentle
   accent so abandoned-self users notice it without it screaming
   when other states are also vying for attention. */
.mg-bigtwo__reclaim-btn {
    flex: 0 0 auto;
    margin-left: 8px;
    padding: 4px 12px;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    border-radius: 6px;
    /* Pulse to draw eye — abandoned users are by definition not
       paying full attention. Subtle, not jittery. */
    animation: mg-bigtwo-reclaim-pulse 1.6s ease-in-out infinite;
}
@keyframes mg-bigtwo-reclaim-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 165, 0, 0.4); }
    50%      { box-shadow: 0 0 0 5px rgba(255, 165, 0, 0); }
}

/* ============================================================
   Table — sophisticated dark surface
   ============================================================ */
.mg-bigtwo__table {
    display: grid;
    /* Side columns sized for opponent card-back stacks. Now that
       card-backs are the same size as face-up cards (~64px desktop),
       sides need at least 90px. Center column dominant for trick area. */
    grid-template-columns: minmax(90px, 1fr) minmax(280px, 3fr) minmax(90px, 1fr);
    grid-template-rows: auto 1fr auto;
    /* Top + bottom span full width so human hand + top opponent get
       breathing room; left + right opponents stay in side columns. */
    grid-template-areas:
        "top    top    top"
        "left   center right"
        "bottom bottom bottom";
    gap: 14px;
    min-height: 540px;
    max-width: 820px;
    margin: 0 auto;
    background:
        radial-gradient(ellipse 90% 70% at 50% 50%,
            var(--bigtwo-table-bg) 0%,
            var(--bigtwo-table-edge) 100%);
    border: 1px solid var(--bigtwo-table-line);
    border-radius: 16px;
    padding: 20px;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.04),
        0 4px 16px rgba(0, 0, 0, 0.3);
    position: relative;
}

.mg-bigtwo__seat--top    { grid-area: top; }
.mg-bigtwo__seat--left   { grid-area: left; }
.mg-bigtwo__seat--right  { grid-area: right; }
.mg-bigtwo__seat--bottom { grid-area: bottom; }

/* Opponent seat panels: top + left + right all share the same panel
   styling (subtle bg, rounded, gentle padding) so they read as a
   cohesive set. Their widths differ because top spans 3 grid cols
   while left/right occupy single cols, but the panel treatment is
   identical. */
.mg-bigtwo__seat--top,
.mg-bigtwo__seat--left,
.mg-bigtwo__seat--right {
    background: rgba(0, 0, 0, 0.12);
    border-radius: 10px;
    padding: 8px 14px;
}

.mg-bigtwo__seat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 8px;
    border-radius: 12px;
    transition: all 250ms ease;
    min-height: 70px;
    position: relative;
    z-index: 1;
}
.mg-bigtwo__seat.is-active {
    background: var(--mg-accent-soft);
    box-shadow:
        0 0 0 1px var(--mg-accent-glow),
        0 0 16px var(--mg-accent-soft);
}
.mg-bigtwo__seat.is-finished {
    opacity: 0.4;
    filter: saturate(0.5);
}
/* v0.22.33: seat marked abandoned (player walked away — server's
   tick_timeout reached CONSECUTIVE_TIMEOUTS_TO_ABANDON). AI continues
   playing for them at server cadence. Keep the cards visible (so other
   players can read the table state) but desaturate + tag the name,
   and render the "Walked away — AI continues" badge in muted tone via
   the count line which renderSeat now overrides. */
.mg-bigtwo__seat.is-abandoned {
    opacity: 0.55;
    filter: saturate(0.6);
}
.mg-bigtwo__seat.is-abandoned .mg-bigtwo__seat-name {
    text-decoration: line-through;
    text-decoration-thickness: 1px;
    color: var(--mg-text-muted, #999);
}
.mg-bigtwo__seat.is-abandoned [data-seat-count] {
    color: var(--mg-warning, #c97a2b);
    font-style: italic;
    font-size: 0.85em;
}
.mg-bigtwo__seat--left,
.mg-bigtwo__seat--right {
    justify-content: center;
}
.mg-bigtwo__seat--bottom {
    /* No fixed min-height — let content size it. Add bottom padding
       so the lift on hover/select doesn't push cards past the frame
       edge. Width capped to ~7 cards + gaps so the human hand block
       doesn't sprawl across the full table width on wide displays. */
    padding-bottom: 24px;
    background: rgba(0, 0, 0, 0.18);
    border-radius: 10px;
    max-width: calc((var(--bigtwo-card-w) + 6px) * 7 + 24px);
    margin-left: auto;
    margin-right: auto;
    width: 100%;
}
.mg-bigtwo__seat--bottom.is-active {
    background: var(--mg-accent-soft);
}

/* ============================================================
   TranslatePress-immune content rendering (v0.22.31)
   ============================================================
   Six element classes display their text via `data-text` attribute
   and `::after { content: attr(data-text) }` rather than as real
   DOM text nodes. MutationObserver-based translators (TranslatePress,
   Google Translate, Bing Translator) walk only text nodes; pseudo-
   element content is invisible to them. This is the ONLY reliable
   way to stop the visible flicker that v0.22.21–v0.22.30's five
   layers of notranslate/translate=no/contain/min-height/setText-
   diffing failed to eliminate — TP's observer runs regardless of
   those hints, and the microsecond decision window is what's
   actually visible as the flash.
   
   Used only for content that is genuinely never translated:
     - Display names (proper nouns)
     - Card counts, score values, timer (numbers)
     - Match IDs (#42)
   See setStaticText() in bigtwo.js for the JS pairing.
   
   Accessibility: setStaticText also writes aria-label so screen
   readers continue to announce the value even though it lives in a
   pseudo element. Modern AT (NVDA, JAWS, VoiceOver post ~2018) read
   pseudo content directly; aria-label is a defense for older AT. */
.mg-bigtwo__seat-name[data-text]::after,
.mg-bigtwo__seat-count[data-text]::after,
.mg-bigtwo__pvp-timer-value[data-text]::after,
.mg-bigtwo__pvp-lobby-meta[data-text]::after,
.mg-bigtwo__pvp-score-name[data-text]::after,
.mg-bigtwo__pvp-score-value[data-text]::after {
    content: attr(data-text);
    /* Inherit text styling so the pseudo content visually matches
       what a real text node would have rendered. The host element's
       font-size / color / weight all flow through naturally because
       pseudo content is rendered with the host's computed style. */
}

.mg-bigtwo__seat-info {
    display: flex;
    align-items: baseline;
    gap: 8px;
    color: rgba(255, 255, 255, 0.92);
    font-size: 13px;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
    /* TranslatePress (and other DOM-mutation translators) sometimes
       wrap descendants in <trp-segment> / <trp-block> ghost tags
       even on elements marked translate="no", and re-walks the
       subtree on every parent class-toggle (.is-active flips per
       turn). Reserve a fixed vertical box and contain the layout
       so any internal wrapping/reflow can't bubble up and shove
       the seat-hand below it — which manifested as a visible
       up-down jitter on every poll.
       See user feedback v0.22.23. */
    min-height: 22px;
    contain: layout style;
}
.mg-bigtwo__seat-name {
    font-weight: 600;
    /* Reserve a single line of space so a brief wrapper insert
       can't push height to 2 lines mid-poll. Long names ellipsize
       rather than wrap. */
    display: inline-block;
    line-height: 1.2;
    min-height: 1.2em;
    max-width: 14em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: baseline;
}
.mg-bigtwo__seat-count {
    font-size: 11px;
    opacity: 0.85;
    background: rgba(0, 0, 0, 0.4);
    padding: 2px 8px;
    border-radius: 999px;
    font-variant-numeric: tabular-nums;
    border: 1px solid rgba(255, 255, 255, 0.08);
    /* Same rationale as seat-name — keep single-line. */
    display: inline-block;
    line-height: 1.2;
    min-height: 1.2em;
    white-space: nowrap;
    vertical-align: baseline;
}

/* Whole-seat containment: any internal change (TranslatePress
   wrappers, class toggles, hand re-render) calculates layout
   inside the seat box and never reflows the parent grid. This
   prevents a flickering name from shoving sibling seats around. */
.mg-bigtwo__seat {
    contain: layout style;
}

/* ============================================================
   Opponent face-down hands
   ============================================================ */
.mg-bigtwo__seat:not(.mg-bigtwo__seat--human) .mg-bigtwo__seat-hand {
    display: flex;
    gap: 0;
    flex-wrap: nowrap;
}
.mg-bigtwo__seat-hand--vertical { flex-direction: column; }
.mg-bigtwo__seat-hand--horizontal { flex-direction: row; }

/* ============================================================
   Card back (v0.22.71): user-selectable design
   ============================================================
   Base class holds sizing, border, radius, shadow — properties
   common to every variant. The visual treatment (background +
   ::before glyph) is selected by `data-mg-cardback="<slug>"` on
   the .mg-bigtwo root, written by class-mg-user-prefs (server)
   or by the theme picker JS (client live-preview).

   Six variants ship: hash-spade (default), frame, band, split,
   checker, solid. Picker UI in class-mg-user-prefs::sc_picker.

   All variants use --mg-accent for body and --mg-accent-ink for
   pattern/glyph so they auto-contrast on whatever accent each
   user picks. color-mix() softens pattern colors to muted alpha
   without needing pre-computed RGB tuples.
   ============================================================ */
.mg-bigtwo__card-back {
    width: var(--bigtwo-back-w);
    height: var(--bigtwo-back-h);
    background-color: var(--mg-accent);
    border: 1px solid var(--mg-line-strong);
    border-radius: clamp(4px, 0.6vw, 8px);
    flex-shrink: 0;
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.22),
        inset 0 1px 0 rgba(255, 255, 255, 0.12);
    position: relative;
}

/* Variant 1 — hash + ♠ (default) */
.mg-bigtwo[data-mg-cardback="hash-spade"] .mg-bigtwo__card-back {
    background-image: repeating-linear-gradient(
        45deg,
        transparent 0,
        transparent 7px,
        color-mix(in srgb, var(--mg-accent-ink) 16%, transparent) 7px,
        color-mix(in srgb, var(--mg-accent-ink) 16%, transparent) 8px);
}
.mg-bigtwo[data-mg-cardback="hash-spade"] .mg-bigtwo__card-back::before {
    content: "♠";
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--mg-accent-ink);
    font-size: calc(var(--bigtwo-back-w) * 0.4);
    font-weight: 900;
    line-height: 1;
    opacity: 0.26;
    pointer-events: none;
}

/* Variant 2 — luxury dot grid (v0.22.73, replaces 'frame')
   Small dots on a 5px grid. Auto-contrast via --mg-accent-ink so
   the dots stay visible on pale and dark accents alike. */
.mg-bigtwo[data-mg-cardback="dot"] .mg-bigtwo__card-back {
    background-image: radial-gradient(
        circle,
        color-mix(in srgb, var(--mg-accent-ink) 60%, transparent) 0.7px,
        transparent 1.5px);
    background-size: 5px 5px;
}

/* Variant 3 — center vertical band */
.mg-bigtwo[data-mg-cardback="band"] .mg-bigtwo__card-back {
    background-image: linear-gradient(
        90deg,
        transparent 0%,
        transparent 35%,
        color-mix(in srgb, var(--mg-accent-ink) 18%, transparent) 35%,
        color-mix(in srgb, var(--mg-accent-ink) 18%, transparent) 65%,
        transparent 65%,
        transparent 100%);
}

/* Variant 4 — 135° diagonal split (two-tone) */
.mg-bigtwo[data-mg-cardback="split"] .mg-bigtwo__card-back {
    background-image: linear-gradient(
        135deg,
        transparent 0%,
        transparent 50%,
        color-mix(in srgb, var(--mg-accent-ink) 28%, transparent) 50%,
        color-mix(in srgb, var(--mg-accent-ink) 28%, transparent) 100%);
}

/* Variant 5 — tiny checker (3px) */
.mg-bigtwo[data-mg-cardback="checker"] .mg-bigtwo__card-back {
    background-image:
        linear-gradient(45deg,
            color-mix(in srgb, var(--mg-accent-ink) 12%, transparent) 25%,
            transparent 25%,
            transparent 75%,
            color-mix(in srgb, var(--mg-accent-ink) 12%, transparent) 75%),
        linear-gradient(45deg,
            color-mix(in srgb, var(--mg-accent-ink) 12%, transparent) 25%,
            transparent 25%,
            transparent 75%,
            color-mix(in srgb, var(--mg-accent-ink) 12%, transparent) 75%);
    background-size: 6px 6px;
    background-position: 0 0, 3px 3px;
}

/* Variant 6 — solid + ♠ (no pattern) */
.mg-bigtwo[data-mg-cardback="solid"] .mg-bigtwo__card-back::before {
    content: "♠";
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--mg-accent-ink);
    font-size: calc(var(--bigtwo-back-w) * 0.5);
    font-weight: 900;
    line-height: 1;
    opacity: 0.28;
    pointer-events: none;
}

/* Fallback for older saved data with no slug set (e.g. cached HTML
   from before v0.22.71): match the default. */
.mg-bigtwo:not([data-mg-cardback]) .mg-bigtwo__card-back {
    background-image: repeating-linear-gradient(
        45deg,
        transparent 0,
        transparent 7px,
        color-mix(in srgb, var(--mg-accent-ink) 16%, transparent) 7px,
        color-mix(in srgb, var(--mg-accent-ink) 16%, transparent) 8px);
}
.mg-bigtwo:not([data-mg-cardback]) .mg-bigtwo__card-back::before {
    content: "♠";
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--mg-accent-ink);
    font-size: calc(var(--bigtwo-back-w) * 0.4);
    font-weight: 900;
    line-height: 1;
    opacity: 0.26;
    pointer-events: none;
}
/* Overlap proportions tuned per orientation:
   - Horizontal (top opponent): 70% overlap — wider bar shows more edges
   - Vertical (left/right): 85% overlap — tight enough that 13 cards
     fit in the middle row height (~92px card * 0.15 step * 12 + 92 ≈ 257px)
   Calc against actual card size so it scales with viewport. */
.mg-bigtwo__seat-hand--horizontal .mg-bigtwo__card-back + .mg-bigtwo__card-back {
    margin-left: calc(var(--bigtwo-back-w) * -0.7);
}
.mg-bigtwo__seat-hand--vertical .mg-bigtwo__card-back + .mg-bigtwo__card-back {
    margin-top: calc(var(--bigtwo-back-h) * -0.85);
}

/* ============================================================
   Center: trick + history
   ============================================================ */
.mg-bigtwo__center {
    grid-area: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 130px;
    position: relative;
    z-index: 1;
}
.mg-bigtwo__trick {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    min-height: 72px;
    perspective: 600px;
}
.mg-bigtwo__trick .mg-bigtwo__card {
    animation: bigtwoCardPlay 280ms cubic-bezier(0.34, 1.3, 0.64, 1);
}
@keyframes bigtwoCardPlay {
    from {
        transform: translateY(-6px) rotateY(15deg);
        opacity: 0;
    }
    to {
        transform: translateY(0) rotateY(0);
        opacity: 1;
    }
}

/* ============================================================
   Deal animation — opening sequence
   ============================================================ */
/* When .is-dealing, all card-backs (opponents) and the human's cards
   start invisible and animate into place. Round-robin schedule is set
   by JS via inline animation-delay on each card. */
.mg-bigtwo.is-dealing .mg-bigtwo__card-back {
    opacity: 0;
    transform: translate(-200%, -200%) scale(0.4) rotate(-180deg);
    animation: bigtwoDealCardBack 350ms cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
}
.mg-bigtwo.is-dealing .mg-bigtwo__seat-hand--human .mg-bigtwo__card {
    opacity: 0;
    transform: translateY(-200px) scale(0.5) rotate(-15deg);
    animation: bigtwoDealHumanCard 350ms cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
}
@keyframes bigtwoDealCardBack {
    from {
        opacity: 0;
        transform: translate(-200%, -200%) scale(0.4) rotate(-180deg);
    }
    50% { opacity: 1; }
    to {
        opacity: 1;
        transform: translate(0, 0) scale(1) rotate(0);
    }
}
@keyframes bigtwoDealHumanCard {
    from {
        opacity: 0;
        transform: translateY(-200px) scale(0.5) rotate(-15deg);
    }
    50% { opacity: 1; }
    to {
        opacity: 1;
        transform: translateY(0) scale(1) rotate(0);
    }
}
/* Stagger handled by JS — sets inline `animation-delay` on each card
   so dealing follows round-robin order (seat0 → seat1 → seat2 → seat3
   → seat0 → ...) like a real dealer. CSS nth-child can't do this
   because the cards are in 4 different containers. */

/* During dealing, suppress hover/select on human cards (player can't
   click yet) and dim the trick area. */
.mg-bigtwo.is-dealing .mg-bigtwo__seat-hand--human .mg-bigtwo__card {
    pointer-events: none;
}
.mg-bigtwo.is-dealing .mg-bigtwo__trick {
    opacity: 0.4;
}
.mg-bigtwo__trick-empty {
    color: rgba(255, 255, 255, 0.45);
    font-size: 13px;
    font-style: italic;
    letter-spacing: 0.03em;
}
.mg-bigtwo__trick-meta {
    font-size: 12px;
    color: rgba(255, 255, 255, 0.85);
    text-align: center;
    min-height: 1.2em;
    letter-spacing: 0.02em;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

/* History strip — previous play */
.mg-bigtwo__history {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 10px;
    background: rgba(0, 0, 0, 0.25);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 999px;
    margin-top: 4px;
    max-width: 100%;
    flex-wrap: wrap;
    justify-content: center;
    opacity: 0.75;
}
.mg-bigtwo__history[hidden] { display: none; }
.mg-bigtwo__history-label {
    font-size: 11px;
    color: rgba(255, 255, 255, 0.65);
    letter-spacing: 0.02em;
    white-space: nowrap;
}
.mg-bigtwo__history-cards {
    display: flex;
    gap: 2px;
}

/* ============================================================
   Cards
   ============================================================ */
.mg-bigtwo__card {
    display: inline-flex;
    flex-direction: column;
    width: var(--bigtwo-card-w);
    height: var(--bigtwo-card-h);
    padding: clamp(4px, 0.5vw, 7px);
    background:
        linear-gradient(180deg, var(--bigtwo-card-bg) 0%, #f5efe0 100%);
    border: 1px solid var(--bigtwo-card-border);
    border-radius: clamp(4px, 0.6vw, 8px);
    box-shadow:
        0 2px 4px rgba(0, 0, 0, 0.3),
        0 1px 2px rgba(0, 0, 0, 0.15),
        inset 0 1px 0 rgba(255, 255, 255, 0.6);
    font-family: 'Helvetica Neue', Arial, sans-serif;
    user-select: none;
    flex-shrink: 0;
    line-height: 1;
    position: relative;
}
/* v0.23.84: restored .mg-bigtwo__card--red / .mg-bigtwo__card--black
   — previous audit (v0.23.83) wrongly thought these were unused.
   makeCardEl() in bigtwo.js still sets className based on suit colour,
   and no inline style replaces this. Without these rules, the rank /
   suit text inherits the dark-theme parent colour and renders white-
   on-white = invisible card faces. */
.mg-bigtwo__card--red    { color: var(--bigtwo-card-red); }
.mg-bigtwo__card--black  { color: var(--bigtwo-card-black); }

.mg-bigtwo__card-rank {
    /* Scale with card width — ~30% of card width */
    font-size: calc(var(--bigtwo-card-w) * 0.3);
    font-weight: 700;
    align-self: flex-start;
    letter-spacing: -0.05em;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.mg-bigtwo__card-suit {
    /* Suit slightly larger than rank */
    font-size: calc(var(--bigtwo-card-w) * 0.48);
    font-weight: 600;
    align-self: center;
    line-height: 1;
    margin-top: auto;
    margin-bottom: auto;
}

/* Mini variant — used in history strip. Uses !important on size
   because some user themes inject overrides on .mg-bigtwo__card that
   were stretching one card to full size in the history. The parent
   strip uses inline-flex and an unstretchable basis. Sized relative
   to the responsive card vars so it scales with viewport. */
.mg-bigtwo__card--mini {
    width:  calc(var(--bigtwo-card-w) * 0.5) !important;
    height: calc(var(--bigtwo-card-h) * 0.5) !important;
    min-width:  calc(var(--bigtwo-card-w) * 0.5);
    max-width:  calc(var(--bigtwo-card-w) * 0.5);
    min-height: calc(var(--bigtwo-card-h) * 0.5);
    max-height: calc(var(--bigtwo-card-h) * 0.5);
    padding: 2px;
    border-radius: 3px;
    box-shadow:
        0 1px 1px rgba(0, 0, 0, 0.25),
        inset 0 1px 0 rgba(255, 255, 255, 0.5);
    flex: 0 0 auto;
}
.mg-bigtwo__card--mini .mg-bigtwo__card-rank {
    font-size: calc(var(--bigtwo-card-w) * 0.16);
}
.mg-bigtwo__card--mini .mg-bigtwo__card-suit {
    font-size: calc(var(--bigtwo-card-w) * 0.22);
}

/* ============================================================
   Human hand
   ============================================================ */
.mg-bigtwo__seat-hand--human {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 4px;
    padding: 12px 8px 6px 8px;
    min-height: 92px;
    align-content: flex-end;
    /* Cap the row width so 13 cards don't sprawl into 3+ rows on
       desktop. ~7 cards per row * (card_w + gap) keeps it to 2 rows
       (7 + 6). The clamp matches viewport-scaled card-w + a small
       margin per card. */
    max-width: calc((var(--bigtwo-card-w) + 6px) * 7);
    margin-left: auto;
    margin-right: auto;
}
.mg-bigtwo__seat-hand--human .mg-bigtwo__card {
    cursor: pointer;
    transition:
        transform 180ms cubic-bezier(0.34, 1.3, 0.64, 1),
        box-shadow 180ms ease,
        border-color 180ms ease;
    will-change: transform;
    position: relative;
}
.mg-bigtwo__seat-hand--human .mg-bigtwo__card:hover,
.mg-bigtwo__seat-hand--human .mg-bigtwo__card.is-selected {
    z-index: 2;
}
.mg-bigtwo__seat-hand--human .mg-bigtwo__card:hover {
    transform: translateY(-6px);
    box-shadow:
        0 6px 12px rgba(0, 0, 0, 0.45),
        0 2px 4px rgba(0, 0, 0, 0.2),
        inset 0 1px 0 rgba(255, 255, 255, 0.6);
    border-color: var(--mg-accent-glow);
}
.mg-bigtwo__seat-hand--human .mg-bigtwo__card.is-selected {
    transform: translateY(-14px);
    border-color: var(--mg-accent);
    border-width: 1.5px;
    box-shadow:
        0 8px 18px var(--mg-accent-glow),
        0 4px 8px rgba(0, 0, 0, 0.3),
        inset 0 1px 0 rgba(255, 255, 255, 0.7);
    /* Prevent the browser from stealing vertical scroll while the
       user swipes a selected card up to play. Horizontal scroll
       remains untouched. */
    touch-action: pan-x;
}

/* Spectator's bottom-seat hand: face-up but non-interactive.
   Suppresses the human-hand hover lift / cursor pointer that would
   otherwise suggest the cards are clickable. The active player's
   identity is conveyed by the seat name + status text "輪到 X",
   not by visual interaction cues. */
.mg-bigtwo__seat-hand--human.is-spectator-view .mg-bigtwo__card {
    cursor: default;
}
.mg-bigtwo__seat-hand--human.is-spectator-view .mg-bigtwo__card:hover {
    transform: none;
    box-shadow:
        0 2px 4px rgba(0, 0, 0, 0.3),
        0 1px 2px rgba(0, 0, 0, 0.15),
        inset 0 1px 0 rgba(255, 255, 255, 0.6);
    border-color: var(--bigtwo-card-border);
}
.mg-bigtwo__seat-hand--human .mg-bigtwo__card.is-selected:hover {
    transform: translateY(-18px);
}

/* ============================================================
   Action buttons
   ============================================================ */
.mg-bigtwo__actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 16px;
    justify-content: center;
}
.mg-bigtwo__actions .mg-btn {
    min-width: 100px;
    transition: all 180ms ease;
    font-weight: 600;
}
.mg-bigtwo__actions .mg-btn:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

.mg-bigtwo__hint {
    font-size: 12px;
    color: var(--mg-ink-muted);
    margin-top: 10px;
    text-align: center;
    font-style: italic;
}

/* ============================================================
   End-game overlay — uses tokens for consistency
   ============================================================ */
.mg-bigtwo__end-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.65);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9000;
    padding: 16px;
}
.mg-bigtwo__end-overlay[hidden] { display: none; }
.mg-bigtwo__end-card {
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line-strong);
    border-radius: var(--mg-radius, 10px);
    padding: 24px;
    max-width: 400px;
    width: 100%;
    box-shadow: 0 12px 36px rgba(0, 0, 0, 0.5);
    text-align: center;
    color: var(--mg-ink);
}
.mg-bigtwo__end-title {
    font-family: var(--mg-display);
    font-size: 22px;
    font-weight: 700;
    margin: 0 0 6px 0;
    color: var(--mg-accent);
}
.mg-bigtwo__end-subtitle {
    font-size: 12px;
    color: var(--mg-ink-muted);
    margin: 0 0 18px 0;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-weight: 600;
}

/* Redeal modal text — uses same overlay/card foundation as end-overlay */
.mg-bigtwo__redeal-message {
    font-size: 14px;
    color: var(--mg-ink);
    margin: 12px 0 24px 0;
    line-height: 1.5;
}
.mg-bigtwo__finishing-order {
    list-style: none;
    counter-reset: rank;
    text-align: left;
    margin: 0 0 24px 0;
    padding: 0;
    font-size: 14px;
}
.mg-bigtwo__finishing-order li {
    counter-increment: rank;
    padding: 10px 14px;
    border-radius: 8px;
    margin: 4px 0;
    background: var(--mg-bg);
    border: 1px solid var(--mg-line);
    display: flex;
    align-items: center;
    gap: 12px;
    line-height: 1.4;
    color: var(--mg-ink);
}
.mg-bigtwo__finishing-order li::before {
    content: counter(rank);
    font-family: var(--mg-display);
    font-size: 18px;
    font-weight: 700;
    color: var(--mg-accent);
    min-width: 22px;
}
.mg-bigtwo__finishing-order li.is-human {
    font-weight: 700;
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent-glow);
}
.mg-bigtwo__end-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
}

/* ============================================================
   PvP lobby (Phase 3)
   ============================================================ */
.mg-bigtwo__pvp-lobby {
    padding: 14px;
    color: var(--mg-ink);
}
.mg-bigtwo__pvp-seats {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
    max-width: 520px;
    margin: 24px auto;
}
.mg-bigtwo__pvp-seat {
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line);
    border-radius: 10px;
    padding: 16px;
    text-align: center;
    min-height: 110px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
}
.mg-bigtwo__pvp-seat.is-host {
    border-color: var(--mg-accent-glow);
}
.mg-bigtwo__pvp-seat.is-you {
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent);
}
.mg-bigtwo__pvp-seat.is-open {
    border-style: dashed;
}
.mg-bigtwo__pvp-seat-label {
    font-size: 11px;
    color: var(--mg-ink-muted);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-family: var(--mg-display);
}
.mg-bigtwo__pvp-seat-name {
    font-size: 16px;
    font-weight: 600;
    color: var(--mg-ink);
    font-family: var(--mg-display);
}
.mg-bigtwo__pvp-seat-name.is-empty {
    color: var(--mg-ink-muted);
    font-weight: 400;
}
/* v0.23.83: removed .mg-bigtwo__pvp-seat-actions — no HTML/JS refs.
   Per-seat leave buttons render directly in the seat card (no wrapper). */
.mg-bigtwo__pvp-controls {
    display: flex;
    gap: 12px;
    justify-content: center;
    margin: 12px 0;
}
.mg-bigtwo__pvp-status {
    text-align: center;
    color: var(--mg-ink-muted);
    font-size: 14px;
    font-family: var(--mg-display);
}
.mg-bigtwo__pvp-lobby-title {
    font-size: 18px;
    color: var(--mg-ink);
    margin: 0;
    font-family: var(--mg-display);
}
.mg-bigtwo__pvp-lobby-meta {
    margin-left: auto;
    color: var(--mg-ink-muted);
    font-size: 13px;
    font-family: var(--mg-display);
    letter-spacing: 0.04em;
}

/* ============================================================
   PvP — match list view
   ============================================================ */
.mg-bigtwo__pvp-list {
    padding: 14px;
    color: var(--mg-ink);
}
/* v0.23.83: removed .mg-bigtwo__pvp-list-title — no HTML/JS refs. */
.mg-bigtwo__pvp-list-section {
    margin: 18px 0;
}
.mg-bigtwo__pvp-list-h {
    font-size: 13px;
    /* Was: var(--mg-ink-muted) — picked up theme white/black, looked
     * disconnected from the accent-colored "1/4" / "2/4" badges below.
     * Now matches the badge color family so the whole row reads as a
     * single accent-themed unit instead of "grey label, colored badge". */
    color: var(--mg-accent);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    margin: 0 0 8px 0;
    font-weight: 600;
    /* Pixel font for visual cohesion with .mg-title — matches the
       2p-game pattern (xiangqi/junglechess use the same explicit
       override to defeat site themes that set h3 globally). */
    font-family: var(--mg-display);
}
.mg-bigtwo__pvp-list-rows {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-height: 56px;  /* breathing room when empty so sections aren't squashed */
}
.mg-bigtwo__pvp-list-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line);
    border-radius: 8px;
    color: var(--mg-ink);
    font-size: 14px;
    text-align: left;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}
.mg-bigtwo__pvp-list-row:hover:not(.is-disabled) {
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent);
}
.mg-bigtwo__pvp-list-row.is-disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
.mg-bigtwo__pvp-list-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    padding: 3px 8px;
    background: var(--mg-bg);
    border: 1px solid var(--mg-line-strong);
    border-radius: 6px;
    font-family: var(--mg-display);
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 0.04em;
    color: var(--mg-accent);
}
/* v0.22.63: .is-full override removed. All seat-count badges now use
 * the single outline style above, regardless of fill state (1/4, 2/4,
 * 3/4, 4/4 all look identical). The "X/Y" text alone conveys fill;
 * styling them differently created an inconsistent lobby where the
 * "我的進行中對局" section's 4/4 looked unlike the "等緊玩家加入"
 * section's 1/4. User wanted three sections to read as one consistent
 * group. */
.mg-bigtwo__pvp-list-names {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--mg-ink);
    /* Names use pixel font in arcade theme (it's already the body
       font there); explicit override ensures clean theme also gets
       the consistent look across all rows. */
    font-family: var(--mg-display);
}
.mg-bigtwo__pvp-list-verb {
    color: var(--mg-ink-muted);
    font-size: 13px;
    flex-shrink: 0;
    font-family: var(--mg-display);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.mg-bigtwo__pvp-list-empty {
    color: var(--mg-ink-muted);
    text-align: center;
    margin: auto;       /* vertical-centre inside flex container */
    padding: 12px 0;
    font-size: 13px;
    font-family: var(--mg-display);
}

/* Row wrapper for own waiting matches: join button + cancel button
   side-by-side. Hover/focus styles on the inner button still apply
   independently. */
.mg-bigtwo__pvp-list-row-wrap {
    display: flex;
    gap: 6px;
    align-items: stretch;
}
.mg-bigtwo__pvp-list-row-wrap .mg-bigtwo__pvp-list-row--main {
    flex: 1;
    min-width: 0;
}
/*
 * Cancel button.
 *
 * v0.22.58 fixes two issues spotted in production:
 *
 *   1. Site theme (Elementor / WP parent) was overriding our
 *      background on hover, painting the button solid coral/orange
 *      regardless of the user's chosen accent. The theme rule was a
 *      generic `button:hover { background: ... }` with enough
 *      specificity to outweigh ours. Fix: compound selector
 *      (`button.mg-bigtwo__pvp-list-cancel`) for the steady state,
 *      plus `!important` on background/border/color for the hover
 *      state where the site theme actively interferes. Scoped to
 *      this one class so other buttons aren't affected.
 *
 *   2. Hover state was a neutral white (--mg-ink) that didn't read
 *      as theme-aware. Now uses --mg-accent-soft bg + --mg-accent
 *      border/text + --mg-accent-glow shadow, so the button visibly
 *      picks up whichever accent the player has set (matches the
 *      .mg-chat__chip hover treatment and the .mg-btn--primary
 *      focus style elsewhere in the system).
 *
 *   3. radius via --mg-radius-sm so arcade theme gets sharp corners
 *      consistent with the rest of arcade UI (was hardcoded 8px).
 */
.mg-bigtwo__pvp-list-cancel,
button.mg-bigtwo__pvp-list-cancel {
    flex-shrink: 0;
    padding: 0 14px;
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line-strong);
    border-radius: var(--mg-radius-sm);
    color: var(--mg-ink-muted);
    font-family: var(--mg-display);
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s, background 0.15s, box-shadow 0.15s;
}
.mg-bigtwo__pvp-list-cancel:hover,
.mg-bigtwo__pvp-list-cancel:focus-visible,
button.mg-bigtwo__pvp-list-cancel:hover,
button.mg-bigtwo__pvp-list-cancel:focus-visible {
    /* !important on background + border + color: the site theme has
       generic button:hover rules with enough specificity to beat a
       plain class selector. Armor narrowly scoped to this one class. */
    background: var(--mg-accent-soft) !important;
    border-color: var(--mg-accent) !important;
    color: var(--mg-accent) !important;
    box-shadow: 0 0 0 1px var(--mg-accent-soft),
                0 0 8px var(--mg-accent-glow);
    outline: none;
}
.mg-bigtwo__pvp-list-cancel:active,
button.mg-bigtwo__pvp-list-cancel:active {
    background: var(--mg-accent) !important;
    color: var(--mg-accent-ink) !important;
    border-color: var(--mg-accent) !important;
    transform: translateY(1px);
}
.mg-bigtwo__pvp-list-cancel:disabled,
.mg-bigtwo__pvp-list-cancel.is-disabled,
button.mg-bigtwo__pvp-list-cancel:disabled,
button.mg-bigtwo__pvp-list-cancel.is-disabled {
    opacity: 0.45;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

/* ============================================================
   PvP — per-turn timer
   ============================================================ */
.mg-bigtwo__pvp-timer {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line);
    border-radius: 16px;
    font-size: 13px;
    color: var(--mg-ink-muted);
    transition: color 0.2s, border-color 0.2s, background 0.2s;
    /* Same rationale as seat-info: stop TranslatePress wrapper
       insertions inside the timer span from collapsing the box. */
    contain: layout style;
}
.mg-bigtwo__pvp-timer-value {
    /* Reserve room for "30s" → "29s" → … so the timer doesn't
       collapse to 0×0 when TranslatePress (or another translator)
       briefly wraps the textContent in a ghost tag during its
       processing pass. User reported in v0.22.23 that the number
       just disappeared after the v0.22.21 notranslate fix; the
       likely cause was a wrapper that lost its inline-flex slot
       while the parent's flex layout reflowed. Explicit
       inline-block + min-width gives it a guaranteed footprint. */
    display: inline-block;
    min-width: 2.4em;
    text-align: right;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}
.mg-bigtwo__pvp-timer[hidden] { display: none; }
.mg-bigtwo__pvp-timer.is-mine {
    border-color: var(--mg-accent);
    color: var(--mg-accent);
}
.mg-bigtwo__pvp-timer.is-mid {
    border-color: var(--mg-line-strong);
    color: var(--mg-ink);
}
.mg-bigtwo__pvp-timer.is-low {
    /* Red-ish urgency without hardcoding a colour — invert the
       accent into a warning palette via CSS filter. Browsers
       reduce hue-rotate for users with reduced-motion preference. */
    border-color: var(--mg-line-strong);
    color: var(--mg-ink);
    animation: mg-bigtwo-pulse 0.8s ease-in-out infinite;
}
@keyframes mg-bigtwo-pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.06); }
}
.mg-bigtwo__pvp-timer-icon {
    font-size: 12px;
}
.mg-bigtwo__pvp-timer-value {
    font-family: var(--mg-display);
    font-weight: 700;
    min-width: 30px;
    text-align: right;
    letter-spacing: 0.04em;
}

/* ============================================================
   PvP — scores strip (4 cells + round number)
   ============================================================ */
.mg-bigtwo__pvp-scores {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    align-items: center;
    padding: 8px 12px;
    margin: 4px 8px;
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line);
    border-radius: 8px;
}
.mg-bigtwo__pvp-scores[hidden] { display: none; }
.mg-bigtwo__pvp-score-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    flex: 1;
    min-width: 70px;
    padding: 4px 8px;
    border-radius: 6px;
    background: var(--mg-bg);
    border: 1px solid var(--mg-line);
}
.mg-bigtwo__pvp-score-cell.is-you {
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent);
}
.mg-bigtwo__pvp-score-cell.is-positive .mg-bigtwo__pvp-score-value {
    color: var(--mg-accent);
}
.mg-bigtwo__pvp-score-cell.is-negative .mg-bigtwo__pvp-score-value {
    /* Slightly muted for negatives — the contrast keeps them readable
       without hardcoding red. */
    opacity: 0.65;
}
.mg-bigtwo__pvp-score-name {
    font-size: 11px;
    color: var(--mg-ink-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
    font-family: var(--mg-display);
}
.mg-bigtwo__pvp-score-value {
    font-family: var(--mg-display);
    font-weight: 700;
    font-size: 16px;
    color: var(--mg-ink);
    letter-spacing: 0.04em;
}

/* ============================================================
   PvP — spectator badge
   ============================================================ */
.mg-bigtwo__pvp-spectator-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    margin-left: 8px;
    background: var(--mg-accent-soft);
    border: 1px solid var(--mg-accent);
    border-radius: 12px;
    font-size: 12px;
    color: var(--mg-accent-ink);
    font-weight: 600;
    font-family: var(--mg-display);
    letter-spacing: 0.04em;
}

/* .mg-btn--small modifier moved to assets/core.css in v0.23.15 so doudizhu
   (and any future game enqueuing only core.css) gets the same compact
   button sizing. No behavioural change for bigtwo. */

/* ============================================================
   Mobile breakpoint — collapse cross-layout to stacked rows.
   At 900px or less, the cross layout's center column gets too
   cramped, so we switch to stacked rows: top, left, right, center,
   bottom.
   ============================================================ */
@media (max-width: 900px) {
    .mg-bigtwo__table {
        grid-template-columns: 1fr;
        grid-template-rows: auto auto auto auto auto;
        grid-template-areas:
            "top"
            "left"
            "right"
            "center"
            "bottom";
        gap: 8px;
        padding: 14px;
        min-height: 0;
    }
    /* Top + left + right opponents collapse into compact rows with
       label on left + card stack on right. Bottom (the human hand)
       keeps its column layout — label on top, cards below in 2 rows. */
    .mg-bigtwo__seat--top,
    .mg-bigtwo__seat--left,
    .mg-bigtwo__seat--right {
        flex-direction: row;
        justify-content: space-between;
        min-height: 0;
        padding: 8px 12px;
        background: rgba(0, 0, 0, 0.25);
        border-radius: 8px;
        max-width: none;
        /* Override desktop's width: fit-content on --top so all three
           opponent frames stretch to mobile container width. */
        width: auto;
        align-self: stretch;
    }
    .mg-bigtwo__seat--bottom {
        /* Reset desktop width cap — let human hand use full mobile
           width so 13 cards have room to wrap into 2 rows (7+6). */
        max-width: none;
        width: auto;
        padding: 12px 8px 18px 8px;
    }
    .mg-bigtwo__seat--top .mg-bigtwo__seat-hand,
    .mg-bigtwo__seat--left .mg-bigtwo__seat-hand,
    .mg-bigtwo__seat--right .mg-bigtwo__seat-hand {
        flex-direction: row;
    }
    /* On mobile, all 3 opponents are arranged in horizontal rows.
       JS still assigns --vertical class to left/right (per the
       desktop cross layout), so we must FORCE horizontal overlap on
       all of them — !important defends against the global --vertical
       rule and any user-theme overrides that might compete. */
    .mg-bigtwo__seat--top .mg-bigtwo__seat-hand .mg-bigtwo__card-back + .mg-bigtwo__card-back,
    .mg-bigtwo__seat--left .mg-bigtwo__seat-hand .mg-bigtwo__card-back + .mg-bigtwo__card-back,
    .mg-bigtwo__seat--right .mg-bigtwo__seat-hand .mg-bigtwo__card-back + .mg-bigtwo__card-back {
        margin-left: calc(var(--bigtwo-back-w) * -0.7) !important;
        margin-top: 0 !important;
    }
    .mg-bigtwo__center {
        min-height: 110px;
        background: rgba(0, 0, 0, 0.3);
        border-radius: 10px;
        padding: 10px;
    }
}

/* ============================================================
   PvP — match list mobile breakpoint (seats grid → 1 column)
   ============================================================ */
@media (max-width: 600px) {
    .mg-bigtwo__pvp-seats {
        grid-template-columns: 1fr;
    }
}

/* ============================================================
   v0.23.53  Hand overflow fix — long username + abandoned badge
   ============================================================
   User reported on mobile: when the bottom (human) seat's
   username is long, or when "Walked away — AI continues" badge
   shows up, the seat-info row pushes wider than the seat's
   max-width cap (~7 cards). The hand cards (children of a
   separate .seat-hand element below) wrap to the next row
   correctly, but the .seat-info row itself overflows past the
   seat container's right edge — visually clipping into the
   trick / opponent panel.

   Root cause: .seat-info is a flex row inside .seat--bottom
   (flex-direction: column). The column parent's max-width
   constrains its own width but doesn't constrain children's
   intrinsic widths — a 14em seat-name + uncapped seat-count
   badge can easily exceed the parent width and overflow.

   Fix:
   - .seat-info: max-width: 100% + flex: 0 1 auto, so it can't
     exceed the parent (.seat--bottom)'s capped width
   - .seat-name: shrink with min-width: 0 so its ellipsis kicks
     in before it pushes the count badge off-screen
   - .seat-count: flex-shrink: 1 + min-width: 0 so the abandoned
     badge text ellipsizes too
   - Mobile: drop seat-name max-width and let the flex shrink
     handle it entirely
   ============================================================ */

.mg-bigtwo__seat--bottom .mg-bigtwo__seat-info {
    max-width: 100%;
    box-sizing: border-box;
    flex-wrap: wrap;
}
.mg-bigtwo__seat--bottom .mg-bigtwo__seat-name {
    min-width: 0;
    flex: 0 1 auto;
}
.mg-bigtwo__seat--bottom .mg-bigtwo__seat-count {
    min-width: 0;
    flex: 0 1 auto;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* On phones the 14em seat-name is itself overflowing — drop the
   cap entirely and let the parent's max-width + min-width:0 do
   all the bounding. */
@media (max-width: 600px) {
    .mg-bigtwo__seat--bottom .mg-bigtwo__seat-name {
        max-width: none;
    }
}

/* ============================================================
   END v0.23.53
   ============================================================ */


/* ============================================================
   v0.23.58 — finishing-order tie-aware rank display
   ============================================================
   When .is-manual-rank is set on the <ol>, suppress the CSS
   counter ::before and use the explicit <span class="rank"> the
   JS writes. This lets two seats with the same card count
   share a rank (e.g. "3" and "3" instead of "3" then "4").
   ============================================================ */
.mg-bigtwo__finishing-order.is-manual-rank li::before {
    content: none;
}
.mg-bigtwo__finishing-order.is-manual-rank li {
    counter-increment: none;
}
.mg-bigtwo__finishing-rank {
    font-family: var(--mg-display);
    font-size: 18px;
    font-weight: 700;
    color: var(--mg-accent);
    min-width: 22px;
    display: inline-block;
}
.mg-bigtwo__finishing-body {
    flex: 1 1 auto;
}
/* ============================================================
   END v0.23.58
   ============================================================ */

/* v0.23.89: toast fallback element (parity with doudizhu).
   Only renders when window.MG.toast is unavailable; the framework
   normally handles toasts via its own portal. Visual style mirrors
   doudizhu.css equivalent so the fallback feels consistent across
   games. */
.mg-bigtwo__toast {
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line-strong);
    border-radius: var(--mg-radius, 10px);
    padding: 12px 18px;
    color: var(--mg-ink);
    font-size: 13px;
    z-index: 9100;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
    max-width: 80vw;
}
