/* ============================================================
 * 鬥地主 / Doudizhu — refined styling, matches bigtwo design language
 *
 * Design language:
 *   - Dark surface via plugin tokens (--mg-bg-2, --mg-line, etc.) for
 *     consistency with bigtwo and the rest of the plugin.
 *   - Active turn / selection / "your turn" highlights via var(--mg-accent).
 *   - Card faces stay ivory + red/black for poker readability.
 *   - 3-seat CSS Grid table with radial-gradient felt-table surface.
 *
 * Naming: BEM-style .mg-doudizhu__*
 * ============================================================ */

/* CRITICAL: enforce the HTML `hidden` attribute. Many of our panels and
   overlays have `display: flex` rules below; those would otherwise win
   over the UA stylesheet's `[hidden] { display: none }` (same specificity,
   later cascade), leaving overlays stacked on screen even when JS sets
   .hidden=true. */
.mg-doudizhu [hidden],
.mg-doudizhu[hidden] {
    display: none !important;
}

.mg-doudizhu {
    --doudizhu-card-red: #c0392b;
    --doudizhu-card-black: #1a1a1a;
    --doudizhu-card-bg: #fefcf6;
    --doudizhu-card-border: #d8c896;
    --doudizhu-table-bg: var(--mg-bg-2, #2c2c2e);
    --doudizhu-table-edge: var(--mg-bg, #1c1c1e);
    --doudizhu-table-line: var(--mg-line, #38383a);

    /* Responsive card sizing — same scale as bigtwo. */
    --doudizhu-card-w: clamp(36px, 4.0vw, 64px);
    --doudizhu-card-h: clamp(52px, 5.7vw, 92px);
    --doudizhu-back-w: var(--doudizhu-card-w);
    --doudizhu-back-h: var(--doudizhu-card-h);

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

/* ============================================================
   Lobby — same shape as bigtwo
   ============================================================ */
.mg-doudizhu__lobby {
    /* Default block layout — sections rely on their `margin: 18px 0` to
       provide vertical rhythm, and margin-collapse keeps consecutive
       sections at a clean 18px gap. Matches bigtwo's `.mg-bigtwo__lobby`
       (which has no rule at all, falling back to UA defaults). An earlier
       `display: flex; gap: 16px` here added the 16px gap ON TOP of the
       section margins, producing visibly more vertical space between
       items than bigtwo. v0.23.11 fix. */
}
.mg-doudizhu__header-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-left: auto;
}
.mg-doudizhu__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;
    color: var(--mg-ink-muted);
    font-size: 13px;
    line-height: 1.5;
    font-family: var(--mg-display);
}
.mg-doudizhu__pvp-list-section {
    margin: 18px 0;
}
.mg-doudizhu__pvp-list-h {
    font-size: 13px;
    color: var(--mg-accent);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    margin: 0 0 8px 0;
    font-weight: 600;
    font-family: var(--mg-display);
}
.mg-doudizhu__pvp-list-rows {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-height: 56px;
}
.mg-doudizhu__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;
    width: 100%;
    transition: background 0.15s, border-color 0.15s;
}
.mg-doudizhu__pvp-list-row:hover:not(.is-disabled),
.mg-doudizhu__pvp-list-row:focus-visible:not(.is-disabled) {
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent);
    outline: none;
}
.mg-doudizhu__pvp-list-row.is-disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
.mg-doudizhu__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);
    flex-shrink: 0;
}
.mg-doudizhu__pvp-list-names {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--mg-ink);
    font-family: var(--mg-display);
}
.mg-doudizhu__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-doudizhu__pvp-list-empty {
    color: var(--mg-ink-muted);
    text-align: center;
    margin: auto;
    padding: 12px 0;
    font-size: 13px;
    font-family: var(--mg-display);
}

/* Own waiting match: row + cancel button side-by-side */
.mg-doudizhu__pvp-list-row-wrap {
    display: flex;
    gap: 6px;
    align-items: stretch;
}
.mg-doudizhu__pvp-list-row-wrap .mg-doudizhu__pvp-list-row--main {
    flex: 1;
    min-width: 0;
}
.mg-doudizhu__pvp-list-cancel,
button.mg-doudizhu__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-doudizhu__pvp-list-cancel:hover,
.mg-doudizhu__pvp-list-cancel:focus-visible,
button.mg-doudizhu__pvp-list-cancel:hover,
button.mg-doudizhu__pvp-list-cancel:focus-visible {
    /* !important: armor against site theme's generic button:hover overrides */
    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-doudizhu__pvp-list-cancel:active,
button.mg-doudizhu__pvp-list-cancel:active {
    background: var(--mg-accent) !important;
    color: var(--mg-accent-ink) !important;
    border-color: var(--mg-accent) !important;
    transform: translateY(1px);
}

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

/* ============================================================
   Create-match modal — same shape as bigtwo
   ============================================================ */
.mg-doudizhu__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-doudizhu__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-doudizhu__create-title {
    margin: 0 0 14px;
    font-size: 16px;
    font-weight: 600;
    color: var(--mg-ink);
    font-family: var(--mg-display);
}
.mg-doudizhu__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-doudizhu__create-row:hover {
    border-color: var(--mg-line-strong);
}
.mg-doudizhu__create-row input[type="checkbox"] {
    accent-color: var(--mg-accent);
    margin-top: 2px;
    flex: 0 0 auto;
}
.mg-doudizhu__create-row > span {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.mg-doudizhu__create-hint {
    display: block;
    font-size: 12px;
    color: var(--mg-ink-muted);
    margin-top: 4px;
    line-height: 1.4;
    font-weight: normal;
}
.mg-doudizhu__create-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 16px;
}

/* v0.24.38 (Round 9): difficulty button-grid (replaces v0.24.34
   radio fieldset). Pattern mirrors xiangqi/gomoku — each difficulty
   is a button that doubles as the start trigger. Two-line layout:
   bold title + muted tagline. Specificity 0,2,1 matches the global
   `.mg-frame button.mg-btn` rule so its uppercase + wide letter-
   spacing don't bleed onto our two-line button. */
.mg-doudizhu__difficulty-grid {
    display: grid;
    /* minmax(0, 1fr) instead of 1fr — without it long taglines force
       the column wider than the modal and clip. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
    margin: 12px 0 8px 0;
}
@media (max-width: 480px) {
    .mg-doudizhu__difficulty-grid {
        grid-template-columns: 1fr;
    }
}
.mg-doudizhu button.mg-doudizhu__difficulty-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 12px 6px;
    text-align: center;
    line-height: 1.3;
    height: auto;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
    min-width: 0;
    box-sizing: border-box;
}
.mg-doudizhu button.mg-doudizhu__difficulty-btn strong {
    font-size: 15px;
    font-weight: 700;
    color: var(--mg-ink);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    min-width: 0;
}
.mg-doudizhu button.mg-doudizhu__difficulty-btn span {
    font-size: 11px;
    color: var(--mg-ink-muted);
    font-weight: 400;
    line-height: 1.25;
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: break-word;
    max-width: 100%;
    min-width: 0;
}
@media (max-width: 380px) {
    .mg-doudizhu button.mg-doudizhu__difficulty-btn span { font-size: 10px; }
}
.mg-doudizhu__difficulty-btn:hover strong {
    color: var(--mg-accent);
}

/* v0.23.20: bidding-mode fieldset (rob mode radio selector).
   Wraps 2 radio options as a logical group; legend acts as section
   header. Internal radio rows reuse create-row styling for visual
   cohesion (same padding, border, hover behavior). Default UA
   fieldset styling (3D groove border, italic legend) is reset to
   match the modal's clean card aesthetic. */
.mg-doudizhu__create-fieldset {
    flex-direction: column;
    border: 1px solid var(--mg-line);
    /* Override default fieldset border-radius reset done by some themes;
       match the surrounding create-row rounded edges. */
    border-radius: var(--mg-radius-sm, 8px);
    padding: 12px;
    background: var(--mg-bg);
    cursor: default;
}
.mg-doudizhu__create-fieldset > legend {
    /* Standard floating legend looks out of place in a modal card; use
       inline label with bottom margin instead. Reset all browser styling
       by re-declaring everything we care about. */
    font-size: 13px;
    font-weight: 600;
    color: var(--mg-ink-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 0 6px;
    font-family: var(--mg-display);
}
.mg-doudizhu__create-radio {
    /* Same visual structure as create-row but for radio buttons. Distinct
       class so fieldset's > legend selector doesn't accidentally cascade. */
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px;
    margin: 4px 0;
    background: var(--mg-bg-2);
    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, background .12s;
}
.mg-doudizhu__create-radio:hover {
    border-color: var(--mg-line-strong);
}
.mg-doudizhu__create-radio input[type="radio"] {
    accent-color: var(--mg-accent);
    margin-top: 2px;
    flex: 0 0 auto;
}
.mg-doudizhu__create-radio > span {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
/* Selected radio gets accent border + soft background for visual feedback. */
.mg-doudizhu__create-radio:has(input[type="radio"]:checked) {
    border-color: var(--mg-accent);
    background: var(--mg-accent-soft);
}

/* v0.23.20: rob-mode badge in lobby row. Sits between the seats-filled
   badge and the names. Distinct background tint (accent-soft) so it's
   visually distinct from the standard "2/3" filled badge. */
.mg-doudizhu__pvp-list-badge--mode {
    min-width: 28px;
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent);
    color: var(--mg-accent);
}

/* ============================================================
   Match header — common to pvp-lobby + match view
   ============================================================ */
.mg-doudizhu__match-header {
    /* v0.23.17: gap matches bigtwo (10px, was 12px). */
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}
.mg-doudizhu__pvp-lobby-title {
    /* v0.23.17: separated from `__match-round` and made bigtwo-identical:
       18px display-font title (was 14px Body font; visually too small
       compared to the bigtwo "Match lobby" heading). */
    font-size: 18px;
    color: var(--mg-ink);
    margin: 0;
    font-family: var(--mg-display);
}
.mg-doudizhu__match-round {
    /* Was sharing the rule above with pvp-lobby-title; now kept separate.
       This is the in-match #N round badge — smaller body-font is fine. */
    font-size: 14px;
    font-weight: 600;
    margin: 0;
    color: var(--mg-ink);
}
.mg-doudizhu__pvp-lobby-meta {
    /* v0.23.17: pixel-match bigtwo. Was 12px body-font with tabular-nums
       only; bigtwo's is 13px display-font with `margin-left: auto` to
       push the meta to the far-right of the header (next to the title),
       plus letter-spacing 0.04em. tabular-nums was unnecessary since the
       meta is now `#<matchId>` (no aligned columns of numbers needed). */
    margin-left: auto;
    color: var(--mg-ink-muted);
    font-size: 13px;
    font-family: var(--mg-display);
    letter-spacing: 0.04em;
}
/* v0.24.51: Practice-mode pill — visually identical to bigtwo's badge.
   JS toggles `hidden`. Only shown in practice mode, hidden in PvP. */
.mg-doudizhu__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-doudizhu__practice-badge[hidden] { display: none; }
.mg-doudizhu__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-doudizhu__status.is-your-turn {
    color: var(--mg-accent);
    font-weight: 700;
}

/* ============================================================
   PvP lobby (waiting room): 3 seat slots
   ============================================================ */
.mg-doudizhu__pvp-lobby {
    /* v0.23.16: pixel-match bigtwo. Was `display: flex; flex-direction:
       column; gap: 14px` — but bigtwo uses `padding: 14px` on a default
       block container. Flex-column subtly changes how `max-width` and
       `margin: auto` resolve on grid children (cross-axis sizing rules
       interact with stretch/auto-margin in non-obvious ways), which
       caused the doudizhu seat grid to render visibly narrower than
       bigtwo's at the same viewport — the user's screenshot comparison
       was the cleanest possible evidence. Mirror bigtwo exactly. */
    padding: 14px;
    color: var(--mg-ink);
}
.mg-doudizhu__pvp-seats {
    /* v0.23.16: match bigtwo's max-width (520px). On mobile (viewport <
       520) both collapse to full container width — the seat ends up the
       same visible width as bigtwo's. On desktop, 3 seats at 1fr inside
       a 520px-max container = ~165px each; bigtwo 4 seats in 2 cols at
       520px max = ~254px each. The user's reference is the mobile
       layout (image 2), so matching there is the priority. */
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    max-width: 520px;
    margin: 24px auto;
}
.mg-doudizhu__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-doudizhu__pvp-seat.is-host {
    border-color: var(--mg-accent-glow);
}
.mg-doudizhu__pvp-seat.is-you {
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent);
}
.mg-doudizhu__pvp-seat.is-open {
    border-style: dashed;
}
.mg-doudizhu__pvp-seat-label {
    font-size: 11px;
    color: var(--mg-ink-muted);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-family: var(--mg-display);
}
.mg-doudizhu__pvp-seat-name {
    font-size: 16px;
    font-weight: 600;
    color: var(--mg-ink);
    font-family: var(--mg-display);
}
.mg-doudizhu__pvp-seat-name.is-empty {
    color: var(--mg-ink-muted);
    font-weight: 400;
}
/* v0.23.83: removed .mg-doudizhu__pvp-seat-actions and .mg-doudizhu__seat-actions
   — no HTML/JS references. Leave buttons render directly in seat cards. */
.mg-doudizhu__pvp-controls {
    /* v0.23.17: match bigtwo exactly — gap 12px (was 8), drop flex-wrap
       (let buttons overflow visually instead of stacking on a new line —
       bigtwo's lobby is designed so 4 buttons fit at typical widths,
       and 4 buttons matches doudizhu's count too: Share / Fill AI /
       Start / Cancel), add margin 12px 0 for breathing room above the
       status text. */
    display: flex;
    gap: 12px;
    justify-content: center;
    margin: 12px 0;
}
.mg-doudizhu__pvp-status {
    /* v0.23.17: match bigtwo — font-size 14px (was 13), add display
       font, drop the `margin: 8px 0 0` (controls now provides the gap
       via its `margin: 12px 0`). */
    text-align: center;
    color: var(--mg-ink-muted);
    font-size: 14px;
    font-family: var(--mg-display);
}

/* ============================================================
   PvP scores strip (above the table)
   ============================================================ */
.mg-doudizhu__pvp-scores {
    display: flex;
    gap: 8px;
    margin-bottom: 12px;
    justify-content: center;
    flex-wrap: wrap;
}
.mg-doudizhu__pvp-score-badge {
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line);
    border-radius: 999px;
    padding: 4px 12px;
    font-size: 12px;
    color: var(--mg-ink-muted);
    display: flex;
    align-items: center;
    gap: 6px;
}
.mg-doudizhu__pvp-score-badge.is-mine {
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent);
    color: var(--mg-ink);
}
.mg-doudizhu__pvp-score-badge.is-landlord {
    border-color: var(--mg-accent-glow);
}
.mg-doudizhu__pvp-score-name {
    font-weight: 600;
    color: var(--mg-ink);
}
.mg-doudizhu__pvp-score-value {
    font-weight: 700;
    color: var(--mg-accent);
    font-variant-numeric: tabular-nums;
}

