/* === Reset === */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    /* Kill Android Chrome / WebView's default blue tap-highlight rectangle
       that flashes up on `.card` and `.btn` touches — we supply our own
       hover/active styles. */
    -webkit-tap-highlight-color: transparent;
    /* Disable text selection and long-tap context menu app-wide.
       Opt in selectively with `.selectable { user-select: text }`. */
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
}

html, body {
    height: 100%;
    font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
    background: #0d3d1a;
}

/* === Game Table === */
/* Safe-area insets are applied to individual edge elements (header, west,
   east, actions) rather than to the outer grid container, so the header
   background extends edge-to-edge on devices with non-zero left/right
   insets (e.g. Android gesture navigation).

   `position: fixed` + `inset: 0` + `margin: auto` with max-width/max-height
   centers the table in the viewport and caps its proportions on wide desktop
   windows. Without these caps, cards/buttons/labels sit at their clamp
   ceilings while the grid stretches to fill 1920×1080, leaving the middle
   play row as an expanse of empty green. The body's #0d3d1a background
   shows through as letterbox on all four sides. On phones and tablets the
   caps don't kick in — `inset: 0` fills the viewport edge-to-edge. Fixed
   positioning also still creates a containing block for the absolutely-
   positioned play slots, animation layer, and hint tooltip below. */