/* ============================================================
   Table — 3-seat layout
   ============================================================ */
.mg-doudizhu__table {
    display: grid;
    /* 2 columns side-by-side for the top opponents; center+bottom span both */
    grid-template-columns: minmax(140px, 1fr) minmax(140px, 1fr);
    grid-template-rows: auto auto auto;
    grid-template-areas:
        "top-left  top-right"
        "center    center"
        "bottom    bottom";
    gap: 14px;
    min-height: 480px;
    max-width: 820px;
    margin: 0 auto;
    background:
        radial-gradient(ellipse 90% 70% at 50% 50%,
            var(--doudizhu-table-bg) 0%,
            var(--doudizhu-table-edge) 100%);
    border: 1px solid var(--doudizhu-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-doudizhu__seat--top-left  { grid-area: top-left; }
.mg-doudizhu__seat--top-right { grid-area: top-right; }
.mg-doudizhu__seat--bottom    { grid-area: bottom; }
.mg-doudizhu__center          { grid-area: center; }

/* Opponent seats: subtle panel treatment */
.mg-doudizhu__seat--top-left,
.mg-doudizhu__seat--top-right {
    background: rgba(0, 0, 0, 0.12);
    border-radius: 10px;
    padding: 10px 14px;
}

.mg-doudizhu__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;
    contain: layout style;
}
.mg-doudizhu__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-doudizhu__seat.is-finished {
    opacity: 0.4;
    filter: saturate(0.5);
}
.mg-doudizhu__seat--bottom {
    padding-bottom: 24px;
    background: rgba(0, 0, 0, 0.18);
    border-radius: 10px;
    max-width: calc((var(--doudizhu-card-w) + 6px) * 9 + 24px);
    margin-left: auto;
    margin-right: auto;
    width: 100%;
}
.mg-doudizhu__seat--bottom.is-active {
    background: var(--mg-accent-soft);
}

.mg-doudizhu__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);
    min-height: 22px;
    contain: layout style;
    flex-wrap: wrap;
    justify-content: center;
}
.mg-doudizhu__seat-name {
    font-weight: 600;
    display: inline-block;
    line-height: 1.2;
    min-height: 1.2em;
    max-width: 12em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: baseline;
}
.mg-doudizhu__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);
    display: inline-block;
    line-height: 1.2;
    min-height: 1.2em;
    white-space: nowrap;
    vertical-align: baseline;
}
.mg-doudizhu__seat-role:empty {
    /* v0.23.22: hide empty badge entirely. During claiming/robbing phases
       (rob mode) and bidding phase (classic mode), landlord is still null
       so the role text is blank. Without :empty hide, you'd see 3 empty
       pills in the seat layout — visually noisy and confusing. */
    display: none;
}
.mg-doudizhu__seat-role {
    /* v0.23.22: badge redesign — old version was 10px (Chinese too small to
       read), washed-out neutral bg, and a cheap rgba border. New version:
       12px display-font, generous padding, solid traditional colors
       (地主 red / 農民 blue — same convention used in QQ 鬥地主), subtle
       inset highlight + ground-shadow for depth. Default state (no role
       assigned yet — pre-claiming/bidding) is hidden via :empty above. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 38px;
    padding: 3px 10px;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.7);
    font-family: var(--mg-display);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    line-height: 1.2;
    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}
.mg-doudizhu__seat-role.is-landlord {
    /* 地主 = traditional red. Vertical gradient gives 立體感 without going
       cartoonish. Inset top-highlight + soft drop-shadow signals "active
       role" without the v0.23.x neon-glow. */
    background: linear-gradient(180deg, #d64545 0%, #9c2828 100%);
    border-color: #ed7878;
    color: #fff;
    box-shadow:
        0 1px 3px rgba(214, 69, 69, 0.45),
        inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.mg-doudizhu__seat-role.is-farmer {
    /* 農民 = traditional blue. Same gradient + inset highlight treatment
       as landlord for visual coherence. */
    background: linear-gradient(180deg, #4a7eb0 0%, #2a5485 100%);
    border-color: #7eaad4;
    color: #fff;
    box-shadow:
        0 1px 3px rgba(74, 126, 176, 0.35),
        inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.mg-doudizhu__seat-hand {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: var(--doudizhu-back-h);
    flex-wrap: nowrap;
    padding: 4px 0;
    contain: layout;
    max-width: 100%;
    overflow: hidden;
}
.mg-doudizhu__seat-hand .mg-doudizhu__card-back + .mg-doudizhu__card-back {
    margin-left: calc(var(--doudizhu-back-w) * -0.7);
}

/* ============================================================
   Center area: hole cards + trick + bid/double panels
   ============================================================ */
.mg-doudizhu__center {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 160px;
    position: relative;
    z-index: 1;
}
.mg-doudizhu__hole {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}
.mg-doudizhu__hole-label {
    font-size: 10px;
    color: rgba(255, 255, 255, 0.55);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.mg-doudizhu__hole-cards {
    display: flex;
    gap: 4px;
    align-items: center;
    justify-content: center;
    min-height: calc(var(--doudizhu-card-h) * 0.7);
}
.mg-doudizhu__hole-cards .mg-doudizhu__card {
    /* Hole cards display smaller than play cards */
    width: calc(var(--doudizhu-card-w) * 0.85);
    height: calc(var(--doudizhu-card-h) * 0.85);
}
.mg-doudizhu__hole-cards .mg-doudizhu__card-back {
    width: calc(var(--doudizhu-back-w) * 0.85);
    height: calc(var(--doudizhu-back-h) * 0.85);
}

.mg-doudizhu__trick {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    min-height: 72px;
    perspective: 600px;
}
.mg-doudizhu__trick .mg-doudizhu__card {
    animation: doudizhuCardPlay 280ms cubic-bezier(0.34, 1.3, 0.64, 1);
}
@keyframes doudizhuCardPlay {
    from { transform: translateY(-6px) rotateY(15deg); opacity: 0; }
    to   { transform: translateY(0)    rotateY(0);     opacity: 1; }
}

/* History strip — previous play. Mirrors bigtwo's pill-shaped strip
   so the visual language is consistent across the two card games. */
.mg-doudizhu__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-doudizhu__history-label {
    font-size: 11px;
    color: rgba(255, 255, 255, 0.65);
    letter-spacing: 0.02em;
    white-space: nowrap;
}
.mg-doudizhu__history-cards {
    display: flex;
    gap: 2px;
}

/* Bid panel */
/* v0.24.1: bid/claim/rob/double panels — modern dark glass treatment.
   Previously used rgba(0,0,0,0.25) which read as washed-out gray over
   the table backdrop (user: "斗地主叫分這個欄 背景的灰色不好看,可以
   深色一些 modern設計"). New treatment:
     - Deeper near-opaque dark gradient so the panel reads as a
       distinct surface, not a tint
     - var(--dz-line-strong) border for crisper edge
     - backdrop-filter blur for the modern glass effect (degrades
       gracefully — solid bg already does the job)
     - Inset highlight + outer drop shadow for depth
   Same treatment shared with double-panel below. */
.mg-doudizhu__bid-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 14px 18px;
    background: linear-gradient(180deg,
        rgba(20, 20, 26, 0.92) 0%,
        rgba(10, 10, 14, 0.96) 100%);
    border: 1px solid var(--dz-line-strong);
    border-radius: 12px;
    min-width: 280px;
    box-shadow:
        0 8px 24px rgba(0, 0, 0, 0.55),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.mg-doudizhu__bid-prompt {
    margin: 0;
    color: rgba(255, 255, 255, 0.92);
    font-size: 13px;
    text-align: center;
    font-weight: 500;
    letter-spacing: 0.02em;
}
.mg-doudizhu__bid-buttons {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    justify-content: center;
}
.mg-doudizhu__bid-buttons .mg-btn {
    min-width: 56px;
    font-weight: 600;
}
.mg-doudizhu__bid-buttons .mg-btn:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

/* Doubling panel — same v0.24.1 treatment as bid-panel above */
.mg-doudizhu__double-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 14px 18px;
    background: linear-gradient(180deg,
        rgba(20, 20, 26, 0.92) 0%,
        rgba(10, 10, 14, 0.96) 100%);
    border: 1px solid var(--dz-line-strong);
    border-radius: 12px;
    min-width: 260px;
    box-shadow:
        0 8px 24px rgba(0, 0, 0, 0.55),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.mg-doudizhu__double-prompt {
    margin: 0;
    color: rgba(255, 255, 255, 0.92);
    font-size: 13px;
    text-align: center;
    font-weight: 500;
    letter-spacing: 0.02em;
}
.mg-doudizhu__double-buttons {
    display: flex;
    gap: 8px;
    justify-content: center;
}
.mg-doudizhu__double-buttons .mg-btn {
    min-width: 80px;
    font-weight: 600;
}

/* ============================================================
   Cards — same visual treatment as bigtwo
   ============================================================ */
.mg-doudizhu__card {
    display: inline-flex;
    flex-direction: column;
    width: var(--doudizhu-card-w);
    height: var(--doudizhu-card-h);
    padding: clamp(4px, 0.5vw, 7px);
    background:
        linear-gradient(180deg, var(--doudizhu-card-bg) 0%, #f5efe0 100%);
    border: 1px solid var(--doudizhu-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;
}
.mg-doudizhu__card--red    { color: var(--doudizhu-card-red); }
.mg-doudizhu__card--black  { color: var(--doudizhu-card-black); }
.mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.3);
    font-weight: 700;
    align-self: flex-start;
    letter-spacing: -0.05em;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.mg-doudizhu__card-suit {
    font-size: calc(var(--doudizhu-card-w) * 0.48);
    font-weight: 600;
    align-self: center;
    line-height: 1;
    margin-top: auto;
    margin-bottom: auto;
}

/* Jokers — use the same ivory card body as regular cards, but with
   distinct red/black star colors. Big joker = red ★ (like the colorful
   poker joker), small joker = black ★. The rank "JKR" sits top-left
   matching the rank position on regular cards. */
.mg-doudizhu__card--joker .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.22);
    font-weight: 800;
    letter-spacing: 0;
}
.mg-doudizhu__card--joker-big {
    color: var(--doudizhu-card-red);
}
.mg-doudizhu__card--joker-small {
    color: var(--doudizhu-card-black);
}

/* Mini variant — used in the history strip. Half-size with simpler
   shadow + smaller text. !important on sizing because some user themes
   set min-width / max-width on generic card classes that would stretch
   these mini cards. Mirrors bigtwo's .mg-bigtwo__card--mini pattern. */
.mg-doudizhu__card--mini {
    width:  calc(var(--doudizhu-card-w) * 0.5) !important;
    height: calc(var(--doudizhu-card-h) * 0.5) !important;
    min-width:  calc(var(--doudizhu-card-w) * 0.5);
    max-width:  calc(var(--doudizhu-card-w) * 0.5);
    min-height: calc(var(--doudizhu-card-h) * 0.5);
    max-height: calc(var(--doudizhu-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;
    animation: none;  /* don't replay the play-in animation on history */
}
.mg-doudizhu__card--mini .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.16);
}
.mg-doudizhu__card--mini .mg-doudizhu__card-suit {
    font-size: calc(var(--doudizhu-card-w) * 0.22);
}
.mg-doudizhu__card--mini.mg-doudizhu__card--joker .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.13);
}

/* ============================================================
   Card back — reuses bigtwo's 6 design variants via
   data-mg-cardback attribute. The applyCardback() helper in
   assets/core.js already targets [data-mg-doudizhu] too so the
   user's chosen back applies to both games.
   ============================================================ */
.mg-doudizhu__card-back {
    width: var(--doudizhu-back-w);
    height: var(--doudizhu-back-h);
    border: 1px solid #1a1a1a;
    border-radius: clamp(4px, 0.6vw, 8px);
    background-color: var(--mg-accent);
    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.18);
    flex-shrink: 0;
    position: relative;
    overflow: hidden;
}
/* Variant 1 — hash + spade (DEFAULT) */
.mg-doudizhu[data-mg-cardback="hash-spade"] .mg-doudizhu__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-doudizhu[data-mg-cardback="hash-spade"] .mg-doudizhu__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(--doudizhu-back-w) * 0.4);
    font-weight: 900; line-height: 1;
    opacity: 0.26;
    pointer-events: none;
}
/* Variant 2 — dot grid */
.mg-doudizhu[data-mg-cardback="dot"] .mg-doudizhu__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 — band */
.mg-doudizhu[data-mg-cardback="band"] .mg-doudizhu__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 — diagonal split */
.mg-doudizhu[data-mg-cardback="split"] .mg-doudizhu__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 — checker */
.mg-doudizhu[data-mg-cardback="checker"] .mg-doudizhu__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 + ♠ */
.mg-doudizhu[data-mg-cardback="solid"] .mg-doudizhu__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(--doudizhu-back-w) * 0.5);
    font-weight: 900; line-height: 1;
    opacity: 0.28;
    pointer-events: none;
}
/* Fallback when no attribute set */
.mg-doudizhu:not([data-mg-cardback]) .mg-doudizhu__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-doudizhu:not([data-mg-cardback]) .mg-doudizhu__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(--doudizhu-back-w) * 0.4);
    font-weight: 900; line-height: 1;
    opacity: 0.26;
    pointer-events: none;
}

/* ============================================================
   Human hand — bigtwo-style with hover lift + selected pop-up
   ============================================================ */
.mg-doudizhu__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;
    max-width: calc((var(--doudizhu-card-w) + 6px) * 10);
    margin-left: auto;
    margin-right: auto;
    overflow: visible;
}
.mg-doudizhu__seat-hand--human .mg-doudizhu__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-doudizhu__seat-hand--human .mg-doudizhu__card:hover,
.mg-doudizhu__seat-hand--human .mg-doudizhu__card.is-selected {
    z-index: 2;
}
.mg-doudizhu__seat-hand--human .mg-doudizhu__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-doudizhu__seat-hand--human .mg-doudizhu__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);
    touch-action: pan-x;
}
.mg-doudizhu__seat-hand--human .mg-doudizhu__card.is-selected:hover {
    transform: translateY(-18px);
}
/* Spectator view (we're not seated): no hover lift, no pointer cursor */
.mg-doudizhu__seat-hand--human.is-spectator-view .mg-doudizhu__card {
    cursor: default;
}
.mg-doudizhu__seat-hand--human.is-spectator-view .mg-doudizhu__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(--doudizhu-card-border);
}

/* ============================================================
   Action buttons (below the table)
   ============================================================ */
.mg-doudizhu__actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 16px;
    justify-content: center;
}
.mg-doudizhu__actions .mg-btn {
    min-width: 100px;
    transition: all 180ms ease;
    font-weight: 600;
}
.mg-doudizhu__actions .mg-btn:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}
.mg-doudizhu__hint {
    font-size: 12px;
    color: var(--mg-ink-muted);
    margin-top: 10px;
    text-align: center;
    /* v0.24.6: removed font-style:italic per user request — "最底的提示
       字不要用斜體字". See bigtwo same-version change. */
}

/* ============================================================
   End-game overlay
   ============================================================ */
.mg-doudizhu__end-overlay {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.72);
    z-index: 9000;
    padding: 16px;
    /* v0.24.1: subtle backdrop blur matches bigtwo's overlay feel */
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.mg-doudizhu__end-card {
    background: var(--mg-bg-2);
    border: 1px solid var(--mg-line-strong);
    border-radius: var(--mg-radius, 10px);
    padding: 28px 32px;
    box-shadow: 0 12px 36px rgba(0, 0, 0, 0.6);
    width: 100%;
    max-width: 460px;
    text-align: center;
    /* v0.24.1: allow tall content to scroll if needed (rare; doudizhu
       has more multiplier rows than bigtwo can ever produce). */
    max-height: calc(100vh - 32px);
    overflow-y: auto;
}
.mg-doudizhu__end-title {
    margin: 0 0 6px;
    font-family: var(--mg-display);
    font-size: 22px;
    font-weight: 700;
    color: var(--mg-accent);
}
/* v0.24.1: subtitle (mirrors bigtwo's end-subtitle pattern) */
.mg-doudizhu__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;
}
/* v0.24.1: viewer-self hero block — bigtwo doesn't have this exact
   element but the rationale is doudizhu-specific (single zero-sum
   per-round delta, vs bigtwo's rank-based scoring). Sits above the
   factor list so the user's bottom-line answer is the FIRST thing
   they see, then the breakdown below explains why. */
.mg-doudizhu__end-you {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    margin: 0 auto 18px;
    padding: 14px 20px;
    background: var(--mg-bg);
    border: 1px solid var(--mg-line);
    border-radius: 10px;
    max-width: 240px;
}
.mg-doudizhu__end-you[hidden] { display: none; }
.mg-doudizhu__end-you.is-positive {
    border-color: rgba(78, 194, 125, 0.45);
    background: rgba(78, 194, 125, 0.08);
}
.mg-doudizhu__end-you.is-negative {
    border-color: rgba(214, 105, 95, 0.45);
    background: rgba(214, 105, 95, 0.08);
}
.mg-doudizhu__end-you-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--mg-ink-muted);
    font-weight: 600;
}
.mg-doudizhu__end-you-value {
    font-family: var(--mg-display);
    font-size: 38px;
    font-weight: 700;
    line-height: 1;
    color: var(--mg-ink);
    font-variant-numeric: tabular-nums;
}
.mg-doudizhu__end-you.is-positive .mg-doudizhu__end-you-value { color: #4ec27d; }
.mg-doudizhu__end-you.is-negative .mg-doudizhu__end-you-value { color: #d6695f; }

/* v0.24.1: multiplier factor pills — bigtwo's li-style finishing-order
   adapted for doudizhu's multiplier breakdown. Each pill = one factor
   that contributed to the final score (base, 炸彈, 火箭, spring, 加倍). */
.mg-doudizhu__end-multipliers {
    list-style: none;
    margin: 0 0 18px;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: center;
}
.mg-doudizhu__end-mult-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    /* v0.24.24: zero out any host-theme `li { margin: ... }` rule that
       leaks past our flex `gap: 6px` and visually splits the two pills
       (底分 / 最終倍數) into left-half + right-half columns instead of
       a centred pair. bigtwo's finishing-order li doesn't need this
       because it already sets margin explicitly (vertical stack). */
    margin: 0;
    padding: 6px 12px;
    background: var(--mg-bg);
    border: 1px solid var(--mg-line);
    border-radius: 999px;
    font-size: 12px;
    color: var(--mg-ink);
    line-height: 1.3;
}
.mg-doudizhu__end-mult-pill.is-total {
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent-glow);
    color: var(--mg-accent);
    font-weight: 700;
}
.mg-doudizhu__end-mult-label {
    font-weight: 500;
    color: var(--mg-ink-muted);
}
.mg-doudizhu__end-mult-pill.is-total .mg-doudizhu__end-mult-label {
    color: var(--mg-accent);
}
.mg-doudizhu__end-mult-value {
    font-family: var(--mg-display);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* v0.24.1: per-seat delta cards — bigtwo's .finishing-order li adapted
   for doudizhu's 3-seat layout (with role badge instead of rank). */
.mg-doudizhu__end-summary {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0 0 6px;
    text-align: left;
}
.mg-doudizhu__end-seat-row {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    background: var(--mg-bg);
    border: 1px solid var(--mg-line);
    border-radius: 8px;
    color: var(--mg-ink);
    font-size: 14px;
    line-height: 1.4;
}
.mg-doudizhu__end-seat-row.is-you {
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent-glow);
    font-weight: 700;
}
/* v0.24.11: end-overlay role badge now mirrors the in-match seat-role
   badge exactly (line ~677-720) — solid red gradient for 地主 / solid
   blue gradient for 農民, 12px display-font white text with inset
   highlight + drop shadow. Previously the end-screen used a generic
   uppercase pill (muted gray default, faded gold for landlord) that
   didn't match the in-match treatment at all. User: "結算頁面的 農民
   地主 badge 要和遊戲局內的設計一致". The default state here is
   FARMER (blue) rather than the in-match default "no role yet" — at
   the end of a round every seat HAS a finalized role, so the empty-
   state of the in-match version doesn't apply. Landlord overrides
   default via `.is-landlord` cascade below. */