.game-table {
    display: grid;
    grid-template-areas:
        "header  header  header"
        "west    play    east"
        "tools   .       actions";
    grid-template-columns: minmax(80px, 1fr) 3fr minmax(80px, 1fr);
    grid-template-rows: auto 1fr auto;
    position: fixed;
    inset: 0;
    margin: auto;
    max-width: 1100px;
    max-height: 820px;
    background: radial-gradient(ellipse at center, #1e7a3a 0%, #145a28 60%, #0d3d1a 100%);
    color: #e0e0e0;
    overflow: hidden;
}

.game-table.loading {
    display: flex;
    align-items: center;
    justify-content: center;
}

.loading-text {
    font-size: 1.5rem;
    color: #aaa;
}

/* === Header Bar === */
/* The header bar is split into two pills (team-levels on the left, game-info
   on the right), leaving a transparent gap in the middle where the
   absolutely-positioned north opponent label sits. Safe-area insets live
   inside each pill's padding (not on `.header-bar`) so the dark pill
   backgrounds extend all the way to x=0 and x=viewport-width on devices
   with non-zero side insets. Content is still kept clear of display
   cutouts via the extra inner padding on the pill's outer edge. */
.header-bar {
    grid-area: header;
    display: flex;
    justify-content: space-between;
    align-items: stretch;
    padding: env(safe-area-inset-top) 0 0 0;
    background: transparent;
    font-size: 0.85rem;
}

.team-levels {
    display: flex;
    gap: 12px;
    align-items: center;
    background: rgba(0, 0, 0, 0.3);
    padding: 8px 16px 8px calc(16px + env(safe-area-inset-left));
    border-radius: 0 0 12px 0;
}

.team-a { color: #7ec8e3; }
.team-b { color: #e8a87c; }
.level-separator { color: #666; }

.game-info {
    display: flex;
    gap: 12px;
    align-items: center;
    color: #ccc;
    background: rgba(0, 0, 0, 0.3);
    padding: 8px calc(16px + env(safe-area-inset-right)) 8px 16px;
    border-radius: 0 0 0 12px;
}

/* === Opponent Areas === */
.opponent-area {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 8px;
    gap: 4px;
}

/* North opponent lives in the gap between the two header pills instead of
   a grid cell. Taking it out of the grid lets the play area (row 2) start
   directly below the header, giving room for taller hand stacks. The
   label is laid out HORIZONTALLY (name on the left, card count on the
   right) so its total height stays small and leaves reliable breathing
   room before the played cards below — the previous vertical stack
   rendered tall enough on some phones that the "X cards" line visually
   touched the played cards. */
.opponent-area.pos-north {
    position: absolute;
    top: calc(env(safe-area-inset-top) + 6px);
    left: 50%;
    transform: translateX(-50%);
    flex-direction: row;
    align-items: center;
    gap: 8px;
    padding: 2px 4px;
    z-index: 5;
    pointer-events: none;
    white-space: nowrap;
}

.opponent-area.pos-north .opponent-name {
    padding: 2px 10px;
    font-size: 0.85rem;
}

.opponent-area.pos-north .opponent-info {
    font-size: 0.75rem;
}

.opponent-area.pos-west {
    grid-area: west;
    padding-left: calc(8px + env(safe-area-inset-left));
}

.opponent-area.pos-east {
    grid-area: east;
    padding-right: calc(8px + env(safe-area-inset-right));
}

.opponent-header {
    display: flex;
    align-items: center;
    gap: 6px;
}

.opponent-name {
    font-weight: 600;
    font-size: 0.9rem;
    background: rgba(0, 0, 0, 0.4);
    padding: 4px 12px;
    border-radius: 12px;
}

.opponent-info {
    font-size: 0.8rem;
    color: #bbb;
}

.card-count { color: #ccc; }

.out-badge {
    color: #e8a87c;
    font-weight: 600;
}

.opponent-area.active-turn .opponent-name {
    background: rgba(255, 200, 0, 0.3);
    box-shadow: 0 0 8px rgba(255, 200, 0, 0.4);
}

/* === Play Area === */
/* `position: relative` anchors the absolutely-positioned `.play-position`
   children. No z-index here — we deliberately avoid creating a stacking
   context on `.play-area` so each `.play-position` can compete with
   `.player-hand` individually (see `.play-position` below).

   `pointer-events: none` lets clicks on the (mostly transparent)
   play area pass through to the player's hand below — without it,
   the hand's deeper-stacked cards (4th, 5th, …) couldn't be
   selected because the play area was eating their clicks. The
   `.play-position` children re-enable pointer events for the
   actually-painted played cards. */
.play-area {
    grid-area: play;
    position: relative;
    min-height: 120px;
    pointer-events: none;
}

/* `z-index: 10` stacks played cards above the absolutely-positioned
   `.player-hand` (z-index 1) so the human's own played cards
   (pos-south) render on top when a tall hand stack extends upward
   into the play area. Opponent positions (west/east/north) also
   need to sit above the hand because a tall hand stack can reach
   into those areas as well. */
.play-position {
    position: absolute;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    z-index: 10;
    pointer-events: auto;
}

/* Once the human's own played cards are no longer the winning play
   (they shrink via `IsSmall` in PlayArea.razor), drop them BELOW
   `.player-hand` so the shrunk cards no longer intercept clicks on
   the hand — in particular, tall hand stacks (bombs) that extend
   upward into the play-area remain selectable. */
.play-position.pos-south.losing {
    z-index: 0;
}

/* pos-east / pos-west are centered vertically; pos-south sits just below
   them so the top edge of the human's played cards lines up with the
   bottom of the small cards in pos-east / pos-west. pos-north sits at the
   top of the play-area, just below the header/north-label row.
   The winning play renders at "normal" (non-small) card size — see
   PlayArea.razor — which is the visual highlight; losing plays stay
   small. */
.play-position.pos-south {
    top: calc(50% + 22px);
    bottom: auto;
    left: 50%;
    transform: translateX(-50%);
}
/* pos-north played cards start below the absolutely-positioned north
   opponent label (see `.opponent-area.pos-north`). The label is laid
   out horizontally (~22px tall) so a smaller top offset still clears
   it comfortably on every device — fixed-pixel because the label is
   also fixed height.
   pos-west / pos-east use a small NEGATIVE left/right offset so the
   played cards poke slightly into their respective side columns,
   tightening the visual gap to the opponent label. The opponent labels
   themselves stay centered in their columns. */
.play-position.pos-north { top: 18px; left: 50%; transform: translateX(-50%); }
.play-position.pos-west { top: 50%; left: -16px; transform: translateY(-50%); }
.play-position.pos-east { top: 50%; right: -16px; transform: translateY(-50%); }

.played-cards {
    display: flex;
}

/* Smoothly shrink the previously-winning play when a new combination
   beats it. The `.small` class is toggled by PlayArea.razor (or
   kicked off synchronously by cardAnimations.play for the south case)
   when the play loses `winner` status. Scoped to `.play-position
   .card.small` -- not `.play-position .card` -- so the transition
   is defined ONLY when the element has `.small`. When `.small` is
   ADDED (losing), the new state's transition fires and width
   smoothly contracts; when `.small` is REMOVED (re-winning, e.g. an
   opponent plays a second combo on top of their own), the new state
   has no transition defined and width snaps instantly -- which is
   what ghost clones need, since they're measured right after Blazor
   re-renders and must read the final big rect. */
.play-position .card.small {
    transition:
        width 260ms cubic-bezier(0.2, 0.7, 0.3, 1),
        margin-left 260ms cubic-bezier(0.2, 0.7, 0.3, 1),
        box-shadow 260ms ease;
}

/* Played cards overlap horizontally at exactly the same proportion as the
   hand columns (`.card-column + .card-column`). Normal-size (winning)
   plays use the hand's clamp verbatim because they are the same width as
   hand cards. Small (losing) plays scale the clamp by the small/normal
   card-width ratio (36/60 = 0.6) so the visible portion of each card is
   the same fraction as in the hand. */
.played-cards .card + .card {
    margin-left: clamp(-13px, -2.5vw, -6px);
}

.played-cards .card.small + .card.small {
    margin-left: clamp(-8px, -1.5vw, -4px);
}

/* Absolute-positioned so the label's presence/absence doesn't change
   `.play-position`'s intrinsic height. When the seat transitions from
   winning to losing, Blazor removes the label element at re-render --
   if the label were a flex child, removing it would shrink the slot
   and the `translateY(-50%)` centering would re-center the cards,
   producing a visible vertical jump right after the shrink animation
   finishes. Sitting the label under the cards via absolute positioning
   keeps the slot's flex height equal to `.played-cards` alone. */
.play-label {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-top: 2px;
    font-size: 0.65rem;
    color: #ccc;
    white-space: nowrap;
    pointer-events: none;
}

.pass-label {
    font-size: 0.8rem;
    color: #999;
    font-style: italic;
    padding: 8px;
}

/* === Actions Column === */
/* The status bar and action bar are stacked vertically in the bottom-right
   grid cell so the status texts ("Your turn", combo name + beat/lose
   indicator, errors) sit directly above the PASS/PLAY buttons. This frees
   up the full middle-column height for the player hand and lets the
   larger cards have more vertical room.
   `padding-bottom` matches the hand's bottom offset + bottom padding (see
   `.player-hand`: `bottom: 4px` + `padding-bottom: 4px` = 8px) so the
   PASS/PLAY buttons bottom-align with the bottom edge of the card BODY
   rather than the bottom of the card's drop shadow. */
/* === Tools Column (left of player hand) === */
/* Both `.tools-col` and `.actions-col` need `position: relative` +
   `z-index: 2` to stack above the absolutely-positioned `.player-hand`
   (z-index: 1) whose 14% left/right insets partially overlap the side
   grid columns. Without this the hand intercepts clicks on the buttons. */
.tools-col {
    grid-area: tools;
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    padding: 4px 2px calc(8px + env(safe-area-inset-bottom)) 2px;
    padding-left: calc(2px + env(safe-area-inset-left));
}

.actions-col {
    grid-area: actions;
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-end;
    gap: 4px;
    padding: 4px 2px calc(8px + env(safe-area-inset-bottom)) 2px;
    padding-right: calc(2px + env(safe-area-inset-right));
}

/* === Status Bar === */
/* Fixed `height` (not min-height) so the `.actions-col` cell stays a
   constant size regardless of status text changes. Without this, on
   Android the status text changing on card selection caused the
   actions row to grow slightly, shrinking the `1fr` play row, which in
   turn shifted the vertically-centered east/west opponent labels
   upward each time the user tapped a card. */
.status-bar {
    text-align: center;
    padding: 2px 4px;
    height: 28px;
    font-size: 0.75rem;
    line-height: 1.15;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
}

.combo-name {
    color: #ffd700;
    font-weight: 600;
}

/* Invalid selection (≥2 cards that don't form a valid combo) renders in
   the same slot as the combo name but in the warning red used by the
   loses-to-winner indicator, so the whole "Invalid ✗" label reads as a
   single warning group. */
.combo-name.invalid-combo {
    color: #e74c3c;
}

.beats-winner {
    color: #4caf50;
    margin-left: 6px;
    font-size: 1rem;
}

.loses-to-winner {
    color: #e74c3c;
    margin-left: 6px;
    font-size: 1rem;
}

.status-message { color: #ccc; }
.error-message { color: #e74c3c; }

/* Inline "clear selection" chip next to the combo label in the status bar.
   Deliberately unobtrusive: small circle, muted border and glyph, so it
   reads as a secondary affordance rather than a primary control. */
.clear-selection {
    appearance: none;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.28);
    color: rgba(255, 255, 255, 0.65);
    width: 18px;
    height: 18px;
    border-radius: 50%;
    padding: 0;
    margin-left: 8px;
    font-size: 0.95rem;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: color 120ms ease, border-color 120ms ease, background-color 120ms ease;
}

.clear-selection:hover {
    color: #fff;
    border-color: rgba(255, 255, 255, 0.55);
}

.clear-selection:active {
    background: rgba(255, 255, 255, 0.08);
}

.clear-selection:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.55);
    outline-offset: 2px;
}

/* === Player Hand === */
/* Absolutely-positioned inside the grid container so the hand owns
   a tall slot from just below the header down to the bottom of the
   table. Cards bottom-align inside, so short stacks stay low and
   tall (8-card) stacks extend upward — visually overlapping the
   north label / play area when needed rather than pushing other
   grid rows. The left/right insets match the middle grid column so
   the hand is centered under the north label and the actions column
   on the right stays clear. */
.player-hand {
    position: absolute;
    /* Hand is wider than the middle grid column so cards have room to
       spread on larger screens. On small screens the edges extend under
       the side buttons, but adjustLayout() in JS accounts for this by
       computing overlap based on the visible width (excluding the area
       hidden under the button columns). */
    left: 14%;
    right: 14%;
    /* `top` tracks the header row: 44px of content height + whatever the
       device reports for the top safe-area inset (notches / status bars).
       Without the env() component the hand would overlap the header on
       notched devices where the header pill is pushed down by its own
       safe-area-inset-top padding. */
    top: calc(44px + env(safe-area-inset-top));
    bottom: 4px;
    /* Lower than `.play-position`'s `z-index: 10` so the winning
       played cards overlap a tall hand-stack, rather than the other
       way around. Still higher than the default stacking order of
       the opponent areas so the hand is free to extend upward into
       the north/east/west opponent cells. Losing pos-south cards
       drop to `z-index: 0` (see `.play-position.pos-south.losing`)
       so they don't intercept clicks on the hand below them. */
    z-index: 1;
    display: flex;
    justify-content: center;
    align-items: flex-end;
    padding: 8px 0 4px;
    overflow: hidden;
    pointer-events: auto;
    /* Scope layout + paint to the hand so reflows during the collapse
       animation don't ripple out to the rest of the table. Formalizes
       the isolation the `overflow: hidden` + absolute positioning
       already implies. */
    contain: layout paint;
}

.card-column {
    display: flex;
    flex-direction: column;
}

/* Columns overlap horizontally so the hand packs tighter and matches
   the Figma fanned-hand look. With 8–10 columns the base overlap is
   enough; for large hands (13+ ranks) the fit-overlap takes over and
   squeezes columns so the entire hand fits between the side buttons.
   Available width = hand container (100vw − 2 × side column) − padding.
   Side columns are max(20%, 80px), padding is 12px. One card is full-
   width; the remaining (N−1) share whatever is left. */
.card-column + .card-column {
    /* --col-margin is computed by dragSelect.adjustLayout() in JS,
       which measures the actual container width and card size.
       Falls back to the base overlap if JS hasn't run yet. */
    margin-left: clamp(-13px, -2.5vw, -6px);
    margin-left: var(--col-margin, clamp(-13px, -2.5vw, -6px));
}

/* Vertical stack overlap: each non-last card exposes enough headroom
   to show the full rank glyph. The clamp is tuned so the exposed
   region (H − |margin|) stays at or above the glyph's bottom edge
   across the `.card` width clamp (42px → 60px). Scaled ~20% from the
   baseline along with the rest of the hand dimensions. */
.card-column .card + .card {
    margin-top: clamp(-50px, -4.9vw, -36px);
}

/* === Card ===
 * Layered card design sourced from the Figma artboard
 * (docs/old/table.css, reference size 58x77). Token names are
 * defined in figma-tokens.css.
 *
 * The live rendered size is proportionally ~20% larger than the
 * previous baseline (42x58 → 60x84 vs the old 35x49 → 50x70) so
 * cards are easier to tap on mobile. Aspect ratio is preserved
 * (50/70 ≈ 0.714) to match the joker SVG's card body proportions.
 */
.card {
    width: clamp(42px, 5.76vw, 60px);
    aspect-ratio: 50 / 70;
    background: var(--te-card-face-gradient);
    border: 1px solid var(--te-card-border);
    border-radius: var(--te-radius-sm);
    /* Three-layer shadow: the two outer layers match `filter0_dd` from
       the Figma card SVGs (soft Y-offset drop shadow, same parameters
       as `--te-shadow-card`); the inset layer matches `filter1_d` from
       the same SVGs, which puts a greyish depth-shadow along the card's
       top-left interior edges. Together they reproduce the subtle
       embossed look the joker SVG bakes into its artwork. */
    box-shadow:
        var(--te-shadow-card),
        inset 3px 3px 3px rgba(0, 0, 0, 0.18);
    position: relative;
    cursor: pointer;
    transition: transform 0.1s ease, box-shadow 0.1s ease;
    touch-action: none;
    font-family: var(--te-font-body);
    font-weight: 700;
    flex-shrink: 0;
}

.card:hover:not(.disabled):not(.selected) {
    box-shadow:
        var(--te-shadow-card),
        inset 3px 3px 3px rgba(0, 0, 0, 0.18),
        0 2px 8px rgba(255, 255, 255, 0.25);
}

/* Selected cards stay in place — the previous upward lift made cards
   jump in and out of the hand as the user dragged across them, which
   was disorienting on mobile. Instead, the face is muted to a greyish
   tone (see docs/old/hand.png) while keeping the rank/suit readable.
   The grey replaces the white card-face gradient; rank/suit icons and
   joker foreground artwork sit on top and keep their colour. */
.card.selected {
    background: linear-gradient(270.51deg, #a8a8a8 0.44%, #c4c4c4 99.56%);
}

.card.wild {
    border: 1px solid #ffd700;
}

/* Inline suit SVGs on wildcard hearts pick up this color via currentColor. */
.card.wild .card-suit-small,
.card.wild .card-suit-large {
    color: #ffd700;
}

.card.level-card {
    border: 1px solid #ffd700;
}

.card.disabled {
    cursor: default;
}

.card.small {
    width: clamp(24px, 3vw, 36px);
    box-shadow:
        0 2px 2px rgba(0, 0, 0, 0.25),
        0 5px 9px rgba(0, 0, 0, 0.12),
        inset 1px 1px 1px rgba(0, 0, 0, 0.18);
}

.card.red {
    color: var(--te-suit-red);
}

.card.black {
    color: var(--te-suit-black);
}

/* Rank/suit slot percentages are slightly larger than the raw Figma
   values (Rank 3.64/54.77/0/62.24, SuitSmall 50/22.95/9.69/68.71,
   SuitLarge 40.91/7.5/56.46/4.93) so the glyphs render at Figma size
   despite the inline SVG viewBoxes carrying a little padding around
   the shape. */
.card-rank {
    position: absolute;
    left: 3%;
    right: 52%;
    top: 0;
    bottom: 58%;
    display: block;
    line-height: 0;
}

/* RankIcon's inline SVG uses fill=currentColor so .card.red / .card.black
   flow through to the glyph. */
.card-rank .rank-svg {
    width: 100%;
    height: 100%;
    display: block;
}

.card-suit-small {
    position: absolute;
    left: 49%;
    right: 20%;
    top: 8%;
    bottom: 65%;
    object-fit: contain;
    pointer-events: none;
}

.card-suit-large {
    position: absolute;
    left: 39%;
    right: 6%;
    top: 54%;
    bottom: 3%;
    object-fit: contain;
    pointer-events: none;
}

/* Joker variant — the foreground SVG contains only artwork (text + icon);
   the card face, border, and shadow come from the base .card styles. */
.card.card-joker {
    overflow: hidden;
}

.card-joker-image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: fill;
    pointer-events: none;
}

/* === Action Bar === */
/* Sits inside `.actions-col` below the status bar, so PASS/PLAY are
   directly below the status text. The column-level padding/safe-area
   insets live on `.actions-col`. */
.action-bar {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 12px;
    padding: 4px 0 0 0;
}

.btn {
    padding: 10px 28px;
    border: none;
    border-radius: 20px;
    font-size: 0.9rem;
    font-weight: 700;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 1px;
    transition: opacity 0.15s, transform 0.1s;
    min-width: 100px;
    min-height: 48px;
}

.btn:disabled {
    opacity: 0.35;
    cursor: default;
}

.btn:not(:disabled):hover {
    transform: scale(1.05);
}

.btn:not(:disabled):active {
    transform: scale(0.97);
}

.btn-pass {
    background: #78909c;
    color: white;
}

.btn-play {
    background: #4caf50;
    color: white;
}

.btn-tool {
    background: #78909c;
    color: white;
}

.btn-continue {
    background: #2196f3;
    color: white;
    margin-top: 16px;
}

.btn-menu {
    background: #607d8b;
    color: white;
    margin-top: 8px;
}

.overlay-buttons {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
}

/* === Overlay === */
.overlay-backdrop {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
}

.overlay-panel {
    background: #1e3a2a;
    border: 1px solid #3a5a4a;
    border-radius: 12px;
    padding: 32px 48px;
    text-align: center;
    color: #e0e0e0;
    max-width: 400px;
}

.overlay-panel h2 {
    margin-bottom: 16px;
    font-size: 1.4rem;
    color: #ffd700;
}

.overlay-panel h3 {
    margin-bottom: 8px;
    font-size: 1rem;
    color: #ccc;
}

.finish-order {
    margin-bottom: 16px;
}

.finish-order div {
    padding: 2px 0;
}

.team-levels-overlay {
    margin: 12px 0;
    font-size: 0.9rem;
    color: #bbb;
}

.team-levels-overlay div {
    padding: 2px 0;
}

/* === History Button === */
.btn-history {
    background: transparent;
    border: 1px solid #666;
    color: #ccc;
    padding: 2px 10px;
    border-radius: 10px;
    font-size: 0.75rem;
    cursor: pointer;
    transition: background 0.15s;
}

.btn-history:hover {
    background: rgba(255, 255, 255, 0.1);
}

/* === Trick History Overlay === */
.trick-history-panel {
    max-height: 70vh;
    overflow-y: auto;
    min-width: 320px;
}

.no-history {
    color: #888;
    font-style: italic;
    padding: 16px 0;
}

.trick-history-list {
    text-align: left;
}

.trick-history-item {
    margin-bottom: 12px;
    padding-bottom: 12px;
    border-bottom: 1px solid #3a5a4a;
}

.trick-history-item:last-child {
    border-bottom: none;
}

.trick-header {
    display: flex;
    justify-content: space-between;
    margin-bottom: 4px;
}

.trick-number {
    font-weight: 600;
    color: #ffd700;
    font-size: 0.85rem;
}

.trick-winner {
    color: #4caf50;
    font-size: 0.8rem;
}

.trick-play {
    display: flex;
    gap: 8px;
    align-items: center;
    padding: 2px 0;
    font-size: 0.8rem;
}

.play-player {
    min-width: 50px;
    color: #ccc;
}

.play-combo {
    color: #7ec8e3;
    min-width: 80px;
}

.play-cards {
    display: flex;
    gap: 2px;
}

.play-card {
    font-weight: 600;
    font-size: 0.75rem;
}

.play-card.red { color: #cc0000; }
.play-card.black { color: #ddd; }

/* === Rules Intro Overlay === */
.rules-intro-panel {
    max-width: 480px;
    min-height: 240px;
    display: flex;
    flex-direction: column;
}

.rules-intro-panel p {
    color: #ccc;
    font-size: 0.9rem;
    line-height: 1.6;
    margin: 6px 0;
}

.rules-intro-nav {
    margin-top: auto;
    padding-top: 16px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

.rules-intro-dots {
    display: flex;
    gap: 8px;
}

.dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #555;
    cursor: pointer;
    transition: background 0.2s;
}

.dot.active {
    background: #ffd700;
}

.rules-intro-buttons {
    display: flex;
    gap: 12px;
}

/* === Hint Tooltip === */
.hint-tooltip {
    position: absolute;
    z-index: 90;
    pointer-events: auto;
    animation: hint-fade-in 0.3s ease-out;
}

.hint-tooltip.hint-actions {
    bottom: 120px;
    right: 16px; /* fallback for browsers without env() support */
    right: calc(16px + env(safe-area-inset-right, 0px));
}

.hint-tooltip.hint-play-area {
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    animation: hint-fade-in-center 0.3s ease-out;
}

.hint-tooltip-content {
    background: rgba(0, 0, 0, 0.88);
    border: 1px solid #ffd700;
    border-radius: 10px;
    padding: 14px 20px;
    max-width: 280px;
    text-align: center;
}

.hint-tooltip-content p {
    margin: 0;
    color: #fff;
    font-size: 0.95rem;
    line-height: 1.4;
}

@keyframes hint-fade-in {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

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

.match-end-profile {
    display: flex;
    justify-content: center;
    margin: 12px 0;
}