.mg-doudizhu__end-seat-role {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 38px;
    padding: 3px 10px;
    border-radius: 6px;
    /* 農民 = traditional blue (default — no .is-landlord on row).
       Same gradient + inset highlight as in-match version. */
    background: linear-gradient(180deg, #4a7eb0 0%, #2a5485 100%);
    border: 1px solid #7eaad4;
    color: #fff;
    font-family: var(--mg-display);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    line-height: 1.2;
    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
    box-shadow:
        0 1px 3px rgba(74, 126, 176, 0.35),
        inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.mg-doudizhu__end-seat-row.is-landlord .mg-doudizhu__end-seat-role {
    /* 地主 = traditional red. Identical to in-match `.is-landlord`. */
    background: linear-gradient(180deg, #d64545 0%, #9c2828 100%);
    border-color: #ed7878;
    color: #fff;
    box-shadow:
        0 1px 3px rgba(214, 69, 69, 0.45),
        inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.mg-doudizhu__end-seat-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mg-doudizhu__end-seat-delta {
    font-family: var(--mg-display);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    font-size: 16px;
}
.mg-doudizhu__end-seat-delta.mg-doudizhu__delta-positive { color: #4ec27d; }
.mg-doudizhu__end-seat-delta.mg-doudizhu__delta-negative { color: #d6695f; }

/* v0.24.1: legacy .end-summary-row rules retained below in case any
   stale-callstack render still tries to use addSummaryRow. The new
   renderEndOverlay (v0.24.1) doesn't call it for the main path; the
   defensive function definition stays for safety. */
.mg-doudizhu__end-summary-row {
    display: flex;
    justify-content: space-between;
    padding: 6px 0;
    border-bottom: 1px dashed var(--mg-line);
}
.mg-doudizhu__end-summary-row:last-child {
    border-bottom: none;
}
.mg-doudizhu__end-summary-row.is-total {
    border-top: 1px solid var(--mg-line);
    border-bottom: none;
    margin-top: 6px;
    padding-top: 10px;
    color: var(--mg-ink);
    font-weight: 600;
}
.mg-doudizhu__end-summary-row.is-total .mg-doudizhu__delta-positive { color: #4ec27d; }
.mg-doudizhu__end-summary-row.is-total .mg-doudizhu__delta-negative { color: #d6695f; }
.mg-doudizhu__end-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
    margin-top: 18px;
}

/* ============================================================
   Toast
   ============================================================ */
.mg-doudizhu__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;
}

/* ============================================================
   Mobile (≤900px) — table collapses to single column
   ============================================================ */
@media (max-width: 900px) {
    .mg-doudizhu__table {
        grid-template-columns: 1fr;
        grid-template-rows: auto auto auto auto;
        grid-template-areas:
            "top-left"
            "top-right"
            "center"
            "bottom";
        gap: 8px;
        padding: 14px;
        min-height: 0;
    }
    /* Top opponents collapse to compact horizontal rows: label on
       left, card-back stack on right. Same treatment as bigtwo. */
    .mg-doudizhu__seat--top-left,
    .mg-doudizhu__seat--top-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;
        width: auto;
        align-self: stretch;
        gap: 8px;
    }
    .mg-doudizhu__seat--top-left .mg-doudizhu__seat-hand,
    .mg-doudizhu__seat--top-right .mg-doudizhu__seat-hand {
        flex-direction: row;
        flex-wrap: nowrap;
        min-height: 0;
        flex: 1 1 auto;
        justify-content: flex-end;
        overflow: hidden;
        max-width: 100%;
        min-width: 0;                  /* allow flex item to shrink below
                                           intrinsic content width — without
                                           this the strip refuses to overlap
                                           more and overflows the seat row */
    }
    /* Opponent card-back stack: each back after the first overlaps the
       previous by ~92% so 17 backs collapse to roughly 2× back width.
       v0.23.27 increased overlap from 85% to 92% because at 85% the
       17 visible edges (17 × 0.15 × 42 px = 107 px) plus the final
       full back (42 px) totalled ~149 px — already wider than the
       cramped right half of the seat row on narrow Androids
       (viewport ~360 px ⇒ right half ≈ 160 px after seat-info eats
       45% + gap). At 92% overlap the strip is 17 × 0.08 × 42 + 42
       = ~99 px, comfortably inside even the narrowest layout. */
    .mg-doudizhu__seat--top-left .mg-doudizhu__seat-hand .mg-doudizhu__card-back + .mg-doudizhu__card-back,
    .mg-doudizhu__seat--top-right .mg-doudizhu__seat-hand .mg-doudizhu__card-back + .mg-doudizhu__card-back {
        margin-left: calc(var(--doudizhu-back-w) * -0.92);
    }
    .mg-doudizhu__seat--top-left .mg-doudizhu__seat-info,
    .mg-doudizhu__seat--top-right .mg-doudizhu__seat-info {
        flex-direction: column;
        align-items: flex-start;
        flex-wrap: nowrap;
        gap: 4px;
        min-height: 0;
        flex-shrink: 0;
        max-width: 45%;
    }

    /* HUMAN HAND — fan / overlap layout. Doudizhu hands are 17 cards
       (farmers) or 20 cards (landlord), much larger than bigtwo's 13.
       On mobile a wrapped grid would either overflow horizontally or
       eat enormous vertical space. The standard mobile UX for doudizhu
       apps (Tencent 歡樂鬥地主 et al.) is a single horizontal fan with
       cards overlapping ~60%, showing only the left edge of each card.
       Selected cards lift up vertically (existing `.is-selected` rule
       handles this — they pop above the row via z-index). */
    .mg-doudizhu__seat--bottom {
        max-width: none;
        width: auto;
        padding: 10px 6px 22px 6px;
    }
    .mg-doudizhu__seat-hand--human {
        flex-wrap: nowrap;
        gap: 0;
        justify-content: center;
        padding: 14px 8px 22px;
        max-width: 100%;
        overflow: visible;  /* selected cards lift outside hand box */
        /* Keep min-height generous so the lift doesn't get clipped by
           the parent grid row. */
        min-height: calc(var(--doudizhu-card-h) + 22px);
    }
    /* Negative margin = horizontal overlap. ~58% overlap = ~42% of
       each card's width visible (the rank corner is what users tap).
       The LAST card shows fully. This fits 20 cards in ~340px viewport
       width comfortably. */
    .mg-doudizhu__seat-hand--human .mg-doudizhu__card + .mg-doudizhu__card {
        margin-left: calc(var(--doudizhu-card-w) * -0.58);
    }

    .mg-doudizhu__center {
        min-height: 110px;
        background: rgba(0, 0, 0, 0.3);
        border-radius: 10px;
        padding: 10px;
    }
    /* Bid + double panels narrower on mobile */
    .mg-doudizhu__bid-panel,
    .mg-doudizhu__double-panel {
        min-width: 0;
        width: 100%;
    }
    /* Header buttons (v0.23.14): bigtwo keeps title + buttons inline at
       mobile via `flex-wrap: wrap` on `.mg-header` itself — the previous
       full-width override here was forcing the buttons onto their own row
       even when there was room beside the title. Removing those two rules
       restores the bigtwo behaviour of letting flex-wrap decide naturally,
       which keeps title + Practice + Create Match on one line at typical
       phone widths (~390px) just like image 3 (bigtwo) in the user's
       screenshot. */
    /* PvP seat grid mobile rules moved to their own ≤600px media query
       below — matches bigtwo's collapse breakpoint. At 600–900px the
       3 seat cards remain in a row (each ~225–250px wide), only
       collapsing to a single stacked column on phones. */
    /* v0.24.8: removed `.mg-doudizhu__match-header { gap: 8px; }` and
       `.mg-doudizhu__status { flex-basis: 100%; text-align: left; }`
       overrides here. They forced status text to a new row below the
       Back button on screens ≤900px — wasting the right side of the
       header and making the match-header look like two stacked rows
       (Back btn alone / status alone). Bigtwo has no such override:
       its status stays on the same row at all widths, with the base
       rule's `word-break: break-all` wrapping long text inside the
       status box instead. User: "鬥地主 很容易就分到下一行 bigtwo
       不會的 才能善用右邊的位置". Align doudizhu to bigtwo. */
    /* Lobby list rows: shrink the verb so badge + names get more room */
    .mg-doudizhu__pvp-list-row {
        padding: 10px 12px;
        font-size: 13px;
    }
    .mg-doudizhu__pvp-list-verb {
        font-size: 11px;
    }
    /* End-overlay card: smaller padding so it fits narrow viewports */
    .mg-doudizhu__end-card {
        padding: 20px 18px;
        max-width: 100%;
    }
    .mg-doudizhu__end-title {
        font-size: 18px;
    }
}

/* PvP seat grid — collapse to single column at ≤600px (matches bigtwo's
   `.mg-bigtwo__pvp-seats { grid-template-columns: 1fr }` breakpoint).
   Above 600px the 3 seats stay in a row so the waiting-room reads as a
   compact card row, same visual rhythm as bigtwo's 2-card row. */
@media (max-width: 600px) {
    /* v0.23.14: pixel-match bigtwo @600px behaviour — ONLY collapse the
       grid to a single column. Keep the desktop seat sizing (min-height
       110px, padding 16px, gap 8px, name font 16px) so seats don't shrink
       into tiny strips on phone (user's image-1 vs image-4 comparison:
       doudizhu seats were ~70-80px tall vs bigtwo ~110px+, looking
       cramped). Bigtwo's @600px contains only `grid-template-columns:
       1fr` — match that exactly. */
    .mg-doudizhu__pvp-seats {
        grid-template-columns: 1fr;
    }
}

/* Phones (≤480px) — switch own hand from fan to multi-row wrap.
   v0.23.23: the single-row fan UX inherited from Tencent 歡樂鬥地主
   only works when the row is wide enough to span ≥20 overlapping
   cards. At typical portrait phone widths (360-430px CSS) — Galaxy
   S/Pixel/iPhone 13-15 standard etc. — a 20-card landlord hand was
   overflowing the panel or jammed against the right edge with no
   breathing room. (Earlier v0.23.23 capped this at ≤390 — too
   conservative; phones in the 391-480 range still showed the same
   overflow because the fan is built around ~20 cards × ~16-17px
   visible-edge each, ≈ 320-340 px minimum, before any padding.)
   The wrap layout drops overlap entirely so each card shows fully,
   and lets the row break naturally at the container edge. Other-seat
   hands at the top keep their overlapping back-stack — they're not
   interactive so card edges don't need to be tappable.

   Typical layouts (≈30px panel/page padding eaten before the hand):
     430px viewport, 36px card:  17 cards → 10+7;        20 → 10+10
     412px viewport, 36px card:  17 cards → 9+8 or 10+7; 20 → 10+10 / 9+9+2
     390px viewport, 36px card:  17 cards → 9+8;         20 → 9+9+2
     360px viewport, 32px card:  17 cards → 9+8;         20 → 9+9+2
     320px viewport, 32px card:  17 cards → 7+7+3;       20 → 7+7+6
   Farmer 17-card hand always lands in ≤2 rows on any current phone.
   Landlord 20-card hand may spill to a 3rd short row on the tightest
   viewports — still strictly better than the previous overflow which
   clipped tappable area off the right edge. */
@media (max-width: 480px) {
    .mg-doudizhu {
        /* v0.23.31: settled on FAN OVERLAP layout (single row, cards
           overlap horizontally by ~58 %). User feedback after many
           iterations:
             - 2-row wrap looks ugly with N=10 cards mid-game (last
               row has 1-2 lonely cards)
             - Fan overlap is the standard doudizhu look (Tencent et al.)
             - "Cards bigger" was the only real ask

           Width chosen via clamp(34, 9vw, 46) so the fan auto-fits
           17 (farmer) AND 20 (landlord) cards on every common phone:
             - 360 px viewport → W=34, 20 cards fan = 8.98 × 34 = 305 px
               ≤ 330 px row inner ✓
             - 412 px viewport → W=37, 20 cards = 333 px ≤ 382 ✓
             - 480 px viewport → W=46, 20 cards = 413 px ≤ 460 ✓
           17 cards (farmer) fits even more comfortably at 7.72 × W.

           The actual layout (flex-wrap: nowrap + -58 % negative-margin
           overlap) is inherited from the ≤900 block above. This block
           only sets the variable and adds parent overflow armor. */
        --doudizhu-card-w: clamp(34px, 9vw, 46px);
        --doudizhu-card-h: clamp(48px, 12.6vw, 64px);
    }
    .mg-title { font-size: 20px; }
    .mg-doudizhu__table {
        padding: 10px;
        min-width: 0;                  /* armor: don't grow grid to
                                          intrinsic min-content width */
        overflow-x: hidden;            /* clip overflow if a row of
                                          cards is wider than viewport
                                          (rare on narrowest phones) */
    }
    .mg-doudizhu__actions .mg-btn {
        min-width: 80px;
        padding: 8px 12px;
    }
    /* Parent of the hand — without min-width:0 + overflow-x:hidden,
       Firefox uses the hand's intrinsic content width (= un-overlapped
       sum, e.g. 20 × 46 = 920 px) as the min-content size of this grid
       cell. That forces the grid track to that width, pushing the
       whole game container off-screen to the right. v0.23.29 hit this
       regression. Chrome handles min-content differently and was
       unaffected — this armor makes them behave the same. */
    .mg-doudizhu__seat--bottom {
        min-width: 0;
        overflow-x: hidden;
    }
    /* Each grid cell (top-left, top-right, center, bottom) also needs
       min-width:0 so the parent grid track can shrink to the viewport.
       Without this, Firefox grows the column to fit intrinsic content. */
    .mg-doudizhu__seat--top-left,
    .mg-doudizhu__seat--top-right,
    .mg-doudizhu__center {
        min-width: 0;
        overflow-x: hidden;
    }
    /* Hover-incapable touch devices — kill the lift state that
       lingers after tap and looks like a stuck partial-select. */
    @media (hover: none) {
        .mg-doudizhu__seat-hand--human .mg-doudizhu__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(--doudizhu-card-border);
        }
        .mg-doudizhu__seat-hand--human .mg-doudizhu__card.is-selected:hover {
            transform: translateY(-14px);
            border-color: var(--mg-accent);
        }
    }
}

/* Tiny phones (≤360px) — clamp() floor (34 px) handles the card
   width via the ≤480 block above. No override needed here; left
   as a hook for any future sub-360 tweaks. */
@media (max-width: 360px) {
    /* intentionally empty */
}

/* ============================================================
   v0.23.33  IN-MATCH UI REDESIGN  (cool-neutral · glass)
   ============================================================
   Replaces the v0.23.32 attempt (which leaned warm-ivory cards on
   a deep radial-spotlight felt — visually conflicted). This pass:

   Design language: cool-neutral, frosted-glass panels on a flat
   dark surface — Linear / Vercel / Arc-browser vibe. One accent
   colour only (existing --mg-accent, blue). No casino felt, no
   coloured gradient backdrops, no warm card-stock. Cards read as
   clean paper cards on a dark stage.

   Layout philosophy:
     - DESKTOP (≥901 px) — 3-column grid:
           [ opp-left | stage  | opp-right ]
           [ bottom (own hand) spans 3      ]
       Opponents become tall compact side panels (~190 px wide)
       with a mini card-back stack (5-6 cards, heavily overlapped)
       so the visual "you have hidden cards" reads at a glance,
       but the stack never exceeds the sidebar width.
     - MOBILE (≤900 px) — vertical stack (existing grid stays):
           [ opp-left ]  ← compact horizontal pill row
           [ opp-right]
           [ stage    ]
           [ own hand ]
       Mini back-stack lives at the right of each opponent pill,
       capped at ~84 px wide regardless of card count.

   Hand layout (bottom seat) — UNCHANGED from v0.23.31 (fan
   overlap, single row, ~58% overlap, card width
   clamp(34, 9vw, 46)). Many rounds confirmed this is what
   the user wants. We only refresh the *surrounding* surface.

   To roll back: delete from this comment to EOF. The base layout
   (lines 1-1532) is a working fallback.
   ============================================================ */

.mg-doudizhu__match {
    /* Local design tokens — keep the redesign self-contained so the
       lobby / pvp-list / create modal (which still use base tokens)
       are unaffected. */
    --dz-surface:        rgba(255, 255, 255, 0.04);
    --dz-surface-strong: rgba(255, 255, 255, 0.07);
    --dz-surface-hover:  rgba(255, 255, 255, 0.09);
    --dz-line:           rgba(255, 255, 255, 0.08);
    --dz-line-strong:    rgba(255, 255, 255, 0.14);
    --dz-ink:            rgba(255, 255, 255, 0.95);
    --dz-ink-muted:      rgba(255, 255, 255, 0.62);
    --dz-ink-subtle:     rgba(255, 255, 255, 0.38);
    --dz-radius-lg:      16px;
    --dz-radius:         12px;
    --dz-radius-sm:      8px;
    /* Mini back tile size for opponent-stack visual chips.
       v0.23.34: bumped 22→30 / 30→40 (~36% larger) per user
       "putting all cards bigger" feedback. Still well below the
       full back-card size (42px+) so the strip stays compact. */
    --dz-mini-back-w:    30px;
    --dz-mini-back-h:    40px;
}

/* ============================================================
   Match header — minimal pill row, no debug-strip feel
   ============================================================ */
.mg-doudizhu__match .mg-doudizhu__match-header {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 4px 2px 14px;
    margin-bottom: 6px;
    border-bottom: none;
}
/* v0.23.99: removed "Back to Lobby" button override block here (was
   v0.23.33's --dz-surface pill style with border-radius:999px,
   font-size:13px, padding:6px 12px). User reported the in-match
   button "still not same as bigtwo style" through five fixes
   (v0.23.36/37/38/54/94/99). Bigtwo's back button has ZERO override
   in bigtwo.css — it uses core.css `.mg-btn` directly. To match,
   doudizhu also needs ZERO override. The downstream blocks at
   ~2647 (force-copy with !important) and ~3074 (verbatim copy)
   were both bandaids over THIS block — once it's gone they're
   redundant and only add cascade weight, so they're removed too. */
.mg-doudizhu__match .mg-doudizhu__match-round {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    padding: 5px 12px;
    background: var(--dz-surface);
    border: 1px solid var(--dz-line);
    border-radius: 999px;
    color: var(--dz-ink-muted);
    font-variant-numeric: tabular-nums;
}
/* v0.24.3: removed `.mg-doudizhu__match .mg-doudizhu__status` /
   `:is-your-turn` overrides here. They diverged from bigtwo:
   font-size 13px (vs 14px) and color var(--dz-ink-muted) (vs
   var(--mg-ink-muted)). User asked for cross-game consistency:
   "兩隻game字體和設計上一致?" — so we drop the override entirely
   and let the base `.mg-doudizhu__status` rules (line ~412) apply,
   which are byte-identical to bigtwo's `.mg-bigtwo__status`. */

/* ============================================================
   Table — flat surface, no felt-radial. The "stage" feel comes
   from the trick-area centre frame, not from a coloured backdrop.
   ============================================================ */
.mg-doudizhu__match .mg-doudizhu__table {
    background:
        linear-gradient(180deg,
            rgba(255, 255, 255, 0.015) 0%,
            rgba(0, 0, 0, 0.25) 100%);
    border: 1px solid var(--dz-line);
    border-radius: var(--dz-radius-lg);
    padding: 18px;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.04),
        0 1px 2px rgba(0, 0, 0, 0.35),
        0 8px 24px rgba(0, 0, 0, 0.4);
    /* min-height inherited from base (.mg-doudizhu__table: 480px) on
       desktop; explicitly reset to 0 on mobile in the ≤900 block
       below so stacked rows don't get a weird tall empty area. */
    /* Bump max-width from base 820 → 1040 for the new 3-column layout.
       At 1040 the stage gets ~560 px, opponents 200 px each, plus
       gaps — comfortable for the trick area to breathe. */
    max-width: 1040px;
    /* DESKTOP grid — 3 cols: opponents flank the stage. Bottom hand
       spans full width. Stage column uses minmax(0, 1fr) so it
       can shrink past its intrinsic content if needed. */
    grid-template-columns:
        minmax(180px, 220px)
        minmax(0, 1fr)
        minmax(180px, 220px);
    grid-template-rows: auto auto;
    grid-template-areas:
        "top-left center  top-right"
        "bottom   bottom  bottom";
    gap: 16px;
}

/* ============================================================
   Opponent seats — DESKTOP variant (vertical compact panel)
   ============================================================ */
.mg-doudizhu__match .mg-doudizhu__seat--top-left,
.mg-doudizhu__match .mg-doudizhu__seat--top-right {
    /* Glass panel */
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: 14px;
    background: var(--dz-surface);
    border: 1px solid var(--dz-line);
    border-radius: var(--dz-radius);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    min-height: 0;
    min-width: 0;
    transition:
        border-color 220ms ease,
        background 220ms ease,
        box-shadow 220ms ease;
}
.mg-doudizhu__match .mg-doudizhu__seat--top-left.is-active,
.mg-doudizhu__match .mg-doudizhu__seat--top-right.is-active {
    /* Subtle active treatment — accent border + soft glow.
       NO inset ring (was 0 0 0 1px var(--mg-accent) — looked
       like a thick error outline at warm accents like red). */
    border-color: var(--mg-accent);
    background:
        linear-gradient(180deg,
            var(--mg-accent-soft) 0%,
            var(--dz-surface) 100%);
    box-shadow:
        0 0 18px -6px var(--mg-accent-glow),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.mg-doudizhu__match .mg-doudizhu__seat--top-left.is-finished,
.mg-doudizhu__match .mg-doudizhu__seat--top-right.is-finished {
    opacity: 0.45;
    filter: saturate(0.4);
}

/* Seat-info — name + role + count, stacked vertically on desktop */
.mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-info,
.mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-info {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    min-width: 0;
    min-height: 0;
    flex-wrap: nowrap;
    width: 100%;
    text-shadow: none;
}
.mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-name,
.mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--dz-ink);
    width: 100%;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.3;
}
/* Card count: tabular-nums pill, secondary visual weight */
.mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-count,
.mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-count {
    font-size: 12px;
    font-weight: 600;
    color: var(--dz-ink-muted);
    font-variant-numeric: tabular-nums;
    padding: 0;
    background: none;
    border: none;
    letter-spacing: 0.02em;
}

/* Opponent hand — MINI back stack (replaces the v0.23.32
   "drop the stack entirely" approach). Cards are tiny tiles
   (22 × 30 px) so even 20 of them with 70 % overlap fit a
   ~100 px row. The stack reads as "this player has cards"
   without dominating the panel.

   The base .mg-doudizhu__card-back uses var(--doudizhu-back-w/h).
   We override those locally inside opponent seats so the existing
   card-back markup stays untouched — pure CSS sizing override. */
.mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-hand,
.mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-hand {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: flex-start;
    gap: 0;
    min-height: var(--dz-mini-back-h);
    width: 100%;
    max-width: 100%;
    min-width: 0;
    padding: 0;
    overflow: hidden;
}
.mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-hand .mg-doudizhu__card-back,
.mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-hand .mg-doudizhu__card-back {
    width: var(--dz-mini-back-w);
    height: var(--dz-mini-back-h);
    border-radius: 4px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.4),
        inset 0 1px 0 rgba(255, 255, 255, 0.08);
    flex-shrink: 0;
    flex-grow: 0;
}
/* Heavy overlap: 20 backs × 0.22 visible + 22 = 22 × 4.4 = ~110 px.
   Even with overlap maths, capping the strip width below ensures it
   never exceeds the panel. */
.mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-hand .mg-doudizhu__card-back + .mg-doudizhu__card-back,
.mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-hand .mg-doudizhu__card-back + .mg-doudizhu__card-back {
    margin-left: calc(var(--dz-mini-back-w) * -0.78);
}

/* ============================================================
   Centre — the stage. Glass panel, soft inner glow, the trick
   cards float here as the focal point.
   ============================================================ */
.mg-doudizhu__match .mg-doudizhu__center {
    background: var(--dz-surface);
    border: 1px solid var(--dz-line);
    border-radius: var(--dz-radius);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    padding: 18px 16px;
    gap: 14px;
    min-height: 200px;
    min-width: 0;
    position: relative;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.04);
}

/* Hole cards strip — small caps label, cards centred */
.mg-doudizhu__match .mg-doudizhu__hole-label {
    font-size: 10px;
    color: var(--dz-ink-subtle);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-weight: 700;
}

/* Trick area — generous breathing room. Drop-shadow on cards
   gives the "playing on the table" feel without a coloured
   spotlight backdrop. */
.mg-doudizhu__match .mg-doudizhu__trick {
    min-height: 90px;
    padding: 8px 4px;
}
.mg-doudizhu__match .mg-doudizhu__trick .mg-doudizhu__card {
    box-shadow:
        0 6px 16px rgba(0, 0, 0, 0.45),
        0 2px 4px rgba(0, 0, 0, 0.25),
        inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

/* History strip — quieter than v0.23.32 */
.mg-doudizhu__match .mg-doudizhu__history {
    opacity: 0.7;
}
.mg-doudizhu__match .mg-doudizhu__history-label {
    color: var(--dz-ink-subtle);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* ============================================================
   Bid / Claim / Rob / Doubling panels — modern dark treatment

   v0.24.16: replaced the var(--dz-surface-strong) background
   (rgba(255,255,255,0.07)) with a deep gradient + red-accent top
   hairline. The translucent-white bg read as washed-out medium grey
   over the carbon table — user feedback: "斗地主叫人加倍 叫地主
   叫分 這個框的灰色背景不好看 也可能太淺色了 改得現代一些".

   New treatment mirrors the end-overlay card (var(--mg-bg-2) +
   var(--mg-line-strong)) for visual continuity, adds a 1px crimson
   top edge tied to var(--mg-accent) so the panel reads as part of
   the game theme rather than a stock dialog, and bumps the prompt
   text size + weight for a tighter "decision moment" feel.
   ============================================================ */
.mg-doudizhu__match .mg-doudizhu__bid-panel,
.mg-doudizhu__match .mg-doudizhu__double-panel {
    background:
        linear-gradient(180deg,
            color-mix(in srgb, var(--mg-bg-2) 96%, var(--mg-accent) 4%) 0%,
            var(--mg-bg-2) 100%);
    border: 1px solid var(--mg-line-strong);
    border-top: 1px solid var(--mg-accent);
    border-radius: var(--dz-radius);
    padding: 18px 20px 16px;
    min-width: 0;
    width: 100%;
    max-width: 360px;
    box-shadow:
        0 10px 28px rgba(0, 0, 0, 0.55),
        0 0 0 1px rgba(0, 0, 0, 0.4),
        inset 0 1px 0 rgba(255, 255, 255, 0.04);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
}
/* Fallback for browsers without color-mix() — Safari < 16.4 etc.
   Skipped the tinted top stop; pure --mg-bg-2 still reads modern. */
@supports not (background: color-mix(in srgb, red, blue)) {
    .mg-doudizhu__match .mg-doudizhu__bid-panel,
    .mg-doudizhu__match .mg-doudizhu__double-panel {
        background: var(--mg-bg-2);
    }
}
.mg-doudizhu__match .mg-doudizhu__bid-prompt,
.mg-doudizhu__match .mg-doudizhu__double-prompt {
    font-size: 14px;
    color: var(--dz-ink);
    margin: 0 0 14px;
    text-align: center;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.mg-doudizhu__match .mg-doudizhu__bid-buttons,
.mg-doudizhu__match .mg-doudizhu__double-buttons {
    display: flex;
    gap: 8px;
    justify-content: center;
    flex-wrap: wrap;
}
/* v0.23.34: stripped the custom dark-glass overrides on these
   buttons. They now inherit the base .mg-btn styling (Cubic-11
   retro pulse + accent outlined glow) — same look as bigtwo's
   buttons + the action buttons below. Only sizing tweaks remain. */
.mg-doudizhu__match .mg-doudizhu__bid-buttons .mg-btn,
.mg-doudizhu__match .mg-doudizhu__double-buttons .mg-btn {
    min-width: 64px;
    font-weight: 600;
}

/* ============================================================
   Bottom seat — own hand container
   ============================================================ */
.mg-doudizhu__match .mg-doudizhu__seat--bottom {
    background: var(--dz-surface);
    border: 1px solid var(--dz-line);
    border-radius: var(--dz-radius);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    padding: 10px 14px 20px;
    /* Cap the hand panel so on desktop it sits as a clean band
       in the lower third, not a 1000-px-wide bar. The base rule
       (line 632) caps it via `calc((card-w + 6) * 9 + 24)` which
       only makes sense for the fan layout's narrow phone card. On
       desktop where card-w can hit 64 px, we want a comfortable
       640 px band — wide enough that the fan reads well, narrow
       enough to feel anchored. */
    max-width: 640px;
    width: 100%;
    margin-left: auto;
    margin-right: auto;
    min-width: 0;
    justify-self: center;
    transition:
        border-color 220ms ease,
        box-shadow 220ms ease,
        background 220ms ease;
}
.mg-doudizhu__match .mg-doudizhu__seat--bottom.is-active {
    /* Match the opponents' subtle active treatment — no thick
       inset ring. The accent-border + soft glow are enough signal. */
    border-color: var(--mg-accent);
    background:
        linear-gradient(180deg,
            var(--mg-accent-soft) 0%,
            var(--dz-surface) 100%);
    box-shadow:
        0 0 24px -8px var(--mg-accent-glow),
        inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.mg-doudizhu__match .mg-doudizhu__seat--bottom .mg-doudizhu__seat-info {
    justify-content: center;
    gap: 10px;
    margin-bottom: 4px;
    text-shadow: none;
}
.mg-doudizhu__match .mg-doudizhu__seat--bottom .mg-doudizhu__seat-name {
    color: var(--dz-ink);
    font-weight: 600;
    font-size: 13px;
}
.mg-doudizhu__match .mg-doudizhu__seat--bottom .mg-doudizhu__seat-count {
    color: var(--dz-ink-muted);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

/* ============================================================
   Card body — clean white, minimal border. Replaces the warm
   ivory gradient from v0.23.32 (which clashed with the dark
   cool surface). White faces on a dark stage = high contrast,
   poker-clean readability.
   ============================================================ */
.mg-doudizhu__match .mg-doudizhu__card {
    background: #fafafa;
    border: 1px solid rgba(0, 0, 0, 0.12);
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.3),
        0 4px 8px rgba(0, 0, 0, 0.18);
    border-radius: 6px;
}

/* Selected card — accent border + lift. Border colour is the
   primary signal (cheap to render), the lift is the secondary
   confirmation. */
.mg-doudizhu__match .mg-doudizhu__seat-hand--human .mg-doudizhu__card.is-selected {
    transform: translateY(-16px);
    border-color: var(--mg-accent);
    border-width: 2px;
    box-shadow:
        0 12px 24px rgba(0, 0, 0, 0.45),
        0 0 0 1px var(--mg-accent),
        0 0 16px var(--mg-accent-glow);
}

/* ============================================================
   Action button bar — v0.23.34 redesign (bigtwo-style natural-
   width, centered, wrap-on-overflow) lives at the very end of
   this file so it wins over the older v0.23.33 stretch-row.
   Search for "Action buttons — bigtwo style" below.
   ============================================================ */

/* Hint text — subtle, doesn't compete */
.mg-doudizhu .mg-doudizhu__hint {
    text-align: center;
    color: var(--dz-ink-subtle);
    font-size: 12px;
    margin: 8px auto 0;
    max-width: 420px;
    line-height: 1.5;
}

/* ============================================================
   Responsive — MOBILE (≤900) overrides
   ============================================================ */
@media (max-width: 900px) {
    .mg-doudizhu__match .mg-doudizhu__table {
        /* Revert to single-column stacked grid on mobile. The base
           ≤900 rule already sets these, but we re-state them here
           so source-order wins over our desktop 3-col definition. */
        grid-template-columns: 1fr;
        grid-template-rows: auto auto auto auto;
        grid-template-areas:
            "top-left"
            "top-right"
            "center"
            "bottom";
        padding: 12px;
        gap: 10px;
        min-height: 0;
        max-width: none;
    }

    /* Opponent seats — horizontal pill row on mobile */
    .mg-doudizhu__match .mg-doudizhu__seat--top-left,
    .mg-doudizhu__match .mg-doudizhu__seat--top-right {
        flex-direction: row;
        align-items: center;
        gap: 10px;
        padding: 10px 14px;
        min-height: 52px;
    }
    .mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-info,
    .mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-info {
        flex-direction: column;
        align-items: flex-start;
        gap: 4px;
        flex: 1 1 auto;
        max-width: 50%;
    }
    .mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-hand,
    .mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-hand {
        flex: 0 1 auto;
        justify-content: flex-end;
        margin-left: auto;
        /* v0.23.34: cap bumped 100 → 150 to fit the bigger 30 px
           mini-backs (20 backs × 0.22 visible × 30 + 30 = ~156).
           overflow: hidden (set on the seat-hand rule above) still
           clips any spillover on the very narrowest phones. */
        max-width: 150px;
    }

    /* Centre — slightly tighter padding on mobile */
    .mg-doudizhu__match .mg-doudizhu__center {
        padding: 14px 10px;
        min-height: 140px;
    }

    /* Bottom hand — full width on mobile (no 640 cap) */
    .mg-doudizhu__match .mg-doudizhu__seat--bottom {
        max-width: none;
    }
}

/* ≤480 — keep the existing fan-overlap card-width clamp
   (defined in the base @media (max-width: 480px) block at
   line ~1451). No card-size override needed here; we only
   tighten padding so the hand has more room. */
@media (max-width: 480px) {
    .mg-doudizhu__match .mg-doudizhu__seat--bottom {
        padding: 8px 8px 18px;
    }
    .mg-doudizhu__match .mg-doudizhu__seat--top-left,
    .mg-doudizhu__match .mg-doudizhu__seat--top-right {
        padding: 8px 12px;
        min-height: 48px;
    }
    .mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-name,
    .mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-name {
        font-size: 13px;
    }
    .mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-hand,
    .mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-hand {
        max-width: 120px;
    }
}

/* ============================================================
   v0.23.34 — Hand 2-row wrap + bigger cards + bigtwo-style actions
   ============================================================
   User feedback after seeing v0.23.33 screenshots:
     - "卡牌真的有點多 ... 可以以現在的排牌方式 一張疊一張 但
        分成可能兩行 同時將對手的牌 及自己的牌放大一些"
     - "最下方出牌pass清除按鈕 請務必依照鋤大d的做法"

   Three changes:
     1. Own hand: keep the overlap style, but WRAP to 2 rows on
        mobile, and bump card width 35-46 → 40-48 so cards feel
        larger and easier to tap.
     2. Mini back stack on opponents already bumped 22→30 in the
        token block above.
     3. Action buttons revert to bigtwo's natural-width centered
        layout (flex-wrap: wrap + min-width: 100px), not the
        full-width stretched row I had in v0.23.33.

   The "wrap-with-overlap" trick uses padding-left on the hand
   container to compensate for the negative margin on row-2's
   first card. Without it, row-2's first card would render with
   margin-left: -X relative to a non-existent predecessor and
   overflow the container left edge. */

/* --- 1. Hand wraps to 2 rows on mobile, with bigger cards --- */
@media (max-width: 900px) {
    /* Bump card variable so each card is ~48 px on a typical
       phone. clamp(40, 11vw, 48) → 360 vp = 40, 412 vp = 45,
       480+ vp = 48 (cap). */
    .mg-doudizhu__match {
        --doudizhu-card-w: clamp(40px, 11vw, 48px);
        --doudizhu-card-h: clamp(56px, 15.4vw, 68px);
    }

    /* Hand container: allow wrapping, keep cards overlapped via
       negative margin on .__card + .__card. Compensate the
       row-2-first-card overhang with padding-left equal to the
       overlap amount, so the wrapped row starts cleanly at the
       container edge. */
    .mg-doudizhu__match .mg-doudizhu__seat-hand--human {
        flex-wrap: wrap;
        row-gap: 22px;
        column-gap: 0;
        align-content: flex-start;
        justify-content: center;
        /* padding-left compensates the negative margin of the
           first card on each wrapped row (the CSS adjacent-
           sibling selector doesn't know about row boundaries,
           so row 2's first card also gets margin-left: -X). */
        padding-top: 18px;
        padding-bottom: 22px;
        padding-left: calc(var(--doudizhu-card-w) * 0.25);
        padding-right: 8px;
        /* min-height for two rows of cards plus row-gap plus
           selected-card lift (16 px). */
        min-height: calc(var(--doudizhu-card-h) * 2 + 22px + 22px);
    }

    /* Overlap: -25% (was -58% single-row fan). At 48 × 0.25 = 12 px
       overlap, 9 cards per row consume 9×48 - 8×12 = 336 px which
       just fits a ~340 px row inner. 10th card wraps. 17 cards
       → 9 + 8 (two clean rows). 20 cards → 9 + 9 + 2 (the trailing
       row is short, acceptable — the user said "可能兩行" expecting
       this for the landlord case). */
    .mg-doudizhu__match .mg-doudizhu__seat-hand--human .mg-doudizhu__card + .mg-doudizhu__card {
        margin-left: calc(var(--doudizhu-card-w) * -0.25);
    }
}

/* On desktop (>900 px) the hand stays single-row by default
   — the base ≤900 wrap rule doesn't apply, so flex-wrap is the
   inherited default (nowrap from base line 735). Card-w on
   desktop comes from base clamp(36, 4.0vw, 64). No override. */
@media (min-width: 901px) {
    .mg-doudizhu__match {
        /* Keep base clamp(36px, 4.0vw, 64px) — at 1024 vp = 40,
           1280 vp = 51, 1600 vp = 64. Good range. No override. */
    }
    .mg-doudizhu__match .mg-doudizhu__seat-hand--human {
        /* Reset any padding-left from the mobile rule (in case
           a desktop viewport is resized down then up). */
        padding-left: 0;
    }
}

/* --- 2. Action buttons — bigtwo style (natural width, centered) --- */

/* Bigtwo's `.mg-bigtwo__actions` pattern (line 917 of bigtwo.css):
       display: flex; gap: 10px; flex-wrap: wrap;
       margin-top: 16px; justify-content: center;
   plus per-button min-width: 100. We do exactly the same — only
   layout, not button visuals. The base `.mg-btn` (and
   `.mg-btn--primary`) styling from core.css then comes through
   naturally — same Cubic-11 retro pulse + accent glow that bigtwo
   buttons have. */
.mg-doudizhu .mg-doudizhu__actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    margin: 16px auto 8px;
    /* No max-width cap — bigtwo doesn't have one; centered flex
       handles centering. */
    max-width: none;
    width: auto;
    padding: 0 8px;
    justify-content: center;
}
.mg-doudizhu .mg-doudizhu__actions .mg-btn {
    /* Match bigtwo's per-button rule — min-width + transition.
       Everything else (background, border, color, font, shadows,
       pulse animation) inherits from core.css base .mg-btn. */
    min-width: 100px;
    font-weight: 600;
}

/* ============================================================
   END v0.23.34 additions
   ============================================================ */

/* ============================================================
   v0.23.35  CARD-SIZE CONSISTENCY + DESKTOP OPP PANEL HEIGHT
   ============================================================
   User feedback after seeing v0.23.34 in play:
     - "自己的手牌設計非常好,不需要更動" — own hand is correct
     - "地主牌、對方的牌背、及上一手的牌、和我的手牌大小不一致,
        可以使用同樣大小,我在鋤大D應該也是這樣的"
       → hole cards, opponent backs, and history strip should be
         the same size as the own-hand cards (bigtwo precedent:
         `--bigtwo-back-w: var(--bigtwo-card-w)` at line 40 of
         bigtwo.css — opponent backs ARE same size as face cards)
     - "電腦view 其他player的box下方太多空位 看起來不舒服"
       → desktop opponent panels stretch to match center cell's
         height, leaving empty space below the back stack

   Four targeted changes, all scoped inside .mg-doudizhu__match
   so the lobby / pvp-list views remain untouched:
   ============================================================ */

/* --- 1. Hole cards (地主牌) — full size, no 0.85× shrink ----- */
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card {
    width: var(--doudizhu-card-w);
    height: var(--doudizhu-card-h);
}
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card-back {
    width: var(--doudizhu-back-w);
    height: var(--doudizhu-back-h);
}
.mg-doudizhu__match .mg-doudizhu__hole-cards {
    min-height: var(--doudizhu-card-h);
}

/* --- 2. History strip (上一手) — full-size cards -------------
   The mini class is added by JS (doudizhu.js:1258). Rather than
   tear out the JS class, override its sizing inside the match
   view so the cards visually match the hand. Font-sizes scaled
   from the original mini's 0.16 / 0.22 ratios back up to the
   full-card ratios (0.30 rank, 0.48 suit — matching base CSS
   line 920 / 928). */
.mg-doudizhu__match .mg-doudizhu__history-cards .mg-doudizhu__card--mini {
    width:  var(--doudizhu-card-w) !important;
    height: var(--doudizhu-card-h) !important;
    min-width:  var(--doudizhu-card-w);
    max-width:  var(--doudizhu-card-w);
    min-height: var(--doudizhu-card-h);
    max-height: var(--doudizhu-card-h);
    padding: clamp(4px, 0.5vw, 7px);
    border-radius: clamp(4px, 0.6vw, 8px);
}
.mg-doudizhu__match .mg-doudizhu__history-cards .mg-doudizhu__card--mini .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.30);
}
.mg-doudizhu__match .mg-doudizhu__history-cards .mg-doudizhu__card--mini .mg-doudizhu__card-suit {
    font-size: calc(var(--doudizhu-card-w) * 0.48);
}
.mg-doudizhu__match .mg-doudizhu__history-cards .mg-doudizhu__card--mini.mg-doudizhu__card--joker .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.22);
}
/* Loosen the history pill to accommodate the bigger cards */
.mg-doudizhu__match .mg-doudizhu__history {
    padding: 6px 12px;
    gap: 10px;
}
.mg-doudizhu__match .mg-doudizhu__history-cards {
    gap: 3px;
    flex-wrap: wrap;
    justify-content: center;
}

/* --- 3. Opponent card-backs — match own-hand size ------------
   v0.23.34 had a separate --dz-mini-back-w/h pair (30/40 px).
   We retire those and point the mini-back rules at the same
   variables as the own hand uses. This brings doudizhu in line
   with bigtwo's "back size === face card size" convention.

   With cards now ~45 px on mobile, 17 backs at -0.78 overlap
   would be 17×0.22×45 + 45 = 213 px — too wide for the 150 px
   mobile cap. We crank overlap to -0.92 so the strip becomes
   17×0.08×45 + 45 = ~106 px and fits comfortably. Same maths
   on desktop @ 64 px card: 17×0.08×64 + 64 = ~151 px, fits
   the 180-220 px desktop sidebar. */
.mg-doudizhu__match {
    /* Override the v0.23.34 mini-back tokens to share the
       own-hand card variable. Doing it here (cascade-late)
       keeps the redesign block self-contained. */
    --dz-mini-back-w: var(--doudizhu-card-w);
    --dz-mini-back-h: var(--doudizhu-card-h);
}
.mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-hand .mg-doudizhu__card-back + .mg-doudizhu__card-back,
.mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-hand .mg-doudizhu__card-back + .mg-doudizhu__card-back {
    margin-left: calc(var(--dz-mini-back-w) * -0.92);
}
/* Update the seat-hand height-floor so the larger backs aren't
   clipped vertically. The base ≤900 / ≤480 rules cap horizontal
   max-width at 150/120 px — those caps stay, the strip just
   gets denser overlap to fit. */
.mg-doudizhu__match .mg-doudizhu__seat--top-left .mg-doudizhu__seat-hand,
.mg-doudizhu__match .mg-doudizhu__seat--top-right .mg-doudizhu__seat-hand {
    min-height: var(--dz-mini-back-h);
}

/* --- 4. Desktop opp panels — don't stretch to grid row -------
   The grid row sized to fit the tallest cell (the center stage
   with hole cards + history + bid panels). Without an align-
   self override, opponent panels grow to match — leaving a
   large empty band below their back-stack. align-self: start
   pins each panel to the top of its grid row, so the panel is
   only as tall as its content. The empty grid area below is
   neutral table felt, not a hollow panel. */
@media (min-width: 901px) {
    .mg-doudizhu__match .mg-doudizhu__seat--top-left,
    .mg-doudizhu__match .mg-doudizhu__seat--top-right {
        align-self: start;
    }
}

/* ============================================================
   END v0.23.35
   ============================================================ */

/* ============================================================
   v0.23.36  HOLE-SHRINK + OPP CENTER + HEADER FOLLOWS BIGTWO
   ============================================================
   User feedback after seeing v0.23.35:
     - "其他這兩個玩家的項目，整個對準中間的出牌區而置中…
        防止中間如太多東西，把左右拉空了"
       → desktop opponent panels should align CENTER with the
         trick area, not top (which left big empty space below)
     - "地主牌可以較小，更多只是一個提示"
       → hole cards (bumped to 1× in v0.23.35) are too big,
         user now says they should be smaller — they're a hint,
         not the focal point. We go 0.55× — clearly secondary.
     - "最上方的回到大廳button，header的東西，完全follow bigtwo"
       → header back-button + match-round were custom pill-styled
         in v0.23.33; remove the custom styling so the back button
         falls back to the default .mg-btn (matches bigtwo's look).
         Match-round keeps a minimal indicator but loses the
         heavy pill chrome.

   Three targeted changes, scoped inside .mg-doudizhu__match.
   These supersede the corresponding rules earlier in this file.
   ============================================================ */

/* --- 1. Hole cards (地主牌) — SECONDARY size, ~0.55× of hand --
   Supersedes v0.23.35 #1 (which set 1× same as hand). User said
   the cards were too prominent — they're a "hint", not focal. At
   0.55× of card-w (e.g. 45 → 25 px mobile, 64 → 35 px desktop),
   they read as informational icons sitting above the trick area. */
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card {
    width:  calc(var(--doudizhu-card-w) * 0.55);
    height: calc(var(--doudizhu-card-h) * 0.55);
    padding: 3px;
    border-radius: 4px;
}
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card-back {
    width:  calc(var(--doudizhu-back-w) * 0.55);
    height: calc(var(--doudizhu-back-h) * 0.55);
    border-radius: 4px;
}
.mg-doudizhu__match .mg-doudizhu__hole-cards {
    gap: 3px;
    min-height: calc(var(--doudizhu-card-h) * 0.55);
}
/* Shrink rank/suit glyphs proportionally so they don't crowd the
   tiny card body. Same 0.55× scale applied to font-sizes that
   reference the parent card width. */
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.55 * 0.32);
}
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card-suit {
    font-size: calc(var(--doudizhu-card-w) * 0.55 * 0.50);
}
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card--joker .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.55 * 0.24);
}

/* --- 2. Desktop opponent panels — VERTICALLY CENTER ----------
   Supersedes v0.23.35 #4 (align-self: start). With smaller hole
   cards (#1 above) the center cell is shorter, but it still has
   trick area + bid panel taking vertical space. Centering the
   opponent panels makes them visually align with the trick area
   itself — they sit beside it like flanking commentators rather
   than perched at the top with a blank band below. */
@media (min-width: 901px) {
    .mg-doudizhu__match .mg-doudizhu__seat--top-left,
    .mg-doudizhu__match .mg-doudizhu__seat--top-right {
        align-self: center;
    }
}

/* --- 3. Match header — follow bigtwo exactly -----------------
   The v0.23.33 redesign block (line ~1596) gave the back button
   a custom pill style (--dz-surface, rounded 999px, muted color)
   and the match-round indicator a heavy pill-badge treatment.
   Bigtwo (bigtwo.css line 205+) keeps it minimal: default .mg-btn
   for back button, no special round indicator (doudizhu has one,
   we just tone it down). Status div is already bigtwo-shaped.

   Override: minimise the match-round badge to a near-invisible meta
   string (so the header reads as: [Back btn] [#1] [status… ]).
   v0.23.99: removed the .mg-btn:first-child revert rules that were
   here — block 1 (the pill style they were reverting) is gone, so
   nothing to revert. */
.mg-doudizhu__match .mg-doudizhu__match-round {
    /* Minimal meta — no pill chrome, no border, no background.
       Just sits inline like a chapter marker. */
    background: none;
    border: none;
    border-radius: 0;
    padding: 0;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--dz-ink-subtle);
}

/* ============================================================
   END v0.23.36
   ============================================================ */

/* ============================================================
   v0.23.37  HOLE-SIZE TUNE + RESTORE BACK-BTN PILL
   ============================================================
   User feedback after v0.23.36:
     - "地主牌也太小了" — 0.55× went too far the other way
     - "回到大廳的按鈕超奇怪" — reverting back-btn to default
       .mg-btn (which has the retro neon-pulse animation from
       core.css) clashed with the cool-neutral redesign. The
       bigtwo precedent is fine for bigtwo's UI but reads as
       out of place inside this dark glass surface.

   Resolution:
     - Hole cards: 0.55 → 0.75 (still a hint, not the focal
       point, but big enough to actually read the rank/suit
       glyphs from a normal viewing distance).
     - Back-button: revert v0.23.36 #3 — restore the v0.23.33
       pill style (subtle surface bg + rounded). The match-
       round badge stays minimal (v0.23.36 #3 second half).
   ============================================================ */

/* --- 1. Hole cards — 0.75× compromise size ------------------- */
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card {
    width:  calc(var(--doudizhu-card-w) * 0.75);
    height: calc(var(--doudizhu-card-h) * 0.75);
    padding: 4px;
    border-radius: 5px;
}
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card-back {
    width:  calc(var(--doudizhu-back-w) * 0.75);
    height: calc(var(--doudizhu-back-h) * 0.75);
    border-radius: 5px;
}
.mg-doudizhu__match .mg-doudizhu__hole-cards {
    gap: 4px;
    min-height: calc(var(--doudizhu-card-h) * 0.75);
}
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.75 * 0.32);
}
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card-suit {
    font-size: calc(var(--doudizhu-card-w) * 0.75 * 0.50);
}
.mg-doudizhu__match .mg-doudizhu__hole-cards .mg-doudizhu__card--joker .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.75 * 0.24);
}

/* --- 2. Back button ---------------------------------------------
   v0.23.94: deleted the v0.23.33 / v0.23.91 / v0.23.92 overrides
   for `.mg-doudizhu__match-header > .mg-btn:first-child`. They
   layered:
     - v0.23.33 "quiet pill" idle (surface bg, thin grey rim, no
       animation) to differentiate doudizhu's cool-neutral glass UI
       from the core.css retro arcade look
     - v0.23.91 hover override re-adding the pulse animation (since
       v0.23.33 had killed it idle, hover had no glow)
     - v0.23.92 stronger near-opaque white border + 0.45 alpha halo
       to make the glow visible under prefers-reduced-motion

   User v0.23.94: "白光有了 但白边還在 其實這個button和鋤大D的那一
   個要一樣". Bigtwo's back-to-lobby button uses the default `.mg-btn`
   straight from core.css (no override) — idle has a 1.5px grey
   `--mg-line-strong` border, hover shifts border to `--mg-ink`
   white + breathing pulse animation. The v0.23.92 alpha of 0.85
   made doudizhu's border read as a hard white rim around the
   glow rather than a soft lit edge fading into it; bigtwo doesn't
   have that "rim then halo" two-stage look.

   Reverting to default removes the dedicated override entirely so
   doudizhu and bigtwo render the back-to-lobby identically (modulo
   any future core.css changes — they'll affect both together). The
   "cool-neutral" idle look (which v0.23.33 was trying to preserve)
   was a designer-side concern that the user has now explicitly
   overridden. */


/* The reclaim button (.mg-doudizhu__reclaim-btn / .mg-btn--primary)
   inherits the core.css primary style — accent fill, glow, pulse.
   In this redesign it dominates the header on its own row. Tone
   it down to fit the surface: quieter accent border + soft fill,
   no pulse animation. Still distinguishable as the primary
   action (accent color), just not screaming. */
.mg-doudizhu__match .mg-doudizhu__match-header .mg-doudizhu__reclaim-btn {
    background: var(--mg-accent-soft) !important;
    border: 1px solid var(--mg-accent) !important;
    color: var(--mg-accent) !important;
    padding: 6px 14px !important;
    border-radius: 999px !important;
    font-size: 13px !important;
    font-weight: 600 !important;
    letter-spacing: 0 !important;
    text-transform: none !important;
    animation: none !important;
    box-shadow: 0 0 12px -4px var(--mg-accent-glow) !important;
}
.mg-doudizhu__match .mg-doudizhu__match-header .mg-doudizhu__reclaim-btn:hover {
    background: var(--mg-accent) !important;
    color: var(--mg-bg, #1c1c1e) !important;
}

/* ============================================================
   END v0.23.37
   ============================================================ */

/* ============================================================
   v0.23.38  HISTORY MINI + NO HOVER-JUMP + BACK-BTN = BIGTWO
   ============================================================
   User feedback after v0.23.37:
     - "上一手的那個item 請也跟隨big two 也是比較小的"
       → Revert v0.23.35 #2 — history cards back to small (0.5×
         via the existing .mg-doudizhu__card--mini class), plus
         overlap for many-card plays (鬥地主 can play 8+ cards
         in a 飛機帶翅膀, the strip can't show them flat).
     - "pc hover住卡牌 會上下跳動"
       → The base :hover translateY(-6px) lift looks playful on
         touch (no persistent hover) but obnoxious on desktop
         where the mouse hovers over cards while reading. Kill
         the lift, replace with a subtle border-glow feedback.
     - "回到大廳 button跟bigtwo!!!" (with 3 exclamation marks)
       → My v0.23.36 used `revert` which sent the button to
         user-agent default (gray browser button — that was the
         "超奇怪" reaction). v0.23.37 went the other way with a
         custom pill. Both wrong. The correct interpretation:
         render EXACTLY as bigtwo renders — bigtwo uses the
         shared core.css base `.mg-btn` (1.5px solid border,
         transparent bg, uppercase tracking, retro pulse on
         hover). Force-apply those values explicitly so user's
         v0.23.33 pill override is overridden.
   ============================================================ */

/* --- 1. History strip — revert to small/mini + overlap ------- */
/* Revert v0.23.35's full-size override. Restore base mini
   (0.5×) sizing — that's what bigtwo's history strip uses too.
   The .mg-doudizhu__card--mini class is added by JS at
   doudizhu.js:1258, base sizing rule is at css:956. Just don't
   override it any more. */
.mg-doudizhu__match .mg-doudizhu__history-cards .mg-doudizhu__card--mini {
    /* Reset v0.23.35 #2 — back to base mini. !important here
       counters the v0.23.35 !important rules earlier in this
       file. Values match the base .mg-doudizhu__card--mini at
       css line 956-979. */
    width:  calc(var(--doudizhu-card-w) * 0.5) !important;
    height: calc(var(--doudizhu-card-h) * 0.5) !important;
    min-width:  calc(var(--doudizhu-card-w) * 0.5) !important;
    max-width:  calc(var(--doudizhu-card-w) * 0.5) !important;
    min-height: calc(var(--doudizhu-card-h) * 0.5) !important;
    max-height: calc(var(--doudizhu-card-h) * 0.5) !important;
    padding: 2px !important;
    border-radius: 3px !important;
}
.mg-doudizhu__match .mg-doudizhu__history-cards .mg-doudizhu__card--mini .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.16);
}
.mg-doudizhu__match .mg-doudizhu__history-cards .mg-doudizhu__card--mini .mg-doudizhu__card-suit {
    font-size: calc(var(--doudizhu-card-w) * 0.22);
}
.mg-doudizhu__match .mg-doudizhu__history-cards .mg-doudizhu__card--mini.mg-doudizhu__card--joker .mg-doudizhu__card-rank {
    font-size: calc(var(--doudizhu-card-w) * 0.13);
}
/* History pill — base padding/gap (v0.23.35 had expanded these
   for the bigger cards; now reset). */
.mg-doudizhu__match .mg-doudizhu__history {
    padding: 4px 10px;
    gap: 8px;
}
/* Many-card plays (飛機帶翅膀 8-16 cards, four-with-2-pairs 8
   cards) would overflow the strip flat. Apply negative margin
   so consecutive cards overlap ~40% — keeps the strip a tidy
   pill even with long combos. First card no margin. */
.mg-doudizhu__match .mg-doudizhu__history-cards {
    gap: 0;
    flex-wrap: nowrap;
    justify-content: center;
}
.mg-doudizhu__match .mg-doudizhu__history-cards .mg-doudizhu__card--mini + .mg-doudizhu__card--mini {
    margin-left: calc(var(--doudizhu-card-w) * 0.5 * -0.40);
}

/* --- 2. Desktop hover — no jump, glow instead ----------------
   The base rule `:hover { transform: translateY(-6px) }` is set
   at css:1115. It lifts the card 6px on hover. On touch this is
   fine (briefly seen on tap, then released). On desktop the
   mouse hovers persistently, so every cursor sweep over the hand
   bounces 17 cards in turn — distracting + nausea-inducing.

   Replace with a brightness/border-glow effect that signals
   "this is interactive" without moving anything. Selected state
   (-14 px lift) is unaffected — only the hover state. */
@media (hover: hover) and (pointer: fine) {
    .mg-doudizhu__match .mg-doudizhu__seat-hand--human .mg-doudizhu__card:hover {
        transform: none;
        border-color: var(--mg-accent);
        box-shadow:
            0 4px 8px rgba(0, 0, 0, 0.4),
            0 0 0 1px var(--mg-accent),
            0 0 14px -4px var(--mg-accent-glow),
            inset 0 1px 0 rgba(255, 255, 255, 0.65);
    }
    /* Selected-then-hovered: keep the selected lift (no extra
       jump on hover), just intensify the glow. */
    .mg-doudizhu__match .mg-doudizhu__seat-hand--human .mg-doudizhu__card.is-selected:hover {
        transform: translateY(-14px);
        box-shadow:
            0 14px 28px rgba(0, 0, 0, 0.5),
            0 0 0 2px var(--mg-accent),
            0 0 22px var(--mg-accent-glow);
    }
}

/* --- 3. Back-to-Lobby button — pixel-identical to bigtwo -----
   bigtwo's back button uses the shared core.css base .mg-btn
   (transparent + 1.5px line-strong border + uppercase, with
   retro pulse on hover via mg-btn-pulse keyframe). v0.23.33
   styled doudizhu's back button as a custom pill (surface bg,
   muted ink, no pulse) — that's NOT bigtwo. Force-apply the
   base .mg-btn properties to override the v0.23.33 / v0.23.37
   pill, so this button renders identical to bigtwo's.

   Same treatment for the reclaim button (.mg-btn--primary) so
   the header matches bigtwo's match-header pair-by-pair.

   v0.23.99: removed the .mg-btn:first-child force-copy block here
   (was 31 lines of !important properties duplicating core.css's
   .mg-btn defaults). With block 1 (the pill style this was
   counter-acting) gone, this block became redundant — the back
   button now inherits core.css `.mg-btn` directly, same as bigtwo.
   The reclaim-btn rules below stay; .mg-btn--primary is a different
   base style with its own override needs. */

/* Reclaim button — bigtwo's `.mg-btn--primary` rendering.
   Defined in core.css line 533+: accent border + accent ink +
   stronger glow. Override v0.23.37's custom soft-fill pill. */
.mg-doudizhu__match .mg-doudizhu__match-header .mg-doudizhu__reclaim-btn {
    background: transparent !important;
    border: 1.5px solid var(--mg-accent) !important;
    color: var(--mg-accent) !important;
    font-family: var(--mg-body) !important;
    font-size: 13px !important;
    font-weight: 700 !important;
    text-transform: uppercase !important;
    letter-spacing: 0.08em !important;
    padding: 10px 18px !important;
    border-radius: var(--mg-radius-sm) !important;
    box-shadow:
        0 0 8px -2px var(--mg-accent-glow),
        inset 0 0 6px -2px var(--mg-accent-soft) !important;
    animation: revert !important;
}
.mg-doudizhu__match .mg-doudizhu__match-header .mg-doudizhu__reclaim-btn:hover {
    background: var(--mg-accent-soft) !important;
    box-shadow:
        0 0 16px -2px var(--mg-accent-glow),
        inset 0 0 8px -2px var(--mg-accent-soft) !important;
}

/* ============================================================
   END v0.23.38
   ============================================================ */

/* ============================================================
   v0.23.39  DEAL ANIMATION + PER-TURN TIMER (port from bigtwo)
   ============================================================
   New features (user request):
     - Deal animation + sound (sound is already in v0.23.19,
       just adding the visual cascade now)
     - Per-turn countdown timer

   The server already exposes `turn_started_at` + `timeout_per_turn_sec`
   in public_state_for and uses them in is_turn_expired/tick_timeout.
   Only the client side was missing. This block ports bigtwo's deal-
   cascade keyframes + timer pill + JS hooks 1:1 with the doudizhu
   class prefixes.
   ============================================================ */

/* --- Deal animation: card-backs (opponents + hole) ----------- */
.mg-doudizhu.is-dealing .mg-doudizhu__card-back {
    opacity: 0;
    transform: translate(-200%, -200%) scale(0.4) rotate(-180deg);
    animation: doudizhuDealCardBack 350ms cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
}
/* --- Deal animation: own hand (face-up cards) ----------------
   Cards fly in from above with a small twist, then settle. */
.mg-doudizhu.is-dealing .mg-doudizhu__seat-hand--human .mg-doudizhu__card {
    opacity: 0;
    transform: translateY(-200px) scale(0.5) rotate(-15deg);
    animation: doudizhuDealHumanCard 350ms cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
}
@keyframes doudizhuDealCardBack {
    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 doudizhuDealHumanCard {
    from {
        opacity: 0;
        transform: translateY(-200px) scale(0.5) rotate(-15deg);
    }
    50% { opacity: 1; }
    to {
        opacity: 1;
        transform: translateY(0) scale(1) rotate(0);
    }
}
/* During dealing, kill interaction and dim the trick area */
.mg-doudizhu.is-dealing .mg-doudizhu__seat-hand--human .mg-doudizhu__card {
    pointer-events: none;
}
.mg-doudizhu.is-dealing .mg-doudizhu__trick {
    opacity: 0.3;
    pointer-events: none;
}
/* v0.24.23: bid history pills get FULLY hidden during dealing (was
   opacity: 0.3, partially visible). User wanted a clean deal-first /
   bid-after sequence — having the AI's pending bid faintly readable
   alongside the cascade-out cards muddied the visual story. */
.mg-doudizhu.is-dealing .mg-doudizhu__history {
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease;
}
/* Suppress ALL decision panels (bid / double / claim / rob) mid-deal
   so they don't appear AND don't take layout space while cards are
   still flying. v0.24.23: switched from `opacity: 0` to `display:
   none` — opacity-only left the panel in the document flow,
   pushing surrounding elements (cards, status line) into shifted
   positions during the 8s deal, then jolting them back when the
   panel faded in. claim/rob panels added here too (originally only
   bid/double were suppressed — claim/rob are also bidding-phase
   variants and have the same surprise-appearance issue during
   redeal cascades). */
.mg-doudizhu.is-dealing .mg-doudizhu__bid-panel,
.mg-doudizhu.is-dealing .mg-doudizhu__double-panel,
.mg-doudizhu.is-dealing .mg-doudizhu__claim-panel,
.mg-doudizhu.is-dealing .mg-doudizhu__rob-panel {
    display: none !important;
}
/* v0.24.23: timer also hidden during dealing. The JS-side guard at
   pvpTimerTick (doudizhu.js ~line 892) already freezes the displayed
   value at "30s", but having the pill visible while cards fly out
   still implied "you're being timed right now". Hiding the chrome
   entirely matches bigtwo's effective feel — the timer reappears
   the moment .is-dealing clears, by which point turn_started_at's
   +10s grace gives the full 30s budget cleanly. */
.mg-doudizhu.is-dealing .mg-doudizhu__pvp-timer {
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease;
}

/* --- Per-turn timer pill ------------------------------------- */
/* v0.24.5: aligned to bigtwo's `.mg-bigtwo__pvp-timer` spec — same
   direction as v0.24.3 status alignment. User: "鬥地主較易入了下一行,
   bigtwo不會這樣,然後timer感覺也有少許不同". Doudizhu's timer was
   wider (gap:6px / padding:4px 12px / icon:14px), pushing the status
   line into wrapping at narrower widths. Re-spec to byte-match bigtwo's
   numbers; kept `font-variant-numeric: tabular-nums` (a doudizhu
   improvement worth porting back to bigtwo too — see bigtwo css). */
.mg-doudizhu__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);
    font-variant-numeric: tabular-nums;
    transition: color 0.2s, border-color 0.2s, background 0.2s;
}
.mg-doudizhu__pvp-timer[hidden] { display: none; }
.mg-doudizhu__pvp-timer-icon {
    font-size: 12px;
    line-height: 1;
}
.mg-doudizhu__pvp-timer-value {
    font-family: var(--mg-display);
    font-weight: 700;
    min-width: 30px;
    text-align: right;
    letter-spacing: 0.04em;
}
/* "Your turn" — accent treatment */
.mg-doudizhu__pvp-timer.is-mine {
    background: var(--mg-accent-soft);
    border-color: var(--mg-accent);
    color: var(--mg-accent);
}
/* 5 < remaining ≤ 15s — orange warning */
.mg-doudizhu__pvp-timer.is-mid {
    color: #f0a020;
    border-color: rgba(240, 160, 32, 0.45);
}
.mg-doudizhu__pvp-timer.is-mine.is-mid {
    background: rgba(240, 160, 32, 0.12);
}
/* ≤5s — red urgent, pulsing glow */
.mg-doudizhu__pvp-timer.is-low {
    color: #ef4040;
    border-color: rgba(239, 64, 64, 0.55);
    animation: doudizhuTimerLow 0.7s ease-in-out infinite alternate;
}
.mg-doudizhu__pvp-timer.is-mine.is-low {
    background: rgba(239, 64, 64, 0.14);
}
@keyframes doudizhuTimerLow {
    from { box-shadow: 0 0 0 0 rgba(239, 64, 64, 0); }
    to   { box-shadow: 0 0 12px 2px rgba(239, 64, 64, 0.5); }
}

/* ============================================================
   END v0.23.39
   ============================================================ */

/* ============================================================
   v0.23.40  HIDE ROOM ID + RECLAIM/NEXT-ROUND UX (跟 bigtwo)
   ============================================================
   User feedback after v0.23.39:
     - "header 不應該有 room id" — bigtwo's header has no `#1`
       round indicator; doudizhu's was a doudizhu-only addition.
       Hide via CSS (JS still writes to `$round` but with no
       visible target — no JS-side error).
     - "我返來按鈕按下去後 按鈕還在 + 要跳badge 與bigtwo一樣"
       → reclaim: optimistic hide + toast on success (port from
       bigtwo's pvpReclaimSeat).
     - "按下一局 會跳本局未結束的badge"
       → suppress the 409 "doudizhu_not_finished" toast that
       fires when host double-clicks Next-round or when polling
       already advanced the state. Real network errors still
       surface; only this specific race-condition error swallowed.
   ============================================================ */

.mg-doudizhu__match .mg-doudizhu__match-round {
    /* JS writes `#1` etc. into this element but bigtwo's header
       has no equivalent — keep markup for compatibility and hide
       visually. */
    display: none !important;
}

/* ============================================================
   END v0.23.40
   ============================================================ */

/* ============================================================
   v0.23.41  TRICK OVERLAP + KILL MATCH-ROUND ELEMENT
   ============================================================
   User feedback:
     - "出牌區出的牌和上一手一樣 牌都疊住吧"
       → trick area should overlap cards the same way history
       strip does (-30% in v0.23.38). Doudizhu plays up to 12
       cards at once (plane-with-wings); full-size cards with
       4px gap blow out width and wrap to multiple rows.
     - "卡大小不要變"
       → keep card dimensions unchanged. Only collapse the gap
       and add negative margin.
     - "不要 show room id 在 timer 旁" (still)
       → v0.23.40's display:none rule should have handled this,
       but user is still seeing it — likely a cache issue or
       an older install. Kill it more aggressively by also
       removing the DOM node from the template (in this same
       patch). JS write gets null-guarded.
   ============================================================ */

/* --- Trick overlap — same overlap math as history strip ------
   Mobile card w ≈ 45px. 12 cards plane-with-wings, no overlap:
       12 × 45 + 11 × 4 (gap) = 584 px  → wraps on phones
   With -45% overlap (each card visible 55%):
       11 × 0.55 × 45 + 45 = ~317 px  → fits 360 viewport
   Card SIZE is unchanged — only the inter-card spacing shrinks.
   `flex-wrap: wrap` from the base rule (line 790) stays as a
   fallback for extreme cases (e.g. 16-card max). */
.mg-doudizhu__match .mg-doudizhu__trick {
    gap: 0;
}
.mg-doudizhu__match .mg-doudizhu__trick > .mg-doudizhu__card + .mg-doudizhu__card {
    margin-left: calc(var(--doudizhu-card-w) * -0.45);
}

/* ============================================================
   END v0.23.41
   ============================================================ */

/* ============================================================
   v0.23.42  RECLAIM HOVER COLOR + DEAL ANIM RENDER STABILITY
   ============================================================
   User feedback:
     - "我返來接管 button hover 字會黑色 跟大D不一樣"
       → v0.23.37 left a `color: var(--mg-bg, #1c1c1e)` (near-
       black) override on the reclaim button's `:hover` state.
       v0.23.38's hover rule didn't override `color`, so the
       black leaked through. Bigtwo's `.mg-btn--primary:hover`
       uses `color: var(--mg-accent)` (blue/accent). Restore.
     - "動畫感覺很bug 應是一張張錯開的 而且需要一些時間"
       → not a CSS issue. The opponent / human / hole render
       functions in doudizhu.js were unconditionally rebuilding
       hand DOM (`$hand.innerHTML = ''`) on every 1.5s poll.
       Mid-deal, that rebuilds the cards just-staggered by
       applyDealStaggers, killing the cascade. Bigtwo's render
       functions diff and only rebuild when the count or card-
       ids actually change. Fix is in JS (see doudizhu.js diff
       in this patch). This CSS block also explicitly sets the
       hover color override since that's the visual half of
       the user-reported issues.
   ============================================================ */

/* Reclaim button — hover/focus colors match bigtwo's
   .mg-btn--primary:hover (accent text, accent border, accent-
   soft fill). The earlier v0.23.37 override that set color
   to --mg-bg on hover is explicitly defeated here. */
.mg-doudizhu__match .mg-doudizhu__match-header .mg-doudizhu__reclaim-btn:hover,
.mg-doudizhu__match .mg-doudizhu__match-header .mg-doudizhu__reclaim-btn:focus-visible {
    color: var(--mg-accent) !important;
    background: var(--mg-accent-soft) !important;
    border-color: var(--mg-accent) !important;
}

/* ============================================================
   END v0.23.42
   ============================================================ */

/* ============================================================
   v0.23.43  HAND CENTERING FIX + ACTION TOAST STYLES
   ============================================================
   User feedback:
     - "手機卡牌區 我發現不置中 感覺位置怪怪的"
       → root cause is per-row asymmetry. The previous redesign
       used `.__card + .__card { margin-left: -25% }` which only
       targets cards that follow ANOTHER card in DOM order — so
       the FIRST DOM card has no negative margin while every
       subsequent card does. After flex-wrap, the first card on
       row 1 is wider than the first card on rows 2+ (no -25%
       margin to pull it in). This means row 1 fits 1 less card,
       producing the ugly 7+8+2 split visible in the screenshot
       instead of the clean 9+8 the design comment claims. Plus
       each row's `justify-content: center` produces a slightly
       different visual center because the margin-eaten widths
       per row differ.
     - Fix: apply the negative margin to EVERY card uniformly
       (including the DOM-first), and bump padding-left on the
       container to compensate the first-card overhang. Now
       every row has identical per-card width math → flex-wrap
       splits cleanly + every row centers identically.
     - Same idea on desktop single-row layout (the base rule at
       line ~1101) — keep the original `+` selector there since
       there's no wrap; only mobile gets the uniform treatment.
   ============================================================ */

@media (max-width: 900px) {
    /* Apply overlap to EVERY card in the human hand on mobile,
       not just the post-first ones. This guarantees row 1 and
       row 2 have identical card-width math after flex-wrap.

       Also bumped the overlap from -25% to -28% so 9 cards fit
       per row at typical phone widths (412 vp → 45 px card,
       inner row width ≈ 280 px). With 9 cards at -28% overlap:
           9 × 45 × 0.72 = 291 px — fits 280 px row close enough
       given flex's tolerance for the LAST card's full width
       (no margin-right). Actual fit: 45 + 8×(45-12.6) = 45 + 259.2 = 304.
       Hmm — slightly over. At 360 vp (smallest target) card is
       40 px, fit = 40 + 8×(40-11.2) = 270 → fits comfortably.
       Sticking with -28% for 360–412 vp clean 9+8. Wider phones
       (480+ vp) cap card-w at 48 — same -28% gives 48+8×34.5=324,
       and inner width grows proportionally, so still fits.

       The previous `.__card + .__card` selector at line ~2148
       is overridden by this rule (higher specificity via @media
       + same class chain, later source order). */
    .mg-doudizhu__match .mg-doudizhu__seat-hand--human .mg-doudizhu__card {
        margin-left: calc(var(--doudizhu-card-w) * -0.28);
    }
    /* The previous rule's specificity needs to match — also keep
       the .__card + .__card rule from line 2148 in sync (same
       value). When both rules apply, the per-card uniform rule
       wins because it's a simpler selector at the same media
       query level; for cards 2+, this evaluates to the same
       margin so visually identical. */
    .mg-doudizhu__match .mg-doudizhu__seat-hand--human .mg-doudizhu__card + .mg-doudizhu__card {
        margin-left: calc(var(--doudizhu-card-w) * -0.28);
    }
    /* Compensate the first-card neg margin by bumping container
       padding-left to MATCH. With first card now having
       margin-left -0.28 × card_w, padding-left of +0.28 × card_w
       restores the leftmost visual edge to the container edge. */
    .mg-doudizhu__match .mg-doudizhu__seat-hand--human {
        padding-left: calc(var(--doudizhu-card-w) * 0.28);
    }
}

/* --- Action toast — speech-bubble vibe over normal MG.toast ----
   These are the brief "Kelvin Wong 加倍!" / "💣 AI 炸彈!"
   notifications the user requested. We render them via MG.toast
   (existing infrastructure — top-of-game-area floating pill),
   but with the action-specific `mg-toast--action` class so we
   can style louder than a routine error toast: bigger text,
   slight scale-in, accent-tinted background. */
.mg-toast.mg-toast--doudizhu-action {
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.01em;
    background: linear-gradient(180deg,
        rgba(30, 30, 35, 0.96) 0%,
        rgba(18, 18, 22, 0.96) 100%);
    border: 1px solid var(--mg-accent);
    box-shadow:
        0 8px 24px rgba(0, 0, 0, 0.45),
        0 0 18px var(--mg-accent-glow);
    color: var(--mg-ink);
    /* Pop-in animation */
    animation: doudizhuActionToastPop 280ms cubic-bezier(0.34, 1.3, 0.64, 1);
}
@keyframes doudizhuActionToastPop {
    from { transform: translateY(-6px) scale(0.92); opacity: 0; }
    to   { transform: translateY(0)    scale(1);    opacity: 1; }
}

/* ============================================================
   END v0.23.43
   ============================================================ */

/* ============================================================
   v0.23.54  HOTFIX — back/reclaim btn match core .mg-btn exactly
   ============================================================
   v0.23.45 used `all: revert` to "stop fighting the cascade" and
   land core .mg-btn styling. But that's a misunderstanding of how
   `revert` works: it doesn't revert to an earlier rule in the
   same (author) origin — it reverts to the NEXT cascade origin
   below (author → user → user-agent). Since user stylesheets
   rarely set button properties, `all: revert` actually dropped
   to user-agent defaults (the OS-grey browser button), not the
   plugin's .mg-btn skin.

   User feedback v0.23.53: "鬥地主這個 button hover 和鋤大D不
   一致..." — confirms `all: revert` was rendering the OS-default
   button (with the OS hover state showing as plain white border
   on dark background, no pulse animation).

   THE REAL FIX: explicitly copy .mg-btn's properties at higher
   specificity than v0.23.33's redesign block. Same effect as
   bigtwo (which has no doudizhu-redesign-block to fight, so
   inherits .mg-btn directly).

   Selectors are written with `body.mg-active` (or any extra
   stable parent class) to bump specificity above the v0.23.33
   block — but actually identical selectors at later position
   win on equal specificity, so no class-bump needed; we just
   ensure these rules appear AFTER v0.23.45 in source order.

   Properties copied verbatim from assets/core.css .mg-btn /
   :hover / :focus-visible / :active (lines 442-496).
   ============================================================ */

.mg-doudizhu__match .mg-doudizhu__match-header .mg-doudizhu__reclaim-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: transparent;
    border: 1.5px solid var(--mg-line-strong);
    color: var(--mg-ink);
    font-family: var(--mg-body);
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 10px 18px;
    border-radius: var(--mg-radius-sm);
    cursor: pointer;
    text-decoration: none;
    line-height: 1.2;
    position: relative;
    transition:
        border-color .18s ease,
        box-shadow   .18s ease,
        color        .18s ease,
        background   .18s ease,
        transform    .04s ease;
    user-select: none;
    -webkit-user-select: none;
    -webkit-tap-highlight-color: transparent;
    box-shadow:
        0 0 0 0 rgba(255, 255, 255, 0),
        inset 0 0 0 0 rgba(255, 255, 255, 0);
    /* explicitly clear properties from v0.23.33's pill-style block. */
    font-weight: 700;
    opacity: 1;
    filter: none;
}

.mg-doudizhu__match .mg-doudizhu__match-header .mg-doudizhu__reclaim-btn:hover,
.mg-doudizhu__match .mg-doudizhu__match-header .mg-doudizhu__reclaim-btn:focus-visible {
    border-color: var(--mg-ink);
    color: var(--mg-ink);
    background: rgba(255, 255, 255, 0.04);
    outline: none;
    /* Breathing pulse — same animation core.css defines (mg-btn-pulse,
       1.6s ease-in-out infinite). Animation name + keyframes live in
       core.css so we just reference it. */
    animation: mg-btn-pulse 1.6s ease-in-out infinite;
}

.mg-doudizhu__match .mg-doudizhu__match-header .mg-doudizhu__reclaim-btn:active {
    transform: translateY(1px);
    animation: none;
    box-shadow:
        0 0 12px 2px rgba(255, 255, 255, 0.20),
        inset 0 0 8px rgba(255, 255, 255, 0.14);
}
/* v0.23.99: removed .mg-btn:first-child from the three rules above —
   that selector targeted the back-to-lobby button, but blocks 1, 2,
   and 3 (the earlier overrides this block was guarding against) are
   all gone now. The back button inherits core.css `.mg-btn` directly,
   identical to bigtwo. Reclaim button (.mg-doudizhu__reclaim-btn)
   still needs these rules because it's a NEW custom class, not a
   core.css preset. */

/* ============================================================
   END v0.23.54
   ============================================================ */


/* ============================================================
   END v0.23.33 / v0.23.34 redesign block
   ============================================================ */

/* ============================================================
   v0.23.53  Hand overflow fix — long username + abandoned badge
   ============================================================
   Same issue as bigtwo v0.23.53: on mobile the bottom (human)
   seat's name + count badge ("AI 託管中" / abandoned indicator)
   can exceed the seat's width cap (~7 cards), overflowing right.

   Root cause: .seat-info is flex row inside .seat--bottom
   (flex column). Column parent constrains its own width but
   not children's intrinsic widths — 12em seat-name + uncapped
   seat-count can exceed parent on narrow screens.

   Fix: clamp seat-info to 100% of parent, allow name + count to
   shrink with min-width: 0, drop the 12em seat-name cap on
   mobile. (Outside the v0.23.33/34 redesign block — appended
   here so we don't touch the user's redesign block.)
   ============================================================ */

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

@media (max-width: 600px) {
    .mg-doudizhu__match .mg-doudizhu__seat--bottom .mg-doudizhu__seat-name {
        max-width: none;
    }
}

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