/* ─────────────────────────────────────────────────────────────────────────────
   Christianity / Roman War — Sacred Battlefield UI
   Immersive dark-fantasy board: divine light (bottom) vs. darkness (top)
───────────────────────────────────────────────────────────────────────────── */

@import url('https://fonts.googleapis.com/css2?family=Cinzel+Decorative:wght@700&family=Cinzel:wght@500;600;700&family=Nunito+Sans:wght@400;600;700&display=swap');

/* NOTE: BEAGLB is NOT registered here on purpose. The designer's JS registers
   it with trailing spaces in the family name ("BEAGLB  ") due to a PHP ucwords
   quirk on the "BEAGLB__.TTF" filename. The CSS requests "BEAGLB" (no spaces),
   which does not match — so the designer ends up rendering the title in the
   system `serif` fallback. Registering it here with a clean name would make
   the game render in BEAGLB while the designer renders in Times, breaking
   parity. Until the designer's font-loader is fixed, game must also fall back
   to plain serif to match. */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
    --card-w:        72px;
    --card-h:        106px;
    --card-w-sm:     48px;
    --card-h-sm:     70px;
    --card-w-hand:   96px;
    --card-h-hand:   142px;
    --gap:           8px;
    --zone-pad:      10px;
    --radius:        10px;

    /* Sacred palette */
    --col-divine:    #c9a84c;       /* gold */
    --col-divine-glow: rgba(201,168,76,0.35);
    --col-crimson:   #8b1a1a;       /* evil border */
    --col-blood:     rgba(139,26,26,0.45);
    --col-evil-bg:   #0e0404;
    --col-right-bg:  #02080f;
    --col-shared:    #080d14;
    --col-board:     #050a10;
    --col-text:      #ddd8c8;
    --col-text-dim:  rgba(221,216,200,0.5);
    --col-accent:    #c9a84c;
    --col-resisted:  #3ab56e;
    --col-failed:    #c0392b;
    --col-active:    #f0c040;
    --col-sapphire:  #1a3a6b;
    --col-sapphire-glow: rgba(26,58,107,0.45);

    /* Phase colors */
    --col-draw:      #4a8fd4;
    --col-play:      #3ab56e;
    --col-evil:      #c0392b;
    --col-resolve:   #e8a020;
    --col-reset:      #8c5dc5;
    --col-cost:       #2ecc71;
    --col-resistance: #7fb3e8;
    --col-main:       #e8c020;
    --col-discard:    #9b7ec8;
}

html, body {
    height: 100%;
    background: var(--col-board);
    color: var(--col-text);
    font-family: 'Nunito Sans', system-ui, sans-serif;
    font-size: 14px;
    overflow: hidden;
    -webkit-font-smoothing: antialiased;
}

/* ─── Sacred Board Background ─────────────────────────────────────────────── */

#board {
    display: grid;
    grid-template-columns: 1fr;
    min-height: 100dvh;
    gap: 4px;
    padding: 4px;
    padding-top: 105px;
    overflow-y: auto;
    overflow-x: hidden;
    max-width: 100vw;

    /* Split atmosphere: corruption bleeds from top, divine light from bottom */
    background:
        radial-gradient(ellipse 120% 50% at 50% 0%,    rgba(60,0,0,0.7)     0%, transparent 60%),
        radial-gradient(ellipse 120% 50% at 50% 100%,  rgba(10,30,70,0.6)   0%, transparent 60%),
        radial-gradient(ellipse 60% 40% at 50% 50%,    rgba(201,168,76,0.04) 0%, transparent 70%),
        linear-gradient(180deg, #060206 0%, #020810 50%, #020810 100%);

    /* Parchment grain texture overlay */
    position: relative;
}

#board::before {
    content: '';
    position: fixed;
    inset: 0;
    background-image:
        url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E");
    background-size: 180px 180px;
    pointer-events: none;
    z-index: 0;
    opacity: 0.6;
}

#board > * { position: relative; z-index: 1; }
#board.hidden { display: none; }

/* Card Designer: per-theme PLAYMAT TINT — a table-wide wash driven by the
   documentElement var --theme-playmat-tint (set by CardRenderer.applyThemeDesign
   for the active theme). Default transparent → invisible, so the table is
   untouched until an admin sets a tint. */
#board::after {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    background: var(--theme-playmat-tint, transparent);
    mix-blend-mode: soft-light;
}

/* ─── Evil Player Area ────────────────────────────────────────────────────── */

.player-area.evil {
    background:
        linear-gradient(135deg, rgba(60,0,0,0.7) 0%, rgba(14,4,4,0.95) 100%);
    border: 1px solid rgba(139,26,26,0.6);
    border-bottom: 1px solid rgba(139,26,26,0.35);
    border-radius: var(--radius);
    padding: 6px var(--zone-pad);
    display: flex;
    flex-direction: column;
    gap: 4px;
    overflow: visible; /* allow stat bar to be fully visible; ::after uses clip on larger screens */
    min-height: 60px;  /* ensure stats bar never gets clipped */
    box-shadow:
        inset 0 1px 0 rgba(200,50,50,0.15),
        0 4px 24px rgba(0,0,0,0.6);
}

/* Middle: shared zones — battlefield */
#shared-zones {
    background:
        radial-gradient(ellipse 80% 100% at 50% 50%, rgba(20,20,10,0.8) 0%, transparent 100%),
        linear-gradient(180deg, rgba(8,6,2,0.9) 0%, rgba(5,10,16,0.9) 100%);
    border: 1px solid rgba(201,168,76,0.18);
    border-radius: var(--radius);
    padding: 6px 16px;
    display: flex;
    align-items: center;
    gap: 16px;
    /* Spread across the full width: Failed pile hugs the left, Resisted the
       right, and the Active zone fills the wide middle — no dead side gutters. */
    justify-content: space-between;
    flex-shrink: 0;
    box-shadow:
        inset 0 0 40px rgba(0,0,0,0.5),
        0 0 0 1px rgba(0,0,0,0.5);
}
#shared-zones > .pile-display { flex: 0 0 auto; }
#shared-zones > .zone-active-shared { flex: 1 1 auto; min-width: 0; }

/* Failed / Resisted moved into the phase bar → the shared-zones strip holds only
   the floating (position:fixed) Active zone, so collapse it to reclaim the row. */
#shared-zones.shared-zones-collapsed {
    min-height: 0 !important; height: 0 !important; padding: 0 !important;
    margin: 0 !important; border: none !important; background: none !important;
    box-shadow: none !important; gap: 0 !important;
}
/* Compact horizontal Failed/Resisted tallies inside the phase bar. */
.phase-bar-piles { display: flex; gap: 8px; align-items: center; flex-shrink: 0; }
.phase-bar-piles .pile-display {
    display: flex; flex-direction: row; align-items: center; gap: 5px;
    padding: 3px 9px; border-radius: 9px; background: rgba(0,0,0,0.28);
    border: 1px solid rgba(201,168,76,0.16);
}
.phase-bar-piles .pile-display.failed   { border-color: rgba(192,57,43,0.3); }
.phase-bar-piles .pile-display.resisted { border-color: rgba(90,150,90,0.3); }
.phase-bar-piles .pile-count { font-size: 16px; font-weight: 700; line-height: 1; }
.phase-bar-piles .pile-display.failed   .pile-count { color: var(--col-evil, #c0392b); }
.phase-bar-piles .pile-display.resisted .pile-count { color: #7ec07e; }
.phase-bar-piles .pile-label {
    font-size: 8.5px; text-transform: uppercase; letter-spacing: .09em;
    opacity: .72; font-family: 'Cinzel', serif;
}
.phase-bar-piles .pile-bar { width: 40px; height: 4px; border-radius: 2px; }
.phase-bar-piles .pile-mini-host { display: none; }   /* no mini-stack in the compact chip */
@media (max-width: 720px) { .phase-bar-piles .pile-label, .phase-bar-piles .pile-bar { display: none; } }

/* Bottom: righteous player area */
.player-area.righteous {
    background:
        linear-gradient(135deg, rgba(10,25,60,0.75) 0%, rgba(2,8,15,0.97) 100%);
    border: 1px solid rgba(26,58,107,0.6);
    border-top: 1px solid rgba(26,58,107,0.4);
    border-radius: var(--radius);
    padding: 6px var(--zone-pad) 4px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    overflow-y: visible;
    min-height: auto;
    box-shadow:
        inset 0 -1px 0 rgba(100,160,255,0.1),
        0 -4px 24px rgba(0,0,0,0.5);
}

/* Active player: bold YOUR TURN indicator */
.player-area.active-player {
    border-color: var(--col-active, #f0c040);
    box-shadow: 0 0 20px rgba(240,192,64,0.25), inset 0 0 15px rgba(240,192,64,0.05);
    position: relative;
}
/* Optional TURN HIGHLIGHT (body.hl-turn — ON by default, toggled by the 🔆
   phase-bar button): wash the CURRENT player's area gold — righteous or evil —
   so whose turn it is reads at a glance. Non-destructive (border + inner/outer
   gold glow, no background-image swap), so themed area backgrounds show through. */
body.hl-turn .player-area.current-turn {
    /* Replace the base (dark-blue / red) area fill with a clear gold-orange
       so it's unmistakable whose turn it is — for every seat, righteous or evil. */
    background:
        radial-gradient(ellipse 130% 70% at 50% 100%, rgba(235,150,40,0.34) 0%, transparent 72%),
        linear-gradient(180deg, rgba(92,64,16,0.96) 0%, rgba(54,37,9,0.96) 100%) !important;
    border-color: rgba(240,196,80,0.95) !important;
    box-shadow: inset 0 0 0 2px rgba(240,196,80,0.6),
                inset 0 0 80px 6px rgba(235,150,40,0.14),
                0 0 26px rgba(235,150,40,0.34) !important;
    transition: background .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.turnhl-toggle.is-off, .hints-toggle.is-off { filter: grayscale(1); }
/* Turn banner injected by GameUI — carries the active player's real name
   so multi-player games show "Alice's Turn" on her area, not a generic
   "YOUR TURN" everywhere. Only present on the active player area. */
.player-area .turn-banner {
    position: absolute;
    top: -1px;
    right: 12px;
    font-family: 'Cinzel', serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: #0a0600;
    background: linear-gradient(90deg, #c9a84c, #f0c040, #c9a84c);
    padding: 2px 10px;
    border-radius: 0 0 6px 6px;
    z-index: 2;
    animation: turnPulse 2s ease-in-out infinite;
    text-transform: uppercase;
    /* Reset button defaults since the banner is now a <button> */
    border: none;
    cursor: pointer;
    font-family: 'Cinzel', serif;
}
.player-area .turn-banner:hover,
.player-area .turn-banner:focus {
    animation: none;
    opacity: 0.95;
    outline: none;
}
@keyframes turnPulse {
    0%, 100% { opacity: 1; }
    50%       { opacity: 0.7; }
}

/* A hidden opponent hand renders no card backs — collapse the fan so it takes
   no vertical space (the "Hand N" count still shows the size). */
.hand-zone.hand-collapsed,
[id$="-hand"].hand-collapsed {
    display: none;
}

/* DUEL: live "thinking" badge on the AI evil seat — top-left of its panel
   (the turn banner sits top-right, so no collision). "Plotting" on its own
   turn, "Waiting" on yours (it acts on its OWN turn, not during yours). */
.player-area .duel-ai-think {
    position: absolute;
    top: -1px;
    left: 12px;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 0 0 6px 6px;
    font-family: 'Nunito Sans', system-ui, sans-serif;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.03em;
    white-space: nowrap;
    box-shadow: 0 2px 8px rgba(0,0,0,0.4);
}
.player-area .duel-ai-think.plotting {
    color: #ffdccf;
    background: linear-gradient(180deg, rgba(158,44,32,0.97), rgba(96,24,18,0.97));
    border: 1px solid rgba(239,110,90,0.6);
}
.player-area .duel-ai-think.waiting {
    color: #d8cba8;
    background: linear-gradient(180deg, rgba(52,46,30,0.94), rgba(34,30,20,0.94));
    border: 1px solid rgba(201,168,76,0.4);
    opacity: 0.9;
}
.player-area .duel-ai-think .dat-dot {
    width: 8px; height: 8px; border-radius: 50%; background: #ff7a5c;
    animation: datPulse 1.05s infinite;
}
@keyframes datPulse {
    0%   { opacity: 0.4; transform: scale(0.8); }
    50%  { opacity: 1;   transform: scale(1.15); }
    100% { opacity: 0.4; transform: scale(0.8); }
}
@media (prefers-reduced-motion: reduce) { .player-area .duel-ai-think .dat-dot { animation: none; } }

/* Active player — golden radiance */
.player-area.active-player {
    border-color: var(--col-active) !important;
    box-shadow:
        0 0 0 1px rgba(240,192,64,0.3),
        0 0 20px rgba(240,192,64,0.15),
        inset 0 0 20px rgba(240,192,64,0.05) !important;
    animation: active-pulse 3s ease-in-out infinite;
}

@keyframes active-pulse {
    0%, 100% { box-shadow: 0 0 0 1px rgba(240,192,64,0.3), 0 0 20px rgba(240,192,64,0.15), inset 0 0 20px rgba(240,192,64,0.05); }
    50%       { box-shadow: 0 0 0 1px rgba(240,192,64,0.5), 0 0 32px rgba(240,192,64,0.25), inset 0 0 28px rgba(240,192,64,0.08); }
}

/* Active zone — strip that appears above the playmat-grid when a player
   has a Maturity or Unction card that's still being resolved. Hidden
   while empty (JS sets display:none). Yellow/gold tint so it reads as
   "currently resolving" and doesn't blend with the green field. */
.zone-active-strip {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    margin: 2px 0;
    background: linear-gradient(90deg,
        rgba(240, 192, 64, 0.18) 0%,
        rgba(240, 192, 64, 0.08) 50%,
        rgba(240, 192, 64, 0.18) 100%);
    border: 1px solid rgba(240, 192, 64, 0.55);
    border-radius: 6px;
    animation: turnPulse 3s ease-in-out infinite;
    flex-shrink: 0;
}
.zone-active-label {
    font-family: 'Cinzel', serif;
    font-size: 10px;
    letter-spacing: 0.14em;
    color: #f0c040;
    text-transform: uppercase;
    padding: 2px 6px;
    background: rgba(240, 192, 64, 0.15);
    border: 1px solid rgba(240, 192, 64, 0.5);
    border-radius: 10px;
    flex-shrink: 0;
}
.zone-active-strip .zone-scrollable {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    min-height: 0;
    flex: 1;
}

/* Sticky-note reminders — for cards with delayed effects ("at your next
   Check phase..."). Lives in the corner of the player area, collapsible,
   glows when the current phase matches the reminder's trigger phase. */
.reminders-panel {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 9;
    display: flex;
    flex-direction: column;
    gap: 4px;
    max-width: 220px;
    pointer-events: auto;
}
.reminder-note {
    background: rgba(230, 210, 100, 0.14);
    border: 1px solid rgba(230, 210, 100, 0.55);
    border-radius: 6px;
    padding: 4px 6px;
    font-family: 'Cinzel', serif;
    font-size: 10px;
    color: #f0d06a;
    box-shadow: 0 2px 6px rgba(0,0,0,0.45);
}
.reminder-note.firing {
    background: rgba(240, 192, 64, 0.3);
    border-color: #f0c040;
    animation: turnPulse 2s ease-in-out infinite;
}
.reminder-head {
    display: flex;
    align-items: center;
    gap: 6px;
}
.reminder-phase {
    font-size: 8px;
    letter-spacing: 0.1em;
    padding: 1px 5px;
    border-radius: 8px;
    background: rgba(240,192,64,0.18);
    border: 1px solid rgba(240,192,64,0.5);
    color: #f0c040;
    flex-shrink: 0;
}
.reminder-title {
    flex: 1;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.reminder-dismiss {
    background: none;
    border: none;
    color: #f0d06a;
    cursor: pointer;
    font-size: 12px;
    padding: 0 2px;
    opacity: 0.7;
}
.reminder-dismiss:hover { opacity: 1; color: #ff8080; }
.reminder-note-text {
    margin-top: 2px;
    font-family: 'Nunito Sans', sans-serif;
    font-size: 10px;
    color: rgba(230, 210, 100, 0.85);
    line-height: 1.3;
    white-space: pre-wrap;
}

/* Host takeover: banner shown over a player area when the local host has
   taken control of a dropped-out guest. Small, unobtrusive, non-clickable. */
.offline-control-badge {
    position: absolute;
    top: 2px;
    right: 6px;
    z-index: 8;
    padding: 2px 8px;
    background: rgba(240, 110, 70, 0.14);
    color: #f1a890;
    border: 1px solid rgba(240, 110, 70, 0.45);
    border-radius: 10px;
    font-family: 'Cinzel', serif;
    font-size: 10px;
    letter-spacing: 0.05em;
    pointer-events: none;
}
.player-area { position: relative; }

/* ─── Zone rows ───────────────────────────────────────────────────────────── */

.zone-row {
    display: flex;
    align-items: flex-end;
    gap: var(--gap);
    min-height: calc(var(--card-h) + 20px);
    flex-shrink: 0;
}
.zone-row > div {
    width: 100%;
    flex: 1;
}

/* Hand zone row */
.zone-row.hand-row {
    align-items: stretch;
    flex-direction: column;
    gap: 0;
}

/* ── Hand toggle button ──────────────────────────────────────────────────── */
.hand-toggle-btn {
    display: flex;
    align-items: center;
    gap: 5px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    text-align: left;
    flex: 1;
    min-width: 0;
}
.hand-toggle-arrow {
    font-size: 10px;
    color: rgba(201,168,76,0.5);
    transition: transform 0.2s ease;
    flex-shrink: 0;
}
.hand-row.hand-collapsed .hand-toggle-arrow {
    transform: rotate(-90deg);
}

/* ── Fan strip — collapsed ────────────────────────────────────────────────── */
.hand-row.hand-collapsed .hand-fan {
    display: none;
}

/* ── Fan strip — expanded ─────────────────────────────────────────────────── */
.hand-fan {
    display: flex;
    flex-wrap: nowrap;
    gap: 0;
    /* GROW to fill the row (it's a flex item — without this it shrinks to its
       cards and sits at the left, so justify-content has nothing to distribute).
       Then center a partial hand so the cards occupy the middle of the segment;
       `safe` falls back to flex-start when the hand overflows so the leftmost
       cards stay reachable/scrollable. */
    flex: 1 1 auto;
    min-width: 0;
    justify-content: safe center;
    overflow: visible;            /* the 3D tilt + arc extend past the row — don't clip */
    padding: 34px 4px 26px;       /* vertical room for the tilted/arced cards */
    scrollbar-width: thin;
    scrollbar-color: rgba(201,168,76,0.2) transparent;
}
.hand-fan::-webkit-scrollbar { height: 3px; }
.hand-fan::-webkit-scrollbar-thumb { background: rgba(201,168,76,0.2); border-radius: 2px; }

/* Fan overlap + ARC: each card peeks out from the previous and is rotated/dipped
   so the hand reads like real held cards (a shallow arc). --fan-rot / --fan-dip
   are set per card in JS (_applyFanArc); the hover rule overrides to lift flat. */
.hand-fan .card-tile {
    margin-right: -28px;
    flex-shrink: 0;
    transition: transform 0.2s cubic-bezier(0.34,1.56,0.64,1), margin-right 0.18s ease;
    position: relative;
    z-index: 1;
    transform-origin: bottom center;
    /* 3D fan: rotateX tips the card TOP outward/back (perspective depth), then the
       in-plane rotate() splays the fan arc. --fan-tiltx flips for the opponent. */
    transform: perspective(760px) rotateX(var(--fan-tiltx, 15deg)) rotate(var(--fan-rot, 0deg)) translateY(var(--fan-dip, 0px));
}
.hand-fan .card-tile:last-child {
    margin-right: 0;
}
/* The hand row must not clip the tall/tilted fan (cards extend above & below). */
.zone-row.hand-row, .hand-row { overflow: visible; }
/* Hand cards render at the larger HAND size (vs the compact zone size). Scale up
   toward life-size on bigger screens; _autoFitHandFan tightens the overlap so the
   fan still fits, so no manual per-width margins are needed. */
.hand-fan .card-tile { width: calc(var(--card-w-hand) * var(--fan-card-scale, 1)); height: calc(var(--card-h-hand) * var(--fan-card-scale, 1)); }
@media (min-width: 900px)  { :root { --card-w-hand: 110px; --card-h-hand: 162px; } }
@media (min-width: 1200px) { :root { --card-w-hand: 130px; --card-h-hand: 192px; } }
@media (min-width: 1600px) { :root { --card-w-hand: 150px; --card-h-hand: 222px; } }
/* Opponent's face-down hand: pivot from the TOP so the fan bows downward, and
   flip the 3D tilt so their card tops lean the opposite way. */
.hand-fan.hand-backs-fan .card-tile { transform-origin: top center; --fan-tiltx: -15deg; }
.hand-fan .card-tile:hover,
.hand-fan .card-tile:focus {
    transform: perspective(760px) rotateX(0deg) translateY(-18px) scale(1.1) rotate(0deg);
    z-index: 10;
    margin-right: 4px;
}

/* Inline hand spread levels (right-click the hand → Spread). */
.hand-fan.spread-compact .card-tile { margin-right: -44px; }
.hand-fan.spread-normal  .card-tile { margin-right: -28px; }
.hand-fan.spread-wide    .card-tile { margin-right: 0; }
.hand-fan.spread-full    .card-tile { margin-right: 6px; }
.hand-fan.spread-compact .card-tile:last-child,
.hand-fan.spread-normal  .card-tile:last-child,
.hand-fan.spread-wide    .card-tile:last-child,
.hand-fan.spread-full    .card-tile:last-child { margin-right: 0; }

/* Full-card mode: cards no longer overlap, but at narrow viewports the
   tiles render so small that the printed cost in the bottom-left card
   badge is illegible. Keep the cost-overlay pill visible regardless of
   spread so the cost number is always readable in hand. */

/* Full-card mode: hand row sizes to the cards — no forced growth, no
   forced max-height, so the row collapses around the cards and any extra
   vertical space stays with the playmat above instead of becoming a gap. */
.zone-row.hand-row:has(.hand-fan.spread-full) {
    max-height: none;
    flex: 0 0 auto;
    min-height: 0;
    overflow: visible;
}
.hand-fan.spread-full {
    align-items: flex-start;
    overflow: visible;
    padding-top: 2px;
    padding-bottom: 2px;
}
.hand-fan.spread-full .card-tile:hover,
.hand-fan.spread-full .card-tile:focus {
    transform: translateY(-6px) scale(1.02);
    margin-right: 6px;
}

/* Hide inline action buttons — use context menu or modal */
.hand-fan .card-action-btn {
    display: none !important;
}

.zone-label {
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--col-text-dim);
    white-space: nowrap;
    font-family: 'Cinzel', serif;
}

.zone-scrollable {
    display: flex;
    flex-wrap: nowrap;
    gap: 4px;
    overflow-x: auto;
    overflow-y: hidden;
    flex: 1;
    padding-bottom: 4px;
    scrollbar-width: thin;
    scrollbar-color: rgba(201,168,76,0.3) transparent;
}

/* The hand fan is ALSO .zone-scrollable, whose overflow-y:hidden clips the tilted
   3D cards. Higher-specificity override so the fan shows the full cards. */
.zone-scrollable.hand-fan { overflow-x: visible; overflow-y: visible; z-index: 5; }
.zone-scrollable::-webkit-scrollbar { height: 3px; }
.zone-scrollable::-webkit-scrollbar-thumb {
    background: rgba(201,168,76,0.3);
    border-radius: 2px;
}

/* ─── Card Tiles ──────────────────────────────────────────────────────────── */

.card-tile {
    position: relative;
    width: var(--card-w);
    height: var(--card-h);
    border-radius: 7px;
    overflow: hidden;
    cursor: pointer;
    flex-shrink: 0;
    transition: transform 0.18s cubic-bezier(0.34,1.56,0.64,1), box-shadow 0.18s ease;
    border: 1px solid rgba(201,168,76,0.15);
    background: #0d0c0a;
    box-shadow: 0 2px 8px rgba(0,0,0,0.6), 0 1px 0 rgba(201,168,76,0.08) inset;
}

.card-tile:hover {
    transform: translateY(-6px) scale(1.04);
    box-shadow:
        0 12px 30px rgba(0,0,0,0.7),
        0 0 0 1px rgba(201,168,76,0.4),
        0 0 16px rgba(201,168,76,0.15);
    z-index: 10;
}

.card-tile.small {
    width: var(--card-w-sm);
    height: var(--card-h-sm);
}

.card-tile.rotated {
    transform: rotate(90deg);
    margin: 0 18px;
    opacity: 0.7;
}

/* Double-click / tap highlight */
.card-tile { cursor: pointer; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; }

.card-counter-badge {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 26px;
    height: 26px;
    /* Card Designer counter nudge/size (default no-op). */
    transform: translate(var(--counter-dx, 0px), var(--counter-dy, 0px)) scale(var(--counter-scale, 1));
    transform-origin: top left;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 20;
    pointer-events: none;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.7));
}
/* Clock icon fills the badge; the count sits centered on its face. */
.card-counter-badge .counter-glyph { display: block; line-height: 0; }
.card-counter-badge .counter-glyph img.card-graphics-img.counter {
    height: 26px; width: 26px; min-height: 0; display: block;
}
.card-counter-badge .counter-glyph-overlay { font-size: 19px; }
.card-counter-badge .counter-glyph-overlay.cg-len2 { font-size: 13px; }
.card-counter-badge .counter-glyph-overlay.cg-len3 { font-size: 10px; }
/* Scale down counter badge on small / cost-zone tiles so it stays legible
   but doesn't dominate the face-down card back. */
.card-tile.small .card-counter-badge,
.playmat-quad.quad-available .card-counter-badge,
.playmat-quad.quad-spent .card-counter-badge {
    width: 18px;
    height: 18px;
    top: 1px;
    left: 1px;
}
.card-tile.small .card-counter-badge .counter-glyph img.card-graphics-img.counter,
.playmat-quad.quad-available .card-counter-badge .counter-glyph img.card-graphics-img.counter,
.playmat-quad.quad-spent .card-counter-badge .counter-glyph img.card-graphics-img.counter {
    height: 18px; width: 18px;
}
.card-tile.small .card-counter-badge .counter-glyph-overlay,
.playmat-quad.quad-available .card-counter-badge .counter-glyph-overlay,
.playmat-quad.quad-spent .card-counter-badge .counter-glyph-overlay { font-size: 13px; }
.card-tile.small .card-counter-badge .counter-glyph-overlay.cg-len2,
.playmat-quad.quad-available .card-counter-badge .counter-glyph-overlay.cg-len2,
.playmat-quad.quad-spent .card-counter-badge .counter-glyph-overlay.cg-len2 { font-size: 9px; }
.card-tile.small .card-counter-badge .counter-glyph-overlay.cg-len3,
.playmat-quad.quad-available .card-counter-badge .counter-glyph-overlay.cg-len3,
.playmat-quad.quad-spent .card-counter-badge .counter-glyph-overlay.cg-len3 { font-size: 7px; }
/* Rotated cards (cost-spent): counter sits in what appears visually as
   top-right since the whole tile is rotated 90°; that's fine — still readable. */
.card-tile:active { transform: scale(0.97); opacity: 0.85; }

/* card-back image */
.card-tile.card-back img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    pointer-events: none;
}

/* Pre-rendered card PNG (exact designer match) */
.ch-card-png {
    width: 100%;
    height: 100%;
    object-fit: contain;
    border-radius: 40px;
    display: block;
    pointer-events: none;
}

/* Larger cards in hand zones */
[id$="-hand"] .card-tile {
    width: var(--card-w-hand);
    height: var(--card-h-hand);
}

[id$="-hand"] .ch-card-root {
    --ch-scale: 0.107;
}

/* Field + Cost zones: small cards */
[id$="-field"] .card-tile,
[id$="-cost"] .card-tile {
    width: var(--card-w-sm);
    height: var(--card-h-sm);
}
[id$="-field"] .ch-card-root,
[id$="-cost"] .ch-card-root { --ch-scale: 0.064; }
.zone-row:has([id$="-field"]),
.zone-row:has([id$="-cost"]) {
    min-height: calc(var(--card-h-sm) + 20px);
}

/* Evil (opponent) hand: full-size backs, fanned like a real held hand — matches
   the righteous hand size so it reads as the opponent actually holding cards. */
.player-area.evil [id$="-hand"] .card-tile {
    width: calc(var(--card-w-hand) * var(--fan-card-scale, 1));
    height: calc(var(--card-h-hand) * var(--fan-card-scale, 1));
}
.player-area.evil .zone-row.hand-row {
    min-height: calc(var(--card-h-hand) + 20px);
}

/* Righteous hand row: height driven by card size */
.player-area.righteous .zone-row.hand-row {
    flex: 0 0 auto;
}
/* Keep card tiles at fixed size; zoom popup shows full card on hover */
.player-area.righteous [id$="-hand"] .card-tile {
    flex-shrink: 0;
}

/* ─── Designer Card Face (scaled to fit card-tile) ─────────────────────────
   .ch-card-scaler fills the card-tile (position:absolute;inset:0;overflow:hidden).
   .ch-card-root is 750×1100px, transform-scaled, matching the designer card exactly.
   Scale 90/750 = 0.12 (normal), 54/750 = 0.072 (small), 130/750 = 0.173 (hand).
─────────────────────────────────────────────────────────────────────────── */

.ch-card-scaler {
    position: absolute;
    inset: 0;
    overflow: hidden;
}

.ch-card-root {
    --ch-scale: 0.096;
    position: absolute;
    top: 0; left: 0;
    width: 750px;
    height: 1100px;
    transform: scale(var(--ch-scale));
    transform-origin: top left;
    box-sizing: border-box;
    background-size: cover;
    background-position: center;
    /* --ch-card-radius: per-theme Card Designer override; default = 40px. */
    border-radius: var(--ch-card-radius, 40px);
    font-family: 'Nunito Sans', system-ui, sans-serif;
    color: #000;
    pointer-events: none;
}

.card-tile.small .ch-card-root { --ch-scale: 0.064; }

/* Frame backgrounds */
.ch-card-root.gold  { background-image: url('/games/christianity/sets/back_FireGrassIceStone4.png'); background-color: #d6aa4c; }
.ch-card-root.fire  { background-image: url('/games/christianity/sets/back_Fire2.png');              background-color: #7a2600; }
.ch-card-root.grass { background-image: url('/games/christianity/sets/back_Grass3.png');             background-color: #1a5a1a; }
.ch-card-root.ice   { background-image: url('/games/christianity/sets/back_Ice4.png');               background-color: #003060; }
.ch-card-root.stone { background-image: url('/games/christianity/sets/back_Stone5.png');             background-color: #303030; }

/* ─ Card interior — matches designer/designerstyles.css exactly ─────────── */

.ch-card-root .card-inner {
    position: absolute;
    inset: 24px;
    border-radius: 28px;
    box-sizing: border-box;
    padding: 18px 22px 22px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.ch-card-root .card-title-bar {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    margin-bottom: 10px;
    margin-top: -15px;
    flex-shrink: 0;
    z-index: 3;
}

.ch-card-root .card-title-pill {
    background: linear-gradient(180deg, rgba(255,255,255,0.92), rgba(255,255,255,0.82));
    border-radius: 16px;
    padding: 6px 18px;
    /* Match designer: BEAGLB (dynamic, may fall back to serif) — DO NOT add
       Cinzel here or the fallback diverges from designer render. */
    font-family: 'BEAGLB', serif;
    font-size: 3.25rem;   /* designer: 2.5rem × 1.3 font-scale */
    font-weight: 600;
    color: #1a0e00;
    box-shadow: 0 2px 0 rgba(0,0,0,0.25);
    max-width: 82%;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Long-title shrink — higher specificity to beat base rule above */
.ch-card-root .card-title-pill.long-title-gt50,
.ch-card-root.fulltext.tallart .card-title-pill.long-title-gt50 { font-size: 1.4em; }
.ch-card-root .card-title-pill.long-title-gt30,
.ch-card-root.fulltext.tallart .card-title-pill.long-title-gt30 { font-size: 1.7em; }
.ch-card-root .card-title-pill.long-title-gt20,
.ch-card-root.fulltext.tallart .card-title-pill.long-title-gt20 { font-size: 2.1em; }

.ch-card-root .card-type-tag {
    position: absolute;
    right: 4px;
    top: 4px;
    background: #ffffff;
    color: #333;
    font-size: 1.5rem;
    font-weight: 600;
    border: 1px solid rgba(0,0,0,0.25);
    border-radius: 6px;
    width: 68px;
    height: 68px;
    text-align: center;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Art panel (non-tallart only) — see note on .card-rules below. */
.ch-card-root:not(.fulltext) .card-art {
    height: 520px;
    flex: none;
    border-radius: 14px;
    overflow: hidden;
    margin-bottom: 10px;
    position: relative;
    background: rgba(0,0,0,0.1);
}

.ch-card-root:not(.fulltext) .card-art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    mask-image: linear-gradient(to bottom, black 0%, black 60%, transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, black 0%, black 60%, transparent 100%);
}

/* Rules panel (non-tallart only) — cards in fulltext.tallart mode are styled
   exclusively by designerstyles.css; scoping with :not(.fulltext) prevents
   specificity collisions when both rule sets want to set background/color. */
.ch-card-root:not(.fulltext) .card-rules {
    flex: 1;
    background: linear-gradient(
        to bottom,
        rgba(255,255,255,0.0)  0%,
        rgba(255,255,255,0.5) 25%,
        rgba(255,255,255,0.75) 100%
    );
    border-radius: 14px;
    padding: 60px 16px 150px;
    margin-top: -80px;
    position: relative;
    z-index: 2;
    min-height: 200px;
    overflow: hidden;
}

.ch-card-root:not(.fulltext) .rules-text {
    font-family: Tahoma, 'Nunito Sans', sans-serif;
    font-size: 4.18rem;   /* designer: 3.22rem × 1.3 */
    line-height: 1.4;
    color: #1a1006;
}

/* `.tkn[Title]{ruletext}` token-shorthand → a MINI-CARD: a small "Create"
   label above a card-style TITLE PILL, with an optional rules panel beneath —
   so it's obvious this card MINTS a Token that carries its own rule text.
   Emitted by CardRenderer.applyShorthands + GameUI._formatRulesText as
   <span class="token-shorthand">
     <span class="tkn-create">Create</span>
     <span class="tkn-pill">Title Token</span>
     <span class="tkn-body">ruletext</span>   (only when ruletext present)
   </span>.
   Unscoped so it styles the board, view-card, thumbnails AND the admin editor
   preview alike; all sizes are em-relative so it scales with the card. */
/* COMPACT so it barely adds vertical height on text-heavy cards: every metric
   is em-based, so the block is measured by AND shrinks with CardRenderer.
   autoFitRulesText (it's a child of .rules-text) — the whole rules block
   (pre-text + mini-card + post-text) auto-fits with no clipping. */
/* "with N [type] counter(s)" line under the token pill. */
.tkn-counters { display: block; font-style: italic; opacity: 0.85; font-size: 0.9em; margin: 0.05em 0; }
/* Dark rotate/tap glyph vanishes on the token's dark body — invert to a light icon. */
.token-shorthand .card-graphics-img.rotate,
.tkn-body .card-graphics-img.rotate { filter: invert(1) brightness(1.7); }
.token-shorthand {
    display: block;
    position: relative;                       /* anchor the corner CREATE tab */
    width: 88%;
    margin: 0.45em auto 0.35em;               /* centered mini-card */
    padding: 1.05em 0.5em 0.45em;             /* top room for the corner tab */
    text-indent: 0;
    text-align: center;
    line-height: 1.18;
    /* A real mini-card face: parchment gradient, gold frame, soft depth. */
    background: linear-gradient(180deg, rgba(255,250,238,0.97), rgba(248,236,212,0.92));
    border: 0.08em solid rgba(184, 140, 54, 0.85);
    border-radius: 0.55em;
    box-shadow: 0 0.12em 0.3em rgba(0,0,0,0.3), inset 0 0 0 0.05em rgba(255,255,255,0.45);
}
/* "CREATE" as a small tab in the TOP-LEFT corner — like a card's type line,
   right where the title text begins. Sits ON the frame, outer corner rounded
   to match the card, inner corner square. */
.token-shorthand .tkn-create {
    position: absolute;
    top: -0.06em;
    left: -0.06em;
    padding: 0.14em 0.55em 0.16em;
    background: linear-gradient(180deg, #e6c052, #b8862f);
    color: #2a1600;
    font-weight: 800;
    font-size: 0.62em;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    line-height: 1;
    border-radius: 0.5em 0 0.45em 0;          /* round outer (top-left) corner only */
    box-shadow: 0 0.06em 0.12em rgba(0,0,0,0.32);
}
/* "TOKEN" label centered in the top band, to the right of CREATE — names the
   kind of thing being made, kept OUT of the title text below. */
.token-shorthand .tkn-type {
    position: absolute;
    top: 0.08em;
    left: 50%;
    transform: translateX(-50%);
    padding: 0.08em 0.5em 0.1em;
    background: linear-gradient(180deg, rgba(184,140,54,0.22), rgba(184,140,54,0.12));
    color: #7a5410;
    font-weight: 800;
    font-size: 0.56em;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    line-height: 1;
    border-radius: 0.4em;
    border: 0.05em solid rgba(184, 140, 54, 0.4);
}
/* TITLE PILL — mirrors the card's .card-title-pill (rounded pill, light
   gradient, subtle border + shadow, centered) at token scale. */
.token-shorthand .tkn-pill {
    display: inline-block;
    max-width: 100%;
    padding: 0.1em 0.7em;
    background: linear-gradient(180deg, rgba(255,255,255,0.94), rgba(255,255,255,0.82));
    border: 0.05em solid rgba(184, 140, 54, 0.7);
    border-radius: 0.9em;        /* pill, matching the card title bar look */
    box-shadow: 0 0.06em 0 rgba(0,0,0,0.2);
    color: #1a0e00;
    /* Sized to the card's own title scale (fits on one line like a real card
       title) — light weight, not the big bold display it was. */
    font-weight: 500;
    font-size: 0.62em;
    line-height: 1.15;
    text-align: center;
    box-sizing: border-box;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Rules panel BENEATH the pill — a bordered/tinted parchment box, like the
   card's rules area. Omitted entirely for title-only tokens (no .tkn-body). */
.token-shorthand .tkn-body {
    display: block;
    width: 96%;
    margin: 0.2em auto 0;
    padding: 0.18em 0.55em 0.2em;
    /* Visible (solid parchment + dark ink) but clearly SMALLER than the title
       pill (which is 0.62em) so the hierarchy title > rules reads at a glance. */
    background: rgba(255, 248, 230, 0.92);
    border: 0.05em solid rgba(184, 140, 54, 0.6);
    border-radius: 0.35em;
    color: #2b1d05;
    font-size: 0.54em;
    font-weight: 600;
    line-height: 1.22;
    text-align: left;
}
/* `.crd[Title]` → a compact card-reference chip inline in rules text. */
.card-ref {
    display: inline-flex;
    align-items: center;
    gap: 0.28em;
    padding: 0.06em 0.44em 0.08em;
    margin: 0 0.06em;
    background: linear-gradient(180deg, rgba(255,255,255,0.95), rgba(244,236,220,0.9));
    border: 0.05em solid rgba(184, 140, 54, 0.7);
    border-radius: 0.5em;
    box-shadow: 0 0.05em 0.1em rgba(0,0,0,0.18);
    color: #1a0e00;
    font-weight: 700;
    font-size: 0.94em;
    white-space: nowrap;
    vertical-align: baseline;
}
.card-ref .card-ref-mark { font-size: 0.9em; opacity: 0.75; }

.ch-card-root:not(.fulltext) .bible-verse {
    font-family: Tahoma, 'Nunito Sans', sans-serif;
    font-size: 2.4rem;    /* designer: 1.85rem × 1.3 */
    font-style: italic;
    color: rgba(26,16,6,0.65);
    margin-top: 10px;
    border-top: 1px solid rgba(26,16,6,0.15);
    padding-top: 8px;
}

.ch-card-root .cost-badge {
    position: absolute;
    left: 11px; bottom: 11px;  /* = inset(24px) - offset(13px) */
    width: 140px; height: 140px;
    border-radius: 16px;
    border: 1px solid #000;
    background: #22a12a;
    box-shadow: 0 6px 14px rgba(0,0,0,0.55), 0 2px 4px rgba(0,0,0,0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 7rem;
    font-weight: 700;
    color: #fff;
    font-family: 'BEAGLB', 'Cinzel', serif;
    z-index: 3;
}

/* X-cost badge: same green as a fixed cost — italic is enough to signal
 * "pay what you want" without also changing the colour, which otherwise
 * reads as a different resource type. */
.ch-card-root .cost-badge.xcost {
    font-style: italic;
}

/* Modified cost (an active "cost less / cost more" effect applies): show the
   ORIGINAL cost struck through above the NEW cost. Green stays for a discount,
   red for an evil "cost more" tax. Sizes are in the 750×1100 card space, so
   they scale down with the rest of the card. */
.ch-card-root .cost-badge.cost-modified {
    flex-direction: column;
    line-height: 0.82;
    gap: 0.4rem;
    font-size: 5rem;
    padding: 0 4px;
}
.ch-card-root .cost-badge.cost-modified .cost-orig {
    font-size: 3.4rem;
    text-decoration: line-through;
    text-decoration-thickness: 0.5rem;
    text-decoration-color: rgba(255,255,255,0.95);
    opacity: 0.72;
}
.ch-card-root .cost-badge.cost-modified .cost-new {
    font-size: 6rem;
}
.ch-card-root .cost-badge.cost-modified.cost-cheaper {
    background: #0f9d58;                        /* brighter green = discounted */
    box-shadow: 0 0 0 4px rgba(120,255,170,0.35), 0 6px 14px rgba(0,0,0,0.55);
}
.ch-card-root .cost-badge.cost-modified.cost-pricier {
    background: #b5322a;                        /* red = evil "cost more" tax */
    box-shadow: 0 0 0 4px rgba(255,140,120,0.35), 0 6px 14px rgba(0,0,0,0.55);
}

/* ─── Card hover zoom popup ──────────────────────────────────────────────── */

#card-zoom-popup {
    position: fixed;
    /* Must be above every draggable/modal dialog (pile modal 2200, penalty
     * 9999, hand modal) yet below the right-click ctx-menu (10100) and
     * confirm dialog (10200). 10095 sits just below pin-panel (10090) —
     * actually above it because pin-panel shows its own card already. */
    z-index: 10095 !important;
    pointer-events: none;
    display: none;
    border-radius: 12px;
    box-shadow: 0 8px 48px rgba(0,0,0,0.85), 0 0 0 2px rgba(201,168,76,0.4);
    overflow: hidden;
    transition: opacity 0.1s ease;
}

#card-zoom-popup .ch-card-root {
    position: absolute;
    top: 0; left: 0;
}

/* ─── Card action buttons ─────────────────────────────────────────────────── */

.card-action-btn {
    position: absolute;
    bottom: 22px;
    font-size: 8px;
    font-weight: 700;
    letter-spacing: 0.04em;
    padding: 3px 6px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s;
    z-index: 5;
    font-family: 'Cinzel', serif;
    text-transform: uppercase;
}

.card-tile:hover .card-action-btn { opacity: 1; }
/* Show buttons dimly on active player hand cards so they're findable without hovering */
.player-area.active-player [id$="-hand"] .card-tile .card-action-btn { opacity: 0.55; }
.player-area.active-player [id$="-hand"] .card-tile:hover .card-action-btn { opacity: 1; }

.play-btn   { left: 2px;  background: linear-gradient(135deg,#27ae60,#1a7a42); color: #fff;
              box-shadow: 0 2px 8px rgba(39,174,96,0.5); }
.yield-btn  { right: 2px; background: linear-gradient(135deg,#2980b9,#1a5a8a); color: #fff;
              box-shadow: 0 2px 8px rgba(41,128,185,0.5); }
.rotate-btn  { left: 50%; transform: translateX(-50%); background: linear-gradient(135deg,#8e44ad,#5c2f73); color: #fff;
               box-shadow: 0 2px 8px rgba(142,68,173,0.5); }
.resist-btn  { left: 2px;  bottom: 2px; background: linear-gradient(135deg,#27ae60,#1a7a42); color: #fff; font-size: 7px; }
.fail-btn    { right: 2px; bottom: 2px; background: linear-gradient(135deg,#c0392b,#8a1a10); color: #fff; font-size: 7px; }
.discard-btn { left: 50%; transform: translateX(-50%); background: linear-gradient(135deg,#b83a2a,#7a1a10); color: #fff; font-size: 7px;
               bottom: 2px; box-shadow: 0 2px 8px rgba(184,58,42,0.5); }

/* Targetable highlight */
.card-tile.targetable {
    box-shadow: 0 0 0 2px var(--col-active), 0 0 20px rgba(240,192,64,0.6);
    animation: target-pulse 0.9s ease-in-out infinite alternate;
}

@keyframes target-pulse {
    from { box-shadow: 0 0 0 2px rgba(240,192,64,0.8), 0 0 12px rgba(240,192,64,0.4); }
    to   { box-shadow: 0 0 0 3px rgba(240,192,64,1.0), 0 0 28px rgba(240,192,64,0.8); }
}

.zone-empty {
    color: rgba(255,255,255,0.12);
    font-size: 10px;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.06em;
    align-self: center;
    padding: 0 8px;
    text-transform: uppercase;
}

/* ─── Shared / Battle Zones ────────────────────────────────────────────────── */

.pile-display {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    min-width: 74px;
}

.pile-count {
    font-family: 'Cinzel', serif;
    font-size: 26px;
    font-weight: 700;
    line-height: 1;
}

.pile-label {
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-family: 'Cinzel', serif;
    opacity: 0.65;
}

.pile-bar {
    width: 100%;
    height: 5px;
    border-radius: 3px;
    appearance: none;
    background: transparent;
}

.pile-bar.resisted::-webkit-progress-bar  { background: rgba(58,181,110,0.15); border-radius: 3px; }
.pile-bar.resisted::-webkit-progress-value{
    background: linear-gradient(90deg, #2a8a52, #3ab56e, #5de698);
    border-radius: 3px;
    box-shadow: 0 0 6px rgba(58,181,110,0.6);
}
.pile-bar.failed::-webkit-progress-bar    { background: rgba(192,57,43,0.15); border-radius: 3px; }
.pile-bar.failed::-webkit-progress-value  {
    background: linear-gradient(90deg, #7a1a10, #c0392b, #e85a48);
    border-radius: 3px;
    box-shadow: 0 0 6px rgba(192,57,43,0.6);
}

.pile-display.resisted .pile-count { color: var(--col-resisted); text-shadow: 0 0 12px rgba(58,181,110,0.4); }
.pile-display.failed   .pile-count { color: var(--col-failed); text-shadow: 0 0 12px rgba(192,57,43,0.4); }

#zone-evil-field-wrap {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    position: relative;
}

#zone-evil-field-wrap::before {
    content: 'Active';
    font-family: 'Cinzel', serif;
    font-size: 9px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(201,100,80,0.55);
    display: block;
}

#zone-evil-field-wrap .zone-label { display: none; } /* handled by ::before */

#zone-evil-field {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    justify-content: center;
    min-height: var(--card-h);
    padding: 4px 8px;
    background: radial-gradient(ellipse 80% 100% at 50% 50%, rgba(40,0,0,0.3) 0%, transparent 100%);
    border-radius: 8px;
    border: 1px solid rgba(139,26,26,0.2);
}

/* ─── Phase HUD Bar ───────────────────────────────────────────────────────── */

#phase-bar {
    display: flex;
    flex-direction: column;
    padding: 6px 12px 4px;
    background: rgba(0,0,0,0.85);
    border: 1px solid rgba(201,168,76,0.2);
    border-radius: 0;
    flex-shrink: 0;
    backdrop-filter: blur(8px);
    gap: 5px;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    width: 100%;
    z-index: 1000;
    box-shadow: 0 2px 16px rgba(0,0,0,0.6), 0 0 0 1px rgba(201,168,76,0.08) inset;
}

/* Row 1: Turn banner */
#turn-banner {
    display: flex;
    align-items: center;
    gap: 10px;
}

#turn-player-name {
    font-family: 'Cinzel', serif;
    font-size: 13px;
    font-weight: 700;
    color: var(--col-active);
    text-shadow: 0 0 10px rgba(240,192,64,0.5);
    flex-shrink: 0;
}

#turn-round-tag {
    font-size: 10px;
    color: var(--col-text-dim);
    font-family: 'Cinzel', serif;
    letter-spacing: 0.04em;
    flex-shrink: 0;
}

/* ─── Turn ownership badge (multiplayer shared-awareness) ─────────────────────
   A strong "is it MY turn?" indicator in the phase bar. Gold/green = yours;
   dim amber = waiting on someone else. During a response window it reads
   "YOUR RESPONSE" / "Waiting for X to respond…". Scoped under #turn-banner so
   it never collides with mobile.css's drawer styles. */
#turn-banner .turn-ownership {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    font-family: 'Cinzel', serif;
    font-weight: 800;
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 3px 12px;
    border-radius: 999px;
    border: 1.5px solid currentColor;
    white-space: nowrap;
    line-height: 1;
}
#turn-banner .turn-ownership .to-icon { font-size: 13px; }
#turn-banner .turn-ownership.is-mine {
    color: #0a0600;
    background: linear-gradient(90deg, #c9a84c, #f4d060, #c9a84c);
    border-color: #f4d060;
    box-shadow: 0 0 14px -2px rgba(240,192,64,0.85);
    animation: turnMinePulse 1.8s ease-in-out infinite;
}
#turn-banner .turn-ownership.is-mine.is-response {
    background: linear-gradient(90deg, #7fb3e8, #b9dcff, #7fb3e8);
    border-color: #b9dcff;
    box-shadow: 0 0 14px -2px rgba(127,179,232,0.85);
}
#turn-banner .turn-ownership.is-waiting {
    color: rgba(221,216,200,0.72);
    background: rgba(20,16,8,0.85);
    border-color: rgba(201,168,76,0.35);
    animation: none;
}
/* Solo/spectate round-progress badge ("Player 1 — Turn 2/4 · Round 3"). */
#turn-banner .turn-ownership.is-progress {
    color: rgba(240,224,170,0.9);
    background: rgba(20,16,8,0.85);
    border-color: rgba(201,168,76,0.4);
    animation: none; font-variant-numeric: tabular-nums;
}
@keyframes turnMinePulse {
    0%, 100% { box-shadow: 0 0 12px -3px rgba(240,192,64,0.7); }
    50%      { box-shadow: 0 0 18px 0 rgba(240,192,64,0.95); }
}
/* Tint the whole banner subtly so the active-player name still reads as "mine"
   vs "theirs" even at a glance. */
#turn-banner.turn-waiting #turn-player-name { color: rgba(221,216,200,0.7); text-shadow: none; }

#turn-phase-label {
    font-family: 'Cinzel', serif;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    margin-left: auto;
    /* A proper pill so the current phase reads as a distinct badge. The phase
       colour tints both the ring and a soft glow. */
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 11px;
    border-radius: 999px;
    border: 1.5px solid currentColor;
    background: color-mix(in srgb, currentColor 16%, rgba(12,10,20,0.9));
    box-shadow: 0 0 12px -2px currentColor, inset 0 0 8px -4px currentColor;
    text-shadow: 0 0 8px currentColor;
    white-space: nowrap;
    transition: background 0.2s, box-shadow 0.2s;
}

/* Phase color classes */
.phase-draw       { color: var(--col-draw);       }
.phase-play       { color: var(--col-play);       }
.phase-evil       { color: var(--col-evil);        }
.phase-resolve    { color: var(--col-resolve);    }
.phase-reset      { color: var(--col-reset);      }
.phase-check      { color: var(--col-draw);        }
.phase-cost       { color: var(--col-cost);       }
.phase-resistance { color: var(--col-resistance); }
.phase-main       { color: var(--col-main);       }
.phase-discard    { color: var(--col-discard);    }

/* Row 2: Phase track */
.phase-track-header {
    font-family: 'Cinzel', serif;
    font-size: 7px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(201,168,76,0.5);
    white-space: nowrap;
    flex-shrink: 0;
    padding-right: 4px;
}

#phase-track {
    display: flex;
    gap: 3px;
    align-items: center;
    /* When the viewport is narrow enough that all phase steps won't fit at
       their readable min-width, fall back to horizontal scroll rather than
       crushing them to unreadable widths. Mobile already enables this in
       mobile.css; applying it here makes narrow desktops / tablets work
       the same way. Scrollbar hidden on mobile; thin on desktop. */
    overflow-x: auto;
    /* side padding so the active step's gold glow isn't clipped at the edges */
    padding: 3px 8px;
    scrollbar-width: thin;
}
#phase-track::-webkit-scrollbar { height: 6px; }
#phase-track::-webkit-scrollbar-thumb { background: rgba(201,168,76,0.25); border-radius: 3px; }

/* Narrow desktops / small tablets: stop the equal-distribute flex:1 from
   squishing steps to a smudge; give each step a readable min-width and
   let the track scroll horizontally when the total won't fit. Above this
   breakpoint, flex:1 distributes evenly across the whole bar. */
@media (max-width: 1100px) {
    #phase-track .phase-step { flex: 0 0 auto; min-width: 62px; }
}

.phase-step {
    flex: 1;
    text-align: center;
    padding: 3px 4px;
    border-radius: 4px;
    border: 1px solid rgba(255,255,255,0.08);
    font-size: 10px;
    cursor: default;
    opacity: 0.5;
    transition: all 0.25s;
    white-space: nowrap;
    overflow: hidden;
    position: relative;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.02em;
    background: rgba(255,255,255,0.03);
    user-select: none;
}

.phase-step .ps-emoji { font-size: 12px; display: block; line-height: 1; }
.phase-step .ps-label { font-size: 8px; display: block; line-height: 1.3; margin-top: 2px; letter-spacing: 0.04em; }
.phase-step.done { opacity: 0.55; background: rgba(255,255,255,0.05); border-color: rgba(255,255,255,0.12); }
.phase-step.active {
    opacity: 1;
    background: rgba(255, 215, 0, 0.22);
    border-color: gold;
    border-width: 2px;
    box-shadow: 0 0 10px rgba(255, 215, 0, 0.5), inset 0 0 6px rgba(255, 215, 0, 0.15);
    color: #ffe87c;
    transform: scaleY(1.08);
    z-index: 1;
}
.phase-step.active[data-phase="evil"] {
    background: rgba(180, 0, 0, 0.35);
    border-color: #ff4444;
    box-shadow: 0 0 12px rgba(255, 50, 50, 0.6), inset 0 0 6px rgba(200, 0, 0, 0.2);
    color: #ff9999;
}
.phase-step.active[data-phase="resistance"] {
    background: rgba(0, 150, 80, 0.35);
    border-color: #44ff88;
    box-shadow: 0 0 12px rgba(50, 255, 120, 0.5), inset 0 0 6px rgba(0, 180, 80, 0.2);
    color: #99ffcc;
}
.phase-step.active[data-phase="main"] {
    background: rgba(50, 100, 220, 0.35);
    border-color: #6699ff;
    box-shadow: 0 0 12px rgba(80, 130, 255, 0.5), inset 0 0 6px rgba(50, 100, 220, 0.2);
    color: #aaccff;
}

/* ── Phase-change animation ──────────────────────────────────────────
   When a cell becomes the newly-active phase, JS adds .phase-advancing
   (~0.75s) so it pops and a light sweeps across it — the player sees the
   phase move from one step to the next. data-advance-dir (fwd|back) sets
   the sweep direction; the cell we just left gets a brief .phase-handoff
   dim-flash. */
@keyframes phase-pop {
    0%   { transform: scaleY(1.08) scale(0.9); }
    45%  { transform: scaleY(1.08) scale(1.16); }
    100% { transform: scaleY(1.08) scale(1); }
}
@keyframes phase-glow-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(255,255,255,0),   0 0 10px rgba(255,255,255,0.4); }
    35%  { box-shadow: 0 0 0 4px rgba(255,255,255,0.4), 0 0 24px rgba(255,255,255,0.85); }
    100% { box-shadow: 0 0 0 0 rgba(255,255,255,0),   0 0 10px rgba(255,255,255,0.35); }
}
.phase-step.phase-advancing {
    animation: phase-pop 0.55s cubic-bezier(.2,1.3,.4,1) both,
               phase-glow-pulse 0.7s ease-out both;
}
/* light sweep across the newly-active cell */
.phase-step.phase-advancing::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,0.6) 50%, transparent 70%);
    transform: translateX(-120%);
    animation: phase-sweep 0.6s ease-out 0.05s both;
}
.phase-step.phase-advancing[data-advance-dir="back"]::after {
    animation: phase-sweep-back 0.6s ease-out 0.05s both;
}
@keyframes phase-sweep      { to   { transform: translateX(120%); } }
@keyframes phase-sweep-back { from { transform: translateX(120%); } to { transform: translateX(-120%); } }
/* brief hand-off flash on the step we just left */
@keyframes phase-handoff {
    0%   { filter: brightness(1.7); opacity: 1; }
    100% { filter: brightness(1);   opacity: 0.55; }
}
.phase-step.phase-handoff { animation: phase-handoff 0.6s ease-out both; }
@media (prefers-reduced-motion: reduce) {
    .phase-step.phase-advancing,
    .phase-step.phase-advancing::after,
    .phase-step.phase-handoff { animation: none !important; }
}

/* Row 3: action area */
#action-bar {
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    align-items: center;
    min-width: 0;
}

#action-bar .btn-primary {
    padding: 6px 14px;
    font-size: 11px;
    flex-shrink: 0;
}

.phase-instructions {
    font-size: 10px;
    color: var(--col-text);
    font-family: 'Nunito Sans', sans-serif;
    letter-spacing: 0.01em;
    flex: 1;
    min-width: 0;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 2px 0;
}

.phase-hint {
    font-size: 9px;
    color: var(--col-divine, #c9a84c);
    font-family: 'Cinzel', serif;
    letter-spacing: 0.04em;
    opacity: 0.8;
    flex-shrink: 0;
    white-space: nowrap;
}

.evil-thinking {
    font-family: 'Cinzel', serif;
    font-size: 11px;
    color: var(--col-evil);
    letter-spacing: 0.06em;
    animation: evil-flicker 1.5s ease-in-out infinite;
}
@keyframes evil-flicker {
    0%, 100% { opacity: 1; }
    50%       { opacity: 0.4; }
}

.btn-primary {
    background: linear-gradient(135deg, #a87b20, var(--col-accent), #d4b060);
    color: #0a0600;
    border: none;
    border-radius: 6px;
    padding: 6px 16px;
    font-size: 11px;
    font-weight: 700;
    cursor: pointer;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.04em;
    transition: all 0.15s;
    box-shadow: 0 2px 10px rgba(201,168,76,0.35), inset 0 1px 0 rgba(255,255,255,0.2);
    text-transform: uppercase;
}
.btn-primary:hover  { box-shadow: 0 4px 16px rgba(201,168,76,0.5), inset 0 1px 0 rgba(255,255,255,0.25); transform: translateY(-1px); }
.btn-primary:active { transform: scale(0.97) translateY(0); }

.log-toggle {
    font-size: 9px;
    padding: 4px 10px;
    background: rgba(255,255,255,0.06);
    color: var(--col-text-dim);
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: 5px;
    cursor: pointer;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.06em;
    transition: all 0.15s;
}
.log-toggle:hover { background: rgba(255,255,255,0.1); color: var(--col-text); }

.phase-bar-btns { display: flex; gap: 4px; align-items: center; flex-shrink: 0; }

.btn-icon {
    width: 28px; height: 28px;
    background: rgba(255,255,255,0.06);
    color: var(--col-text-dim);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 5px;
    cursor: pointer;
    font-size: 13px;
    display: flex; align-items: center; justify-content: center;
    transition: all 0.15s;
    flex-shrink: 0;
}
.btn-icon:hover { background: rgba(201,168,76,0.15); color: var(--col-divine); border-color: rgba(201,168,76,0.3); }

/* ─── Help overlay ────────────────────────────────────────────────────────── */
/* Modal How-to-Play: roomy, and scales up on bigger screens like the game
   menu/settings dialog (docked side-column mode is handled separately below). */
.overlay-wide { max-width: min(94vw, 960px); max-height: 84vh; overflow-y: auto; text-align: left; }
@media (min-width: 1200px) { .overlay-wide { max-width: min(92vw, 1080px); max-height: 86vh; } }
@media (min-width: 1600px) { .overlay-wide { max-width: 1240px; max-height: 88vh; } }
.overlay-wide h2 { text-align: center; }
.overlay-wide h3 { font-family: 'Cinzel', serif; color: var(--col-divine); margin: 16px 0 6px; font-size: 13px; }
.overlay-wide p  { margin: 4px 0 8px; font-size: 13px; line-height: 1.5; color: var(--col-text-dim); }

/* ── How to Play: use the screen on big displays ─────────────────────────
   The base .overlay-box (max-width:340px) is defined LATER in this file and,
   being equal specificity, was overriding .overlay-wide — so the help modal
   collapsed to a tall 340px scroller. Re-assert a wide box with higher
   specificity, and on desktop flow the body into multiple columns so it isn't
   one endless narrow column. */
#help-overlay > .overlay-box.overlay-wide { max-width: min(94vw, 980px); width: auto; }
.help-body { text-align: left; }
@media (min-width: 1000px) {
  #help-overlay > .overlay-box.overlay-wide {
    max-width: min(96vw, 1200px); width: 96vw; max-height: 88vh;
    display: flex; flex-direction: column; overflow: hidden; padding: 26px 30px 18px;
  }
  #help-overlay > .overlay-box.overlay-wide > h2 { flex: 0 0 auto; margin: 0 0 12px; }
  #help-overlay .help-body {
    flex: 1 1 auto; overflow-y: auto; min-height: 0;
    columns: 2; column-gap: 38px; padding-right: 10px; scrollbar-width: thin;
    scrollbar-color: rgba(201,168,76,.35) transparent;
  }
  /* Let phase cards join the column flow instead of being one tall flex block. */
  #help-overlay .help-body .help-phases { display: block; }
  #help-overlay .help-body > *,
  #help-overlay .help-body .help-phase { break-inside: avoid; }
  #help-overlay .help-body .help-phase { margin-bottom: 10px; }
  #help-overlay .help-body h3 { break-after: avoid; margin-top: 4px; }
  #help-overlay .help-body h3:first-child { margin-top: 0; }
  #help-overlay .help-body::-webkit-scrollbar { width: 10px; }
  #help-overlay .help-body::-webkit-scrollbar-thumb { background: rgba(201,168,76,.3); border-radius: 6px; }
  #help-overlay .help-body::-webkit-scrollbar-thumb:hover { background: rgba(201,168,76,.5); }
  #help-overlay .help-body::-webkit-scrollbar-track { background: transparent; }
}
@media (min-width: 1600px) {
  #help-overlay > .overlay-box.overlay-wide { max-width: 1440px; }
  #help-overlay .help-body { columns: 3; }
}

/* Push the help overlay below the fixed phase-bar so the header doesn't
 * hide behind the top strip; phase-bar is ~105px tall (see #board padding). */
#help-overlay { justify-content: flex-start; padding-top: 115px; }
@media (max-width: 1440px) { #help-overlay { padding-top: 100px; } }
@media (max-width: 640px)  { #help-overlay { padding-top: 95px; } }

.overlay-close,
.overlay-dock {
    position: absolute; top: 12px;
    background: none; border: none; color: var(--col-text-dim);
    font-size: 18px; cursor: pointer; padding: 4px 8px;
    border-radius: 4px; transition: color 0.15s;
}
.overlay-close { right: 14px; }
.overlay-dock  { right: 46px; font-size: 16px; }
.overlay-close:hover, .overlay-dock:hover { color: var(--col-text); }
body.help-dock-right .overlay-dock,
body.help-dock-left  .overlay-dock { color: var(--col-accent); }

/* Docked modes: help-overlay becomes a side column instead of a modal.
 * Game area shrinks via --help-dock-width so rules stay visible alongside
 * the play area. Empty overlay area passes pointer events through. */
:root { --help-dock-width: 0px; }
body.help-dock-right,
body.help-dock-left { --help-dock-width: min(440px, 40vw); }

body.help-dock-right #help-overlay,
body.help-dock-left  #help-overlay {
    top: 0; bottom: 0;
    width: var(--help-dock-width);
    align-items: stretch; justify-content: stretch;
    padding: 105px 0 0 0;
    background: rgba(2,4,8,0.35);
    backdrop-filter: blur(4px);
    pointer-events: none;
}
body.help-dock-right #help-overlay { left: auto; right: 0; }
body.help-dock-left  #help-overlay { right: auto; left: 0; }

body.help-dock-right #help-overlay > .overlay-box,
body.help-dock-left  #help-overlay > .overlay-box {
    pointer-events: auto;
    max-width: none; width: 100%;
    max-height: none; height: 100%;
    border-radius: 0;
    border: none;
    padding: 20px 24px;
    overflow-y: auto;
}
body.help-dock-right #help-overlay > .overlay-box {
    border-left: 1px solid rgba(201,168,76,0.3);
    box-shadow: -12px 0 32px rgba(0,0,0,0.6);
}
body.help-dock-left #help-overlay > .overlay-box {
    border-right: 1px solid rgba(201,168,76,0.3);
    box-shadow: 12px 0 32px rgba(0,0,0,0.6);
}
/* Docked into a narrow side column → undo the centered-modal multi-column layout. */
body.help-dock-right #help-overlay > .overlay-box.overlay-wide,
body.help-dock-left  #help-overlay > .overlay-box.overlay-wide { display: block; overflow-y: auto; }
body.help-dock-right #help-overlay .help-body,
body.help-dock-left  #help-overlay .help-body { columns: 1; overflow: visible; padding-right: 0; }

/* Shrink the board and phase-bar so the dock column doesn't overlap the
 * play area. Experience mode has its own width-locking rules that need
 * stronger overrides — see experience.css. */
body.help-dock-right #board     { padding-right: var(--help-dock-width); }
body.help-dock-right #phase-bar { right: var(--help-dock-width); }
body.help-dock-left  #board     { padding-left: var(--help-dock-width); }
body.help-dock-left  #phase-bar { left: var(--help-dock-width); }

.help-phases { display: flex; flex-direction: column; gap: 10px; }

.help-phase {
    display: flex; gap: 12px; align-items: flex-start;
    padding: 10px 12px;
    background: rgba(255,255,255,0.04);
    border-left: 3px solid rgba(201,168,76,0.3);
    border-radius: 6px;
}
.help-phase.auto   { border-left-color: var(--col-draw); opacity: 0.8; }
.help-phase.evil   { border-left-color: var(--col-evil); }

.help-phase-num {
    font-family: 'Cinzel', serif; font-size: 18px; font-weight: 700;
    color: var(--col-divine); min-width: 24px; line-height: 1.2;
}
.help-phase-body { flex: 1; }
.help-phase-body strong { font-size: 13px; color: var(--col-text); }
.help-phase-body p { margin: 4px 0 0; font-size: 12px; color: var(--col-text-dim); }

.auto-badge {
    display: inline-block; padding: 1px 6px;
    background: rgba(74,143,212,0.3); border-radius: 3px;
    font-size: 9px; color: var(--col-draw); letter-spacing: 0.05em;
    font-family: 'Cinzel', serif; vertical-align: middle; margin-left: 4px;
}

.help-tip {
    margin-top: 6px; padding: 6px 10px;
    background: rgba(201,168,76,0.1); border-left: 2px solid var(--col-divine);
    border-radius: 4px; font-size: 12px; color: rgba(221,216,200,0.8);
}

/* ─── Game Menu overlay ───────────────────────────────────────────────────── */
.menu-items { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.menu-item {
    padding: 12px 16px;
    background: rgba(255,255,255,0.05);
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: 7px;
    color: var(--col-text);
    font-family: 'Cinzel', serif; font-size: 13px;
    cursor: pointer; text-align: left;
    transition: all 0.2s;
}
.menu-item:hover { background: rgba(201,168,76,0.12); border-color: rgba(201,168,76,0.3); }
.menu-item.danger { color: var(--col-evil); border-color: rgba(192,57,43,0.25); }
.menu-item.danger:hover { background: rgba(192,57,43,0.15); border-color: var(--col-evil); }

/* ── Redesigned grouped Game Menu ─────────────────────────────────────────
   The old menu was 12 flat buttons (4 of them just for docking the rules
   panel). Now it's grouped into labelled sections with a compact segmented
   control for the rules-panel dock options. */
/* Wider, screen-proportional menu. On roomy screens the sections flow into
   multiple columns so the dialog is broad and short instead of a tall strip.
   Use .overlay-box.menu-box so it beats the base .overlay-box max-width:340px. */
.overlay-box.menu-box {
    max-width: min(94vw, 860px); width: min(94vw, 860px);
    padding: 26px 26px 22px; overflow-x: hidden;
}
@media (min-width: 1500px) { .overlay-box.menu-box { max-width: 1000px; width: 1000px; } }
.menu-scroll {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 14px 20px; align-items: start;
    margin-top: 12px; max-height: 80vh; overflow-y: auto; overflow-x: hidden; padding-right: 4px;
    scrollbar-width: thin; scrollbar-color: rgba(201,168,76,0.35) transparent;
}
/* Let grid children shrink so nothing forces a horizontal scrollbar / cutoff. */
.menu-section, .menu-grid, .menu-seg { min-width: 0; }
.menu-grid .menu-item { min-width: 0; overflow: hidden; }
/* The Quick Toggles row spans the full width so its buttons don't get cramped. */
#menu-toggles-section { grid-column: 1 / -1; }
.menu-scroll::-webkit-scrollbar { width: 6px; }
.menu-scroll::-webkit-scrollbar-thumb { background: rgba(201,168,76,0.35); border-radius: 3px; }
.menu-scroll::-webkit-scrollbar-track { background: transparent; }
.menu-section { display: flex; flex-direction: column; gap: 7px; }
.menu-section-title {
    font-family: 'Cinzel', serif; font-size: 11px; font-weight: 700;
    letter-spacing: 0.16em; text-transform: uppercase;
    color: rgba(201,168,76,0.9);
    border-bottom: 1px solid rgba(201,168,76,0.2);
    padding-bottom: 4px;
}
/* Two-column compact grid so the menu fits without a scrollbar. */
.menu-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
.menu-grid .span2 { grid-column: 1 / -1; }
.menu-scroll .menu-item {
    padding: 11px 13px; font-size: 12.5px; min-height: 46px;
    display: flex; align-items: center; gap: 6px; line-height: 1.15;
}
.menu-item-sub {
    display: block; margin-top: 2px;
    font-family: system-ui, sans-serif; font-size: 10px; font-weight: 400;
    letter-spacing: 0; text-transform: none; color: rgba(230,220,190,0.5);
}
.menu-seg-label {
    font-family: system-ui, sans-serif; font-size: 11px;
    color: rgba(230,220,190,0.6); margin: 2px 0 -2px 2px;
}
.menu-seg { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; }
.menu-seg > button {
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    padding: 9px 4px;
    background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1);
    border-radius: 8px; color: var(--col-text);
    font-family: 'Cinzel', serif; font-size: 11px;
    cursor: pointer; transition: all 0.15s;
}
.menu-seg > button:hover { background: rgba(201,168,76,0.14); border-color: rgba(201,168,76,0.4); }
.menu-seg > button .seg-ic { font-size: 16px; line-height: 1; }

/* Top-bar cluster now holds only the ☰ opener. */
.phase-bar-btns-top { display: flex; gap: 4px; align-items: center; flex-shrink: 0; }

/* The live toggles are injected into #menu-toggles (inside the ☰ menu). Lay them
   out as a comfortable wrapping row of tappable icon buttons. */
#menu-toggles.phase-bar-btns { display: flex; flex-wrap: wrap; gap: 8px; }
#menu-toggles .btn-icon {
    width: 46px; height: 42px; font-size: 19px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(255,255,255,0.05);
    border: 1px solid rgba(201,168,76,0.22); border-radius: 8px;
    color: var(--col-text); cursor: pointer; transition: all 0.15s;
}
#menu-toggles .btn-icon:hover { background: rgba(201,168,76,0.14); border-color: rgba(201,168,76,0.4); }

/* ── Drag-to-play ─────────────────────────────────────────────────────── */
/* Pointer-based drag (native HTML5 drag won't start from the 3D-tilted cards).
   Disable native dragging entirely so it can't interfere with the pointer drag. */
.card-tile.drag-playable,
.card-tile.drag-playable * { -webkit-user-drag: none; }
.card-tile.drag-playable { cursor: grab; }
body.kcc-dragging-card { cursor: grabbing; }
body.kcc-dragging-card .card-tile.drag-playable { cursor: grabbing; }
/* Drag model: playing always goes to the Active zone, so there's no separate
   "active" drop target. The ONLY special drop target is your AVAILABLE cost zone,
   and only when the dragged card can actually be yielded there — highlight it. */
body.kcc-drag-yield .playmat-quad.quad-available,
body.kcc-drag-yield .cost-subzone.cost-available {
    outline: 2px dashed rgba(224,184,76,0.7); outline-offset: -2px;
    background: rgba(201,168,76,0.10);
    transition: outline-color .15s ease, background .15s ease;
}
body.kcc-drag-yield .playmat-quad.quad-available::after {
    content: "⬇ Drop to add to Cost";
    position: absolute; left: 0; right: 0; bottom: 6px; text-align: center;
    color: #f0d890; font-family: 'Cinzel', serif; font-size: 12px; font-weight: 600;
    letter-spacing: .03em; opacity: .85; pointer-events: none;
}
.drag-drop-hot {
    outline: 3px solid rgba(240,208,120,1) !important; outline-offset: -3px;
    background: rgba(201,168,76,0.22) !important;
    box-shadow: inset 0 0 30px rgba(201,168,76,0.4) !important;
}
/* Hovering a zone where the dragged card can't legally go → red "no". */
.drag-drop-invalid {
    outline: 3px dashed rgba(200,70,60,0.95) !important; outline-offset: -3px;
    background: rgba(180,50,45,0.16) !important;
}
/* ✓ / ✕ badge that rides on the drag ghost. */
.drag-ghost-badge {
    position: absolute; top: -10px; right: -10px;
    width: 26px; height: 26px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 16px; font-weight: 800; color: #fff; line-height: 1;
    box-shadow: 0 2px 8px rgba(0,0,0,.5); pointer-events: none;
    transform: scale(0); transition: transform .12s ease;
}
.drag-ghost-badge.ok { background: #3a9d55; transform: scale(1); }
.drag-ghost-badge.no { background: #c0392b; transform: scale(1); }

/* ─── Player stats row ────────────────────────────────────────────────────── */

.player-stats {
    display: flex;
    gap: 8px;
    align-items: center;
    font-size: 11px;
    flex-wrap: wrap;
    padding-bottom: 2px;
    border-bottom: 1px solid rgba(255,255,255,0.06);
    margin-bottom: 2px;
}

.player-name {
    font-weight: 700;
    font-size: 12px;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.04em;
    color: var(--col-accent);
    text-shadow: 0 0 8px rgba(201,168,76,0.3);
}
/* Turn-order badge — a small numbered chip at the start of each seat's stats
   header showing its position (1..N) in the turn rotation. */
.turn-order-badge {
    flex: 0 0 auto; width: 19px; height: 19px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    font: 700 11px/1 var(--mono, ui-monospace, "SF Mono", monospace);
    background: rgba(18,20,28,0.9); color: #e6c052;
    border: 1px solid rgba(201,168,76,0.55); margin-right: 3px;
}
.turn-order-badge.turn-order-active {
    background: #e6c052; color: #1a1508; border-color: #e6c052;
    box-shadow: 0 0 7px rgba(230,192,82,0.65);
}
.player-area.righteous .player-name {
    cursor: pointer;
    transition: text-shadow 120ms ease-out;
}
.player-area.righteous .player-name:hover {
    text-shadow: 0 0 12px rgba(240,208,122,0.7);
}
.player-area.righteous .player-name[title]::after { content: ''; }
/* Tiny pencil glyph appears on hover so users discover the rename action. */
.player-area.righteous .player-name::after {
    content: ' ✎';
    opacity: 0;
    font-size: 0.85em;
    transition: opacity 120ms ease-out;
}
.player-area.righteous .player-name:hover::after { opacity: 0.65; }

.player-area.evil .player-name {
    color: #d06060;
    text-shadow: 0 0 8px rgba(200,60,60,0.3);
}

.stat-badge {
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 5px;
    padding: 2px 8px;
    white-space: nowrap;
    font-size: 10px;
    color: var(--col-text-dim);
}
.stat-badge span { font-weight: 700; color: var(--col-accent); }

/* Cost-zone "mana" readout: unspent/total. Green when you still have cost
 * to spend, amber/grey when everything is tapped this turn. */
.stat-badge.cost-stat.cost-available {
    background: rgba(30,100,40,0.25);
    border-color: rgba(120,220,120,0.45);
    color: #bfeac0;
}
.stat-badge.cost-stat.cost-available span { color: #9cf0a0; }
.stat-badge.cost-stat.cost-empty {
    background: rgba(120,90,20,0.2);
    border-color: rgba(220,180,60,0.4);
    color: #f0d580;
}
.stat-badge.cost-stat.cost-empty span { color: #f0d580; }

/* ─── Win-track progress bars (Maturity pips + Power/Humility fill) ─────────
 * The Maturity and Power/Humility badges get a small visual progress meter so
 * the player can feel "how close am I to winning" at a glance. A badge grows a
 * second line holding the bar; the value text stays on the first line. */
.stat-badge.has-bar {
    display: inline-flex;
    flex-direction: column;
    align-items: stretch;
    gap: 3px;
    min-width: 62px;
}
.stat-bar { display: block; width: 100%; }
.stat-pips { display: flex; gap: 3px; }
.stat-pip {
    flex: 1 1 0;
    height: 4px;
    border-radius: 2px;
    background: rgba(255,255,255,0.14);
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.35);
    transition: background 0.45s ease, box-shadow 0.45s ease;
}
.stat-pip.on {
    background: linear-gradient(90deg, var(--col-accent), #ffe9a8);
    box-shadow: 0 0 6px rgba(201,168,76,0.65);
}
.stat-fill {
    height: 4px;
    border-radius: 2px;
    background: rgba(255,255,255,0.12);
    overflow: hidden;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.35);
}
.stat-fill-inner {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 2px;
    background: linear-gradient(90deg, #6fae7a, #9be0a4);
    box-shadow: 0 0 6px rgba(120,220,140,0.5);
    transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.stat-badge.stat-complete .stat-fill-inner {
    background: linear-gradient(90deg, var(--col-accent), #ffe9a8);
    box-shadow: 0 0 8px rgba(201,168,76,0.7);
}
.stat-badge.stat-complete .stat-pip.on {
    box-shadow: 0 0 8px rgba(201,168,76,0.85);
}
@media (prefers-reduced-motion: reduce) {
    .stat-pip, .stat-fill-inner { transition: none; }
}

/* ─── Co-op evil entity panel ─────────────────────────────────────────────── */

#evil-entity {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.evil-announcement {
    background: rgba(139,26,26,0.8);
    border: 1px solid rgba(200,60,60,0.5);
    border-radius: 6px;
    padding: 4px 12px;
    font-size: 11px;
    font-family: 'Cinzel', serif;
    color: #f0a0a0;
    text-align: center;
    animation: announcement-in 0.3s ease;
}
.evil-announcement.hidden { display: none; }
@keyframes announcement-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ─── Live narration popup (multiplayer shared-awareness) ─────────────────────
   A brief, themed "who did what" flash fired on EVERY client when a new log
   line lands (local action or a guest applySnapshot). The log panel keeps the
   full history; this is the momentary heads-up. Only one shows at a time. */
#kcc-narration {
    position: fixed;
    top: 64px;                 /* clear the fixed #phase-bar */
    left: 50%;
    transform: translateX(-50%);
    z-index: 1400;             /* above board, below win/lose fanfare + modals */
    pointer-events: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    max-width: min(92vw, 560px);
}
.kcc-narration-toast {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 9px 16px;
    border-radius: 12px;
    background: linear-gradient(180deg, rgba(28,22,10,0.97), rgba(14,10,4,0.97));
    border: 1.5px solid rgba(201,168,76,0.55);
    box-shadow: 0 8px 28px -6px rgba(0,0,0,0.8), 0 0 0 1px rgba(201,168,76,0.12) inset;
    color: #f4e9c1;
    font-family: 'Nunito Sans', system-ui, sans-serif;
    font-size: 13.5px;
    font-weight: 600;
    text-align: center;
    opacity: 0;
    transform: translateY(-8px);
    transition: opacity 0.28s ease, transform 0.28s ease;
}
.kcc-narration-toast.show    { opacity: 1; transform: translateY(0); }
.kcc-narration-toast.leaving { opacity: 0; transform: translateY(-8px); }
.kcc-narration-mark { font-size: 15px; flex: 0 0 auto; }
.kcc-narration-text { line-height: 1.25; }

/* ─── Co-op open ally hands (multiplayer shared-awareness) ────────────────────
   In co-op, teammates' hands are face-up so allies coordinate. A teammate's
   hand this browser does NOT control renders clearly SECONDARY — dimmer, a hair
   smaller, and labelled "team-visible" — so it's readable but never mistaken
   for your own. Evil/opponent hands are unaffected (they stay hidden). */
.player-area.coop-ally-open {
    box-shadow: 0 0 0 1px rgba(63,140,110,0.35) inset;
}
.hand-fan.ally-open-hand {
    opacity: 0.82;
    filter: saturate(0.92);
}
.player-area.coop-ally-open::after {
    content: "🤝 Ally's hand — team-visible";
    position: absolute;
    top: 4px;
    left: 10px;
    z-index: 3;
    font-family: 'Cinzel', serif;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: #bfe6cf;
    background: rgba(8,20,14,0.95);
    border: 1px solid rgba(63,140,110,0.5);
    border-radius: 6px;
    padding: 1px 7px;
    pointer-events: none;
    white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
    #turn-banner .turn-ownership.is-mine { animation: none; }
    .kcc-narration-toast { transition: opacity 0.001s linear; transform: none; }
    .kcc-narration-toast.show,
    .kcc-narration-toast.leaving { transform: none; }
}

/* ─── Local-human response countdown (30s, extendable) ───────────────────────
   A pill above the stack bar shown while it's the local human's turn to respond
   in a priority/response window. The AI does NOT advance past this while the
   clock runs; on expiry the human auto-passes. Reduced-motion-safe: the bar
   width is stepped in JS (250ms), no CSS keyframe animation. */
.kcc-resp-timer {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: 118px;             /* sit just above the stack bar (bottom:14px) */
    z-index: 9100;             /* above the stack bar */
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: min(88vw, 340px);
    max-width: min(94vw, 420px);
    padding: 9px 14px 11px;
    background: linear-gradient(180deg, rgba(30,40,64,0.98), rgba(16,22,38,0.98));
    border: 2px solid #6f9be0;
    border-radius: 12px;
    box-shadow: 0 0 20px rgba(90,140,220,0.45), 0 8px 26px rgba(0,0,0,0.55);
    color: #eaf1ff;
    font-family: 'Nunito Sans', system-ui, sans-serif;
}
.kcc-resp-timer.hidden { display: none !important; }
.kcc-resp-row {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 13.5px;
    font-weight: 600;
    white-space: nowrap;
}
.kcc-resp-icon { font-size: 15px; flex: 0 0 auto; }
.kcc-resp-label { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }
.kcc-resp-clock {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-weight: 800;
    font-size: 15px;
    color: #bfe3ff;
    min-width: 3ch;
    text-align: center;
}
.kcc-resp-extend {
    flex: 0 0 auto;
    margin-left: auto;
    cursor: pointer;
    background: linear-gradient(180deg, #bfe3ff, #5a97d6);
    color: #0b1626;
    border: 0;
    border-radius: 8px;
    padding: 5px 11px;
    font-weight: 800;
    font-size: 12.5px;
}
.kcc-resp-extend:hover { filter: brightness(1.08); }
.kcc-resp-track {
    width: 100%;
    height: 7px;
    background: rgba(255,255,255,0.14);
    border-radius: 5px;
    overflow: hidden;
}
.kcc-resp-fill {
    height: 100%;
    width: 100%;
    background: linear-gradient(90deg, #6f9be0, #bfe3ff);
    border-radius: 5px;
    transition: width 0.24s linear;
}
.kcc-resp-timer.kcc-resp-urgent { border-color: #e0a04f; box-shadow: 0 0 20px rgba(224,150,70,0.5), 0 8px 26px rgba(0,0,0,0.55); }
.kcc-resp-timer.kcc-resp-urgent .kcc-resp-clock { color: #ffcf8a; }
.kcc-resp-timer.kcc-resp-urgent .kcc-resp-fill { background: linear-gradient(90deg, #e0a04f, #ffcf8a); }
.kcc-resp-timer.kcc-resp-bumped { box-shadow: 0 0 26px rgba(120,200,140,0.65), 0 8px 26px rgba(0,0,0,0.55); }
@media (prefers-reduced-motion: reduce) {
    .kcc-resp-fill { transition: none; }
    .kcc-resp-timer.kcc-resp-bumped { box-shadow: 0 0 20px rgba(90,140,220,0.45), 0 8px 26px rgba(0,0,0,0.55); }
}

/* ── Automated next-move countdown (bot/AI pacing, extendable) ─────────────── */
/* Distinct from the human response timer: sits a little HIGHER (above where the
   response pill would appear) so the two never literally overlap, and uses an
   amber/gold treatment to read as "the game is auto-playing" rather than "your
   turn to act". */
.kcc-bot-countdown {
    position: fixed;
    /* DEFAULT anchor: BOTTOM-RIGHT so the pill sits out of the way of the play
       area (was bottom-CENTER). The user can drag it anywhere — GameUI persists
       the chosen {right,bottom} (or {left,top}) in localStorage (kcc.botCdPos)
       and re-applies it on show, clamped on-screen. */
    right: 10px;
    left: auto;
    transform: none;
    /* Anchored at the very bottom of the player's screen (safe-area aware). The
       human response timer and this bot countdown never show at once, so sitting
       low here doesn't collide with it. */
    bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    /* Drag from the pill BODY (cursor: move); the ⏸/＋ buttons keep their own
       pointer cursor + clicks (handled in GameUI so drag doesn't hijack them). */
    cursor: move;
    touch-action: none;
    z-index: 9090;             /* just under the human response timer (9100) */
    display: flex;
    flex-direction: column;
    gap: 3px;
    /* FIXED width so the pill never resizes as the cycling intent text changes. */
    width: min(84vw, 270px);
    box-sizing: border-box;
    padding: 5px 9px 6px;
    /* Inconspicuous: dim, translucent, no glow. Brightens a touch on hover so
       it's still legible when the user looks down at it. */
    background: linear-gradient(180deg, rgba(30,25,14,0.78), rgba(18,14,7,0.78));
    border: 1px solid rgba(201,168,76,0.35);
    border-radius: 9px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.4);
    color: rgba(244,236,214,0.82);
    font-family: 'Nunito Sans', system-ui, sans-serif;
    opacity: 0.62;
    transition: opacity 0.25s ease;
}
.kcc-bot-countdown:hover { opacity: 1; }
.kcc-bot-countdown.hidden { display: none !important; }
.kcc-bot-cd-row {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    font-weight: 600;
    white-space: nowrap;
}
.kcc-bot-cd-icon { font-size: 12px; flex: 0 0 auto; opacity: 0.8; }
.kcc-bot-cd-label { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; opacity: 0.85; }
.kcc-bot-cd-clock {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    font-size: 12px;
    color: rgba(255,230,163,0.85);
    min-width: 2.5ch;
    text-align: center;
}
.kcc-bot-cd-extend {
    flex: 0 0 auto;
    margin-left: auto;
    cursor: pointer;
    background: linear-gradient(180deg, rgba(255,230,163,0.85), rgba(201,168,76,0.85));
    color: #241a08;
    border: 0;
    border-radius: 6px;
    padding: 2px 8px;
    font-weight: 800;
    font-size: 12px;
    line-height: 1;
}
.kcc-bot-cd-extend:hover { filter: brightness(1.12); }
.kcc-bot-cd-pause {
    flex: 0 0 auto;
    cursor: pointer;
    background: rgba(255,255,255,0.1);
    color: #f4ecd6;
    border: 1px solid rgba(201,168,76,0.45);
    border-radius: 6px;
    padding: 2px 8px;
    font-weight: 700;
    font-size: 12px;
    line-height: 1;
}
.kcc-bot-cd-pause:hover { background: rgba(255,255,255,0.18); }
.kcc-bot-cd-pause.is-paused {
    background: linear-gradient(180deg, rgba(120,200,140,0.9), rgba(74,160,96,0.9));
    color: #08160c;
    border-color: transparent;
}
/* Paused: brighten the whole pill (override the resting dim) so the frozen
   state reads clearly while the user looks around. */
.kcc-bot-countdown.kcc-bot-cd-paused {
    opacity: 1;
    border-color: rgba(120,200,140,0.6);
}
.kcc-bot-cd-track {
    width: 100%;
    height: 3px;
    background: rgba(255,255,255,0.1);
    border-radius: 3px;
    overflow: hidden;
}
.kcc-bot-cd-fill {
    height: 100%;
    width: 100%;
    background: linear-gradient(90deg, #c9a84c, #ffe6a3);
    border-radius: 5px;
    transition: width 0.2s linear;
}
.kcc-bot-countdown.kcc-bot-cd-bumped { box-shadow: 0 0 12px rgba(120,200,140,0.4), 0 4px 12px rgba(0,0,0,0.4); }
/* "🤔 Thinking about …" — what the AI is contemplating for its UPCOMING move. */
.kcc-bot-cd-intent {
    font-size: 11.5px;
    font-weight: 600;
    color: rgba(255,230,163,0.85);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    /* Always reserve 2 lines so the pill's HEIGHT stays fixed whether the
       intent is one line or two. */
    height: calc(2 * 1.2 * 11.5px);
}
/* Whose-turn label on the "🤔" line — a small bright chip so the user always
   knows who the pending move belongs to. */
.kcc-bot-cd-actor {
    font-weight: 800;
    color: #ffe6a3;
    padding: 0 4px;
    margin-right: 1px;
    border-radius: 4px;
    background: rgba(201,168,76,0.22);
}
/* While cycling through the options the AI is weighing the line reads gold; it
   brightens + pulses once when it SETTLES on the move that will execute. */
.kcc-bot-cd-intent { transition: color 0.2s ease; }
.kcc-bot-cd-intent.settled {
    color: #fff2c8;
    animation: kccIntentSettle 0.35s ease-out;
}
@keyframes kccIntentSettle {
    0%   { transform: scale(1.06); }
    100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .kcc-bot-cd-intent.settled { animation: none; }
}
/* "↩ …" — the PREVIOUS automated move that just played (dim, one line). */
.kcc-bot-cd-last {
    font-size: 10px;
    font-weight: 500;
    color: rgba(244,236,214,0.5);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
@media (prefers-reduced-motion: reduce) {
    .kcc-bot-cd-fill { transition: none; }
    .kcc-bot-countdown.kcc-bot-cd-bumped { box-shadow: 0 0 16px rgba(201,168,76,0.35), 0 8px 24px rgba(0,0,0,0.5); }
}

/* ─── Evil-phase entrance flourish (themed: elephants / dagger volley) ─────── */
.kcc-evilfx-layer {
    position: fixed;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 9080;             /* over the board, under the pacing pills (9090+) */
}
.kcc-evilfx-sprite {
    position: absolute;
    left: 0; top: 0;
    will-change: transform;
    line-height: 1;
    filter: drop-shadow(0 5px 7px rgba(0,0,0,0.55));
}
.kcc-evilfx-proj {
    position: absolute;
    left: 0; top: 0;
    will-change: transform, opacity;
    line-height: 1;
    filter: drop-shadow(0 2px 3px rgba(0,0,0,0.65));
}
.kcc-evilfx-elephants,
.kcc-evilfx-weapons {
    filter: drop-shadow(0 10px 16px rgba(0,0,0,0.5));
    user-select: none;
    -webkit-user-drag: none;
}
.kcc-evilfx-weapons { filter: drop-shadow(0 4px 12px rgba(255,120,30,0.45)); }
/* The whole layer is decorative — suppress it entirely under reduced-motion
   (JS also gates on _fxReduceMotion, this is belt-and-braces). */
@media (prefers-reduced-motion: reduce) {
    .kcc-evilfx-layer { display: none !important; }
}

/* ─── Game Log ────────────────────────────────────────────────────────────── */

#log-panel {
    display: none;
    position: fixed;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 220px;
    max-height: 60vh;
    overflow-y: auto;
    background: rgba(5,8,14,0.92);
    border: 1px solid rgba(201,168,76,0.15);
    border-radius: var(--radius);
    padding: 10px;
    z-index: 100;
    font-size: 10px;
    line-height: 1.6;
    backdrop-filter: blur(8px);
    scrollbar-width: thin;
    scrollbar-color: rgba(201,168,76,0.2) transparent;
}

#log-panel.visible { display: block; }

/* Explicit "user closed the log" state: beats the ≥768px media query that
 * parks the log in the board grid with display:block. Without this, clicking
 * ✕ on desktop was a no-op because the grid rule overrode .visible toggling. */
#log-panel.log-hidden { display: none !important; }
body.log-hidden #board { margin-right: 0 !important; }

/* Bottom-dock mode — pin the log across the bottom of the viewport as its
 * own sheet instead of the right-side grid column. Lets desktop users
 * glance at the log while still seeing the full board width. */
body.log-dock-bottom #log-panel {
    position: fixed !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    top: auto !important;
    transform: none !important;
    width: 100% !important;
    max-height: 32vh !important;
    height: 32vh !important;
    border-radius: 8px 8px 0 0 !important;
    border: 1px solid rgba(201,168,76,0.25) !important;
    border-bottom: none !important;
    z-index: 1200 !important;
    display: block !important;
    padding: 8px 12px !important;
}
body.log-dock-bottom #board { margin-right: 0 !important; padding-bottom: 32vh !important; }

/* Help docked right + log visible: split the right column vertically so
 * both panes can live on the right at once. Help takes the top 55%, log
 * takes the bottom 45%. */
body.help-dock-right.log-open:not(.log-dock-bottom) #help-overlay > .overlay-box {
    max-height: 55vh !important;
    height: 55vh !important;
}
body.help-dock-right.log-open:not(.log-dock-bottom) #log-panel {
    position: fixed !important;
    right: 0 !important;
    top: 55vh !important;
    bottom: 0 !important;
    width: var(--help-dock-width) !important;
    max-height: 45vh !important;
    height: 45vh !important;
    transform: none !important;
    border-radius: 0 !important;
    border-top: 1px solid rgba(201,168,76,0.35) !important;
    z-index: 1001 !important;
    display: block !important;
}

/* When log is open, board gets room reduced so log is part of layout.
   Apply margin ONLY to #board — child zones inside #board already fill
   their grid cell, so adding margin to them double-subtracts width. */
body.log-open #board {
    margin-right: 260px;
    transition: margin-right 0.15s ease;
}
body.log-open #log-panel.visible {
    position: fixed;
    right: 0;
    top: 0;
    bottom: 0;
    transform: none;
    width: 260px;
    max-height: 100vh;
    height: 100vh;
    border-radius: 0;
    display: block;
}

/* ─── Shared dialog chrome: window buttons + roll-up / minimize ───────── */
.dlg-window-btns {
    display: flex;
    gap: 4px;
    align-items: center;
}
.dlg-btn {
    width: 26px;
    height: 26px;
    padding: 0;
    background: rgba(20,20,20,0.6);
    border: 1px solid rgba(201,168,76,0.35);
    color: #f0c040;
    border-radius: 4px;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.dlg-btn:hover {
    background: rgba(40,30,10,0.9);
    border-color: #f0c040;
}
/* Rolled-up state: hide body, show only header. */
.dlg-rolled-up { height: auto !important; resize: none !important; }
.dlg-rolled-up .penalty-body,
.dlg-rolled-up .overlay-body,
.dlg-rolled-up .pile-modal-body,
.dlg-rolled-up .dlg-body  { display: none !important; }
.dlg-rolled-up::after { display: none; }
/* Minimized state: shrink to a small pill, only header text + buttons. */
.dlg-minimized {
    width: auto !important;
    height: auto !important;
    min-width: 0 !important;
    min-height: 0 !important;
    resize: none !important;
}
.dlg-minimized .penalty-body,
.dlg-minimized .overlay-body,
.dlg-minimized .pile-modal-body,
.dlg-minimized .dlg-body { display: none !important; }
.dlg-minimized::after { display: none; }
.dlg-minimized .penalty-drag-handle,
.dlg-minimized .dlg-drag-handle {
    padding: 4px 8px;
}
.dlg-minimized .pen-title,
.dlg-minimized .dlg-title { font-size: 10px; }

/* ─── Penalty floating dialog ────────────────────────────────────────────── */
.penalty-floating .penalty-drag-handle {
    padding: 8px 12px;
    background: rgba(201,56,56,0.25);
    border-bottom: 1px solid rgba(201,168,76,0.3);
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: move;
    user-select: none;
    -webkit-user-select: none;
    flex-shrink: 0;
    touch-action: none;
    position: relative;
    z-index: 2;
}
.penalty-floating .pen-title {
    font-family: 'Cinzel', serif;
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #ff9b6d;
}
.penalty-floating .pen-hint,
.penalty-floating .pen-hint-inline {
    font-size: 10px;
    color: var(--col-text-dim);
    text-transform: none;
    letter-spacing: 0;
}
.penalty-floating .penalty-body {
    padding: 12px 16px;
    overflow-y: auto;
    overflow-x: hidden;
    flex: 1 1 auto;
    min-height: 0;               /* lets flex child shrink so overflow-y actually scrolls */
    -webkit-overflow-scrolling: touch;
    text-align: left;
}
.penalty-floating .pen-close-btn { color: #f19c9c; border-color: rgba(201,56,56,0.5); }
.penalty-floating .pen-close-btn:hover { background: rgba(120,30,30,0.8); border-color: #ff7a7a; color: #fff; }
.penalty-floating.penalty-resolved { border-color: rgba(90,180,90,0.6); }
.penalty-floating .pen-resolved {
    padding: 10px 12px;
    margin: 0 0 10px;
    text-align: center;
    color: #b6e0a0;
    background: rgba(60,120,60,0.18);
    border: 1px solid rgba(90,180,90,0.5);
    border-radius: 6px;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.penalty-floating .pen-headline { text-align: center; margin: 0 0 4px; }
.penalty-floating .pen-subhead  { font-size: 12px; color: var(--col-text-dim); text-align: center; margin: 0 0 8px; }
.penalty-floating .pen-section-label {
    font-size: 11px;
    letter-spacing: 0.08em;
    color: var(--col-text-dim);
    text-transform: uppercase;
    margin-top: 10px;
}
.penalty-floating .pen-section { margin-top: 10px; }
.penalty-floating .pen-lose-power {
    display: block;
    width: 100%;
    padding: 10px;
    margin: 8px 0;
    font-size: 14px;
    font-weight: 700;
    background: rgba(201,56,56,0.2);
    color: #fff;
    border: 1px solid rgba(255,155,109,0.6);
    border-radius: 6px;
    cursor: pointer;
}
.penalty-floating .pen-lose-power:hover { background: rgba(201,56,56,0.35); }

/* Obey-card callout */
.penalty-floating .pen-obey {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    background: rgba(201,56,56,0.08);
    border: 1px solid rgba(201,56,56,0.4);
    border-radius: 6px;
    padding: 10px;
    margin: 10px 0;
}
/* `_makeCardHtml` returns a bare .ch-card-scaler (position:absolute; inset:0).
 * The normal call sites wrap it in a .card-tile which is position:relative, so
 * the scaler pins to the tile. Inside the penalty dialog there is no card-tile
 * wrapper — without the position:relative + fixed box here the scaler climbs
 * up to .penalty-floating and overlays the whole dialog, eating clicks on the
 * Lose Humility button. */
.penalty-floating .pen-obey-card {
    position: relative;
    flex-shrink: 0;
    width: 110px;
    height: 154px;
    min-width: 100px;
    max-width: 120px;
}
.penalty-floating .pen-obey-card .ch-card-scaler { pointer-events: none; }
.penalty-floating .pen-card-tile {
    /* Stretch to fill the parent (.pen-obey-card or .pen-card-visual)
     * so the bare .ch-card-scaler inside pins to its full size instead
     * of the browser default .card-tile width/height. */
    width: 100%;
    height: 100%;
    border-radius: 4px;
    overflow: hidden;
    cursor: zoom-in;
}
.penalty-floating .pen-card-tile .ch-card-scaler { pointer-events: none; }
.penalty-floating .pen-obey-text { flex: 1; min-width: 0; }
.penalty-floating .pen-obey-label {
    font-size: 11px;
    letter-spacing: 0.1em;
    color: #ff9b6d;
    text-transform: uppercase;
    margin-bottom: 4px;
}
.penalty-floating .pen-obey-name {
    font-family: 'Cinzel', serif;
    font-size: 14px;
    color: #f0c040;
    margin-bottom: 6px;
}
.penalty-floating .pen-obey-rules { font-size: 12px; line-height: 1.5; color: var(--col-text); }
.penalty-floating .pen-obey-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 8px 0;
}
.penalty-floating .pen-obey-action {
    background: linear-gradient(180deg, rgba(201,168,76,0.20), rgba(201,168,76,0.08));
    color: #f0c040;
    border: 1px solid rgba(201,168,76,0.55);
    border-radius: 6px;
    padding: 5px 10px;
    font-size: 12px;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}
.penalty-floating .pen-obey-action:hover:not(:disabled) {
    background: linear-gradient(180deg, rgba(201,168,76,0.35), rgba(201,168,76,0.15));
    border-color: #f0c040;
}
.penalty-floating .pen-obey-action:disabled,
.penalty-floating .pen-obey-action.disabled {
    opacity: 0.5;
    cursor: not-allowed;
    color: #aaa;
    border-color: rgba(150,150,150,0.4);
}
.penalty-floating .pen-obey-disabled-note,
.penalty-floating .pen-obey-done-note {
    font-style: italic;
    opacity: 0.85;
    font-size: 0.92em;
}
/* Designerstyles.css defines .rules-text-icon globally at ~32px for the big
 * card face. In the penalty obey text we want them inline-sized like normal
 * body type, so scope an override. */
.penalty-floating .pen-obey-rules .rules-text-icon {
    font-size: 0.9em;
    padding: 0 5px;
    border-radius: 9px;
    box-shadow: 0 0 0 1.5px #fff, 0 1px 0 rgba(0,0,0,0.25);
    line-height: 1.3;
    min-width: 8px;
    vertical-align: middle;
}
/* Humility triangle is drawn with CSS borders (hardcoded px). The global
 * designerstyles.css sizes it for the big card face (~36px tall). Redeclare
 * the borders at tiny-icon scale (8/12px) inline with body text here.
 * `all: unset` strips the .rules-text-icon pill/shadow/padding styles that
 * are applied alongside on the same span; without it the triangle becomes
 * a green oval. */
.penalty-floating .pen-obey-rules .humility-box {
    all: unset;
    position: relative;
    display: inline-block;
    width: 0; height: 0;
    border-left:  8px solid transparent;
    border-right: 8px solid transparent;
    border-bottom: 12px solid #05d587;
    margin: 0 14px 0 6px;           /* keep the surrounding text from touching the triangle */
    vertical-align: -2px;
}
.penalty-floating .pen-obey-rules .humility-box::before,
.penalty-floating .pen-obey-rules .humility-box::after {
    content: "";
    position: absolute;
    width: 0; height: 0;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-bottom: 14px solid #004c2b;
    z-index: -1;
}
.penalty-floating .pen-obey-rules .humility-box::before { top: -1px; left: -10px; }
.penalty-floating .pen-obey-rules .humility-box::after  { top: -2px; left: -10px; }
.penalty-floating .pen-obey-rules .humility-box .humility-text {
    all: unset;
    position: absolute;
    left: 50%;
    top: 8px;
    transform: translate(-50%, -50%);
    font-size: 7px;
    font-weight: 700;
    color: #fff;
    line-height: 1;
    -webkit-text-stroke: 0.6px #00170c;
    text-shadow: 0 0 2px rgba(0,0,0,0.8);
    white-space: nowrap;
    pointer-events: none;
}
.penalty-floating .pen-obey-rules .card-graphics-img { height: 1.1em; width: auto; vertical-align: middle; }
/* Designer's .tilde-box has lightgoldenrodyellow background with no text
 * color set globally — on the tallart card face `color: black` is applied
 * separately. Everywhere else the inherited light text color makes the
 * tilde-box unreadable. Force dark ink in the penalty obey + ctx rules. */
.penalty-floating .pen-obey-rules .tilde-box,
.ctx-title .ctx-title-rules .tilde-box {
    color: #2a1a0a;
    font-weight: 600;
    text-shadow: none;
    -webkit-text-stroke: 0;
}
.penalty-floating .pen-obey-rules .tilde-box .rules-text-icon,
.ctx-title .ctx-title-rules .tilde-box .rules-text-icon { color: #fff; }
/* Designerstyles .cost-colon is 2.8rem for the big card face — shrink here
 * so the ":" following a cost-box reads as inline punctuation. */
.penalty-floating .pen-obey-rules .cost-colon,
.ctx-title .ctx-title-rules .cost-colon {
    font-size: 1em;
    font-weight: bold;
    margin-left: 1px;
    vertical-align: middle;
}
/* icon_rotate / icon_refresh PNGs are solid-black-on-transparent so they
 * disappear against the dark penalty background. Designerstyles already
 * inverts them on the tallart card face; mirror that here. */
.penalty-floating .pen-obey-rules .card-graphics-img.rotate,
.penalty-floating .pen-obey-rules .card-graphics-img.refresh {
    filter: invert(1);
}
.penalty-floating .pen-destination {
    margin-top: 8px;
    padding: 6px 8px;
    font-size: 11px;
    line-height: 1.4;
    border-radius: 4px;
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.08);
    color: var(--col-text-dim);
}
.penalty-floating .pen-destination-habitual {
    background: rgba(201,56,56,0.14);
    border-color: rgba(201,56,56,0.5);
    color: #ffb99a;
}

/* Card grid (both Hand and Cost-Zone sections) */
.penalty-floating .pen-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 8px;
    margin-top: 6px;
}
/* Cost-zone section renders face-down stacks; shrink to board-scale thumbnails
 * (roughly the in-play cost-zone size) so the fail dialog does not dominate. */
.penalty-floating .pen-section.pen-section-costzone .pen-card-grid {
    grid-template-columns: repeat(auto-fill, minmax(72px, 90px));
    gap: 6px;
}
.penalty-floating .pen-card-slot {
    position: relative;
    border: 1px solid rgba(201,168,76,0.3);
    border-radius: 6px;
    padding: 4px;
    background: rgba(0,0,0,0.3);
    overflow: hidden;
    min-height: 140px;
    display: flex;
    flex-direction: column;
}
/* Face-down cost-zone slot is much smaller — the card isn't being read,
 * just picked. Matches board cost-zone sizing more closely. */
.penalty-floating .pen-card-slot.face-down-fixed {
    min-height: 0;
    padding: 2px;
}
.penalty-floating .pen-card-slot.face-down-fixed .pen-card-back-img {
    min-height: 104px;
    height: 104px;
    flex: 0 0 104px;
}
.penalty-floating .pen-card-slot.face-down-fixed .pen-card-back-img .pen-back-index {
    font-size: 9px;
    bottom: 2px;
    right: 3px;
    padding: 0 3px;
}
.penalty-floating .pen-card-slot.face-down-fixed .pen-discard-btn {
    padding: 2px 6px;
    font-size: 9px;
    margin-top: 3px;
}
.penalty-floating .pen-card-visual  { flex: 1 1 auto; min-height: 80px; position: relative; overflow: hidden; }
/* Cost-zone face-down slot: pure card-back image, no reveal affordance. */
.penalty-floating .pen-card-back-img {
    flex: 1 1 auto;
    min-height: 140px;
    position: relative;
    background-color: #000;
    background-size: cover;
    background-position: center;
    border-radius: 4px;
    border: 1px solid rgba(201,168,76,0.35);
    box-shadow: 0 2px 6px rgba(0,0,0,0.5), inset 0 0 0 1px rgba(0,0,0,0.5);
    pointer-events: none;
}
.penalty-floating .pen-card-back-img .pen-back-index {
    position: absolute;
    bottom: 4px;
    right: 6px;
    font-family: 'Cinzel', serif;
    font-size: 10px;
    letter-spacing: 0.1em;
    color: #f0c040;
    background: rgba(0,0,0,0.55);
    border: 1px solid rgba(201,168,76,0.5);
    border-radius: 3px;
    padding: 1px 4px;
}
.penalty-floating .pen-card-btns {
    display: flex;
    gap: 4px;
    justify-content: flex-end;
    margin-top: 4px;
    flex-shrink: 0;
    position: relative;
    z-index: 2;
}
.penalty-floating .pen-discard-btn {
    padding: 3px 8px;
    border-radius: 4px;
    font-size: 10px;
    cursor: pointer;
    background: rgba(160,40,40,0.9);
    color: #fff;
    border: 1px solid rgba(255,155,109,0.8);
}
.penalty-floating .pen-discard-btn:hover { background: rgba(200,60,60,0.95); }
/* Native resize handle (bottom-right) — make it more visible */
.penalty-floating::after {
    content: '';
    position: absolute;
    right: 2px;
    bottom: 2px;
    width: 14px;
    height: 14px;
    background:
        linear-gradient(135deg, transparent 50%, rgba(201,168,76,0.5) 50%);
    pointer-events: none;
}

.log-panel-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 2px 4px 6px;
    border-bottom: 1px solid rgba(201,168,76,0.15);
    margin-bottom: 4px;
    font-family: 'Cinzel', serif;
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--col-accent);
    position: sticky;
    top: 0;
    background: rgba(5,8,14,0.95);
    z-index: 1;
}
.log-panel-close {
    background: transparent;
    border: 1px solid rgba(201,168,76,0.3);
    color: var(--col-text-dim);
    width: 22px;
    height: 22px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 12px;
    line-height: 1;
    padding: 0;
}
.log-panel-close:hover {
    color: var(--col-text);
    border-color: var(--col-accent);
}

.log-entry {
    border-bottom: 1px solid rgba(255,255,255,0.04);
    padding: 3px 0;
    color: var(--col-text-dim);
}
.log-entry:last-child { border-bottom: none; color: var(--col-text); }
/* Inline cost pills in log lines ("combo −C1 (paid C4)") — same green box the
 * card rules text uses, sized to read inline (mirrors .ctx-title-rules). */
.log-entry .rules-text-icon {
    display: inline-block;
    border-radius: 9px;
    font-size: 0.9em;
    padding: 0 5px;
    color: #fff;
    font-weight: bold;
    min-width: 10px;
    text-align: center;
    line-height: 1.3;
    vertical-align: baseline;
}
.log-entry .cost-box { background: #22a12a; box-shadow: 0 0 0 1.5px #5a5a5a, 0 1px 0 rgba(0,0,0,0.3); }

/* ─── Overlays ────────────────────────────────────────────────────────────── */

.overlay {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    /* Above #phase-bar (z-index 1000) so the main menu / help / win /
     * penalty overlays don't peek out from under the sticky top bar. */
    z-index: 1100;
    background: rgba(2,4,8,0.88);
    backdrop-filter: blur(10px);
}

.overlay.hidden { display: none; }

.overlay-box {
    background: linear-gradient(160deg, rgba(14,10,4,0.98) 0%, rgba(4,8,20,0.98) 100%);
    border: 1px solid rgba(201,168,76,0.25);
    border-radius: 16px;
    padding: 36px 32px;
    text-align: center;
    max-width: 340px;
    width: 90%;
    box-shadow:
        0 0 0 1px rgba(0,0,0,0.8),
        0 32px 80px rgba(0,0,0,0.8),
        inset 0 1px 0 rgba(201,168,76,0.1);
}

.overlay-box h2 {
    font-family: 'Cinzel Decorative', 'Cinzel', serif;
    font-size: 20px;
    margin-bottom: 14px;
    color: var(--col-accent);
    text-shadow: 0 0 20px rgba(201,168,76,0.4);
    letter-spacing: 0.05em;
}

.overlay-box p {
    font-size: 13px;
    color: var(--col-text-dim);
    margin-bottom: 22px;
    line-height: 1.6;
}

.pass-name {
    font-family: 'Cinzel', serif;
    font-size: 24px;
    font-weight: 700;
    color: #fff;
    display: block;
    margin: 8px 0 18px;
    text-shadow: 0 0 20px rgba(201,168,76,0.3);
}

/* ─── Toast / Error ───────────────────────────────────────────────────────── */

#error-toast {
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    background: linear-gradient(135deg, #7a1a10, #c0392b);
    color: #fff;
    padding: 10px 24px;
    border-radius: 24px;
    font-size: 12px;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.04em;
    z-index: 300;
    transition: opacity 0.3s;
    box-shadow: 0 4px 20px rgba(192,57,43,0.5);
}
#error-toast.hidden { opacity: 0; pointer-events: none; }

/* ─── Loading screen ──────────────────────────────────────────────────────── */

#loading-screen {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background:
        radial-gradient(ellipse 90% 60% at 50% 30%, rgba(80,0,0,0.45) 0%, transparent 70%),
        radial-gradient(ellipse 80% 60% at 50% 80%, rgba(15,40,90,0.45) 0%, transparent 70%),
        radial-gradient(ellipse 80% 60% at 50% 50%, #08060a, #020408);
    font-family: 'Cinzel', serif;
    letter-spacing: 0.08em;
    z-index: 400;
    color: var(--col-accent);
    gap: 22px;
    padding: 24px;
}
#loading-screen .loading-logo {
    max-width: min(460px, 72vw);
    height: auto;
    filter: drop-shadow(0 0 20px rgba(201,168,76,0.35));
    opacity: 0;
    animation: loading-logo-in 0.9s ease-out 0.05s forwards;
    user-select: none;
    -webkit-user-drag: none;
}
#loading-screen .loading-title {
    font-size: clamp(18px, 3.2vw, 26px);
    text-transform: uppercase;
    color: #f0d07a;
    text-shadow: 0 0 10px rgba(201,168,76,0.4), 0 2px 0 rgba(0,0,0,0.6);
    opacity: 0;
    animation: loading-logo-in 0.9s ease-out 0.25s forwards;
}
#loading-screen .loading-subtitle {
    display: block;
    font-size: 0.55em;
    letter-spacing: 0.3em;
    color: rgba(201,168,76,0.75);
    margin-top: 4px;
}
#loading-screen .loading-beta-badge {
    display: inline-block;
    padding: 3px 14px;
    font-family: 'Cinzel', serif;
    font-size: 12px;
    letter-spacing: 0.3em;
    font-weight: 700;
    color: #f0d07a;
    background: rgba(40, 28, 8, 0.9);
    border: 1px solid rgba(201,168,76,0.55);
    border-radius: 4px;
    text-transform: uppercase;
    box-shadow: 0 0 8px rgba(201,168,76,0.25);
}
#loading-screen .loading-build {
    font-family: 'Nunito Sans', system-ui, sans-serif;
    font-size: 11px;
    letter-spacing: 0.12em;
    color: rgba(201,168,76,0.5);
    margin-top: 4px;
    text-transform: uppercase;
}
#loading-screen .loading-progress-track {
    width: min(320px, 64vw);
    height: 4px;
    background: rgba(201,168,76,0.12);
    border: 1px solid rgba(201,168,76,0.25);
    border-radius: 3px;
    overflow: hidden;
    position: relative;
    box-shadow: 0 0 8px rgba(0,0,0,0.6) inset;
}
#loading-screen .loading-progress-fill {
    position: absolute;
    inset: 0;
    width: 40%;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(201,168,76,0.55) 20%,
        #f0d07a 50%,
        rgba(201,168,76,0.55) 80%,
        transparent 100%);
    animation: loading-sweep 1.8s ease-in-out infinite;
    box-shadow: 0 0 12px rgba(240,208,122,0.6);
}
/* Determinate mode — once a real % comes in, stop the shimmer
 * sweep and grow the fill from the left edge instead. */
#loading-screen.loading-determinate .loading-progress-fill {
    left: 0;
    animation: none;
    background: linear-gradient(90deg, rgba(201,168,76,0.75), #f0d07a, rgba(201,168,76,0.75));
    transition: width 0.3s ease-out;
}
#loading-screen.loading-done .loading-progress-fill {
    width: 100%;
    animation: none;
    background: linear-gradient(90deg, rgba(201,168,76,0.55), #f0d07a, rgba(201,168,76,0.55));
}
#loading-screen .loading-step {
    font-size: 12px;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: rgba(240,208,122,0.75);
    min-height: 1.2em;
}
#loading-screen.error-state .loading-progress-fill {
    background: linear-gradient(90deg, rgba(160,40,40,0.55), #d64545, rgba(160,40,40,0.55));
    animation: none;
    width: 100%;
}
#loading-screen.error-state .loading-step { color: #ff9191; }
@keyframes loading-logo-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes loading-sweep {
    0%   { left: -40%; }
    100% { left: 100%; }
}
#loading-screen.hidden { display: none; }

/* ─── Win screen ──────────────────────────────────────────────────────────── */

#win-screen .overlay-box {
    border-color: rgba(201,168,76,0.4);
    box-shadow:
        0 0 0 1px rgba(0,0,0,0.8),
        0 0 80px rgba(201,168,76,0.15),
        0 32px 80px rgba(0,0,0,0.8);
}
#win-screen .overlay-box h2 { font-size: 26px; }
#win-screen .win-role {
    font-family: 'Cinzel Decorative', 'Cinzel', serif;
    color: var(--col-accent);
    font-size: 30px;
    font-weight: 900;
    display: block;
    margin: 10px 0;
    text-shadow: 0 0 30px rgba(201,168,76,0.6);
    letter-spacing: 0.05em;
}
#win-screen .win-reason { font-size: 13px; opacity: 0.65; }

/* Above the turn-1 tutorial chips (z 1500) so nothing floats over the payoff. */
#win-screen { z-index: 2000; }
#win-screen .overlay-box { position: relative; z-index: 2; overflow: hidden; }

/* Victory — triumphant gold, glow + scale-in reveal. */
#win-screen.win-victory .overlay-box {
    border-color: rgba(201,168,76,0.75);
    background: linear-gradient(160deg, rgba(40,30,8,0.98) 0%, rgba(10,20,44,0.98) 100%);
    box-shadow:
        0 0 0 1px rgba(0,0,0,0.8),
        0 0 90px rgba(201,168,76,0.35),
        0 32px 80px rgba(0,0,0,0.85);
    animation: winReveal 0.6s cubic-bezier(0.18, 1.2, 0.4, 1) both;
}
#win-screen.win-victory .overlay-box h2 { color: #ffe9a8; text-shadow: 0 0 24px rgba(201,168,76,0.6); }
#win-screen.win-victory .win-role {
    color: #ffe9a8;
    animation: winGlow 2.4s ease-in-out infinite alternate;
}

/* Defeat — somber, desaturated, a quieter reveal. */
#win-screen.win-defeat .overlay-box {
    border-color: rgba(150,70,70,0.55);
    background: linear-gradient(160deg, rgba(26,10,10,0.98) 0%, rgba(10,10,14,0.98) 100%);
    box-shadow:
        0 0 0 1px rgba(0,0,0,0.85),
        0 0 60px rgba(130,35,35,0.22),
        0 32px 80px rgba(0,0,0,0.85);
    animation: loseReveal 0.55s ease-out both;
}
#win-screen.win-defeat .overlay-box h2 { color: #d98a8a; text-shadow: 0 0 18px rgba(160,45,45,0.4); }
#win-screen.win-defeat .win-role {
    color: #e0a0a0;
    text-shadow: 0 0 20px rgba(140,45,45,0.4);
}

@keyframes winReveal {
    0%   { opacity: 0; transform: scale(0.6) translateY(20px); }
    60%  { transform: scale(1.06); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}
@keyframes loseReveal {
    0%   { opacity: 0; transform: scale(0.94) translateY(-8px); filter: blur(4px); }
    100% { opacity: 1; transform: scale(1) translateY(0); filter: blur(0); }
}
@keyframes winGlow {
    from { text-shadow: 0 0 20px rgba(201,168,76,0.5); }
    to   { text-shadow: 0 0 40px rgba(255,220,120,0.95), 0 0 70px rgba(201,168,76,0.5); }
}

/* Falling confetti (victory only; JS builds the pieces, CSS animates them). */
.win-confetti {
    position: fixed;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 1;
}
.win-confetti-piece {
    position: absolute;
    top: -8vh;
    width: 9px;
    height: 14px;
    border-radius: 2px;
    opacity: 0.9;
    animation-name: confettiFall;
    animation-timing-function: linear;
    animation-iteration-count: 1;
    animation-fill-mode: both;
}
@keyframes confettiFall {
    0%   { transform: translateY(-10vh) translateX(0) rotate(0deg); opacity: 0; }
    10%  { opacity: 1; }
    100% { transform: translateY(112vh) translateX(var(--drift, 0)) rotate(720deg); opacity: 0.9; }
}
@media (prefers-reduced-motion: reduce) {
    #win-screen.win-victory .overlay-box,
    #win-screen.win-defeat .overlay-box,
    #win-screen.win-victory .win-role { animation: none; }
    .win-confetti { display: none; }
}

/* ─── Responsive: iPad landscape ──────────────────────────────────────────── */

@media (min-width: 768px) {
    :root {
        --card-w:       100px;
        --card-h:       140px;
        --card-w-hand:  90px;
        --card-h-hand:  133px;
        --gap:          10px;
    }

    #board {
        grid-template-columns: 1fr 175px;
        grid-template-rows: auto auto auto;
        grid-template-areas:
            "evil-area   log"
            "shared      log"
            "right-area  log";
        padding: 8px;
        padding-top: 110px;
        gap: 6px;
    }

    .player-area.evil      { grid-area: evil-area; max-height: none; }
    #shared-zones           { grid-area: shared; }
    .player-area.righteous  { grid-area: right-area; }
    #log-panel              { grid-area: log; position: static; transform: none; width: auto; max-height: 100%; display: block; }

    /* Phase steps: show full labels on desktop */
    .phase-step             { padding: 5px 6px; }
    .phase-step .ps-label   { font-size: 9px; display: block; }
    .phase-step .ps-emoji   { font-size: 14px; }

    /* Hand card scale factor */
    [id$="-hand"] .ch-card-root { --ch-scale: calc(0.12 * var(--fan-card-scale, 1)); }
}

/* ─── Lobby ───────────────────────────────────────────────────────────────── */

body.lobby {
    overflow: auto;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 20px;
    min-height: 100dvh;
    background:
        radial-gradient(ellipse 80% 60% at 50% 20%, rgba(40,20,0,0.6) 0%, transparent 60%),
        radial-gradient(ellipse 60% 40% at 50% 80%, rgba(10,25,60,0.5) 0%, transparent 60%),
        #050a10;
}

.lobby-container {
    max-width: 480px;
    width: 100%;
}

.lobby-container h1 {
    font-family: 'Cinzel Decorative', 'Cinzel', serif;
    font-size: 26px;
    color: var(--col-accent);
    text-align: center;
    margin-bottom: 4px;
    text-shadow: 0 0 24px rgba(201,168,76,0.4);
    letter-spacing: 0.05em;
}

.lobby-container .subtitle {
    text-align: center;
    color: var(--col-text-dim);
    margin-bottom: 24px;
    font-size: 12px;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.lobby-section {
    background: rgba(255,255,255,0.03);
    border: 1px solid rgba(201,168,76,0.12);
    border-radius: var(--radius);
    padding: 16px;
    margin-bottom: 12px;
    backdrop-filter: blur(4px);
}

.lobby-section h3 {
    font-family: 'Cinzel', serif;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--col-accent);
    opacity: 0.7;
    margin-bottom: 12px;
}

.form-row { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.form-row label { font-size: 11px; opacity: 0.7; font-family: 'Cinzel', serif; letter-spacing: 0.05em; text-transform: uppercase; }

.form-row input,
.form-row select {
    background: rgba(255,255,255,0.05);
    border: 1px solid rgba(201,168,76,0.15);
    color: var(--col-text);
    border-radius: 7px;
    padding: 8px 12px;
    font-size: 14px;
    width: 100%;
    font-family: 'Nunito Sans', sans-serif;
    transition: border-color 0.15s;
    outline: none;
}
.form-row input:focus,
.form-row select:focus { border-color: rgba(201,168,76,0.45); box-shadow: 0 0 0 3px rgba(201,168,76,0.08); }
.form-row select option { background: #0d0c0a; }

.theme-picker {
    display: flex;
    gap: 8px;
}

.theme-btn {
    flex: 1;
    padding: 12px 8px;
    border: 1px solid rgba(201,168,76,0.15);
    background: rgba(255,255,255,0.03);
    color: var(--col-text);
    border-radius: 8px;
    cursor: pointer;
    font-size: 11px;
    font-weight: 700;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.04em;
    text-align: center;
    transition: all 0.15s;
}

.theme-btn:hover { border-color: rgba(201,168,76,0.4); background: rgba(201,168,76,0.06); }
.theme-btn.selected { border-color: var(--col-accent); background: rgba(201,168,76,0.12); color: var(--col-accent); }

.theme-btn .theme-icon { font-size: 26px; display: block; margin-bottom: 6px; }

.btn-start {
    width: 100%;
    background: linear-gradient(135deg, #9a6e10, var(--col-accent), #d4b060);
    color: #0a0600;
    border: none;
    border-radius: 8px;
    padding: 14px;
    font-size: 14px;
    font-weight: 700;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
    margin-top: 8px;
    transition: all 0.15s;
    box-shadow: 0 4px 20px rgba(201,168,76,0.3);
}
.btn-start:hover { box-shadow: 0 6px 28px rgba(201,168,76,0.45); transform: translateY(-1px); opacity: 0.93; }

/* ─── Rules Text Formatting Badges ──────────────────────────────────────────── */

/* SQUARE badge: equal width/height for single digits ("1", "2", "X") with
 * near-square corners; longer content widens but keeps the height. */
.ch-card-root .rules-text-icon {
    display: inline-block;
    box-sizing: border-box;
    border-radius: 0.18em;
    font-size: 0.72em;
    padding: 0 0.22em;
    color: white;
    box-shadow: 0 0 0 2px #fff, 0 2px 0 rgba(0,0,0,0.3);
    font-weight: bold;
    min-width: 1.35em;
    height: 1.35em;
    line-height: 1.35em;
    text-align: center;
    vertical-align: middle;
}

.ch-card-root .cost-box {
    background: #22a12a;
    box-shadow: 0 0 0 2px #5a5a5a, 0 2px 0 rgba(0,0,0,0.3);
}

.ch-card-root .draw-to-hand-box {
    background: #2892ff;
}

.ch-card-root .negative-box {
    background: #a12222;
}

.ch-card-root .discard-from-cost-zone-box {
    background: #958f8f;
}

.ch-card-root .cost-colon {
    font-weight: bold;
    margin-left: 1px;
    vertical-align: middle;
}

/* Inline number boxes (C#, D#, S#, A#) inside a rendered card's rules text.
   The autofit pins .rules-text-icon font-size to a FIXED fraction (~0.72em on
   the board) of the fitted rules font, so the pill rendered SMALLER than the
   #rot#/#ctr# graphics glyphs (height:1em / 1.15em) and the words on the same
   line. Track the fitted rules font instead so every inline element sits at the
   same visual height. !important beats the inline px pin the autofit writes;
   the (0,3,0) selector also outranks the game.css .rules-text-icon base. */
.ch-card-root .rules-text .cost-box,
.ch-card-root .rules-text .draw-to-hand-box,
.ch-card-root .rules-text .discard-from-cost-zone-box,
.ch-card-root .rules-text .negative-box {
    font-size: 0.82em !important;   /* box height = 1.35em × 0.82em ≈ 1.1em, matching #rot#/#ctr# */
    vertical-align: -0.16em;        /* baseline-align with the 1em graphics icons */
}

/* Humility triangle badge */
.ch-card-root .humility-box {
    all: unset;
    position: relative;
    display: inline-block;
    width: 0;
    height: 0;
    border-left: 18px solid transparent;
    border-right: 18px solid transparent;
    border-bottom: 26px solid #05d587;
    top: -4px;
    /* Only a hair of side margin so the triangle hugs adjacent words like the
       other inline boxes (designerstyles' .rules-text copy wins in-card, but
       keep this consistent for non-.rules-text contexts). */
    margin: 0 0.1em;
    vertical-align: middle;
}
.ch-card-root .humility-box::before {
    content: "";
    position: absolute;
    width: 0;
    height: 0;
    border-left: 21px solid transparent;
    border-right: 21px solid transparent;
    border-bottom: 30px solid #004c2b;
    top: 0px;
    left: -21px;
    z-index: -1;
}
.ch-card-root .humility-box::after {
    content: "";
    position: absolute;
    width: 0;
    height: 0;
    border-left: 21px solid transparent;
    border-right: 21px solid transparent;
    border-bottom: 30px solid #004c2b;
    top: -6px;
    left: -21px;
    z-index: -1;
}
.ch-card-root .humility-box .humility-text {
    all: unset;
    position: absolute;
    left: 50%;
    top: 18px;
    transform: translate(-50%, -50%);
    font-size: 0.72em;
    font-weight: bold;
    color: white;
    -webkit-text-stroke: 0.6px #00170c;
    text-shadow: -1px 0 1px #00160b, 1px 0 1px #00160b, 0 1px 1px #00160b, 0 0 3px #000;
    white-space: nowrap;
}

/* Tilde box */
.ch-card-root .tilde-box {
    font-size: 0.8em;
    background: lightgoldenrodyellow;
    border-radius: 6px;
    display: inline-block;
    padding: 1px 4px;
    color: #333;
}
.ch-card-root .tilde-box.tilde-D {
    background: #2892ff;
    color: white;
}
.ch-card-root .tilde-box.tilde-BB {
    background: rgba(208,250,249,0.85);
    display: inline-block;
    padding: 2px 4px;
    width: 97%;
    box-sizing: border-box;
}
.ch-card-root .tilde-box.tilde-U {
    background: #abecc5;
    color: black;
}
.ch-card-root .tilde-box .desc { display: none; }

/* Card type icons inline — size with surrounding text so they scale at
   zoom/preview, with a hard floor for the small card-grid render. */
.ch-card-root .card-graphics-img {
    height: 1.3em;
    min-height: 22px;
    width: auto;
    vertical-align: middle;
    display: inline;
}

/* Math symbols */
.ch-card-root .math-symbol {
    font-weight: bold;
    font-size: 1em;
}

/* Cost-zone coin pill — styling comes from designerstyles.css (gold gradient
   circle). We intentionally do NOT override it here; the designer CSS is
   loaded ahead of game.css in game.php / experience/game.php. */

/* Type icon in card-type-tag (matches designer img.ctype) */
.ch-card-root .card-type-icon-img {
    height: 100px;
    width: auto;
    display: block;
    background: transparent !important;
}

/* Per-type icon transforms (copied from designer img.ctype rules) */
.ch-card-root img.ctype.ctype-Maturity   { transform: rotate(-20deg); margin-top: -58px; margin-left: -27px; width: 128px; }
.ch-card-root img.ctype.ctype-Unction    { transform: rotate(-20deg); margin-top: -40px; margin-left: 10px; }
.ch-card-root img.ctype.ctype-Temptation { transform: rotate(-90deg); margin-top: -62px; margin-left: -29px; width: 128px; }
.ch-card-root img.ctype.ctype-Resistance { margin-top: -40px; margin-left: -25px; width: 120px; height: auto; }
.ch-card-root img.ctype.ctype-Habitual   { margin-top: -45px; margin-left: -10px; }

/* Type-specific card-type-tag background (matches designer) */
.ch-card-root .card-type-tag.card-type-Unction    { background: #ffda67; }
.ch-card-root .card-type-tag.card-type-Maturity   { background: #c8f4b0; }
.ch-card-root .card-type-tag.card-type-Resistance { background: #cacaca; }
.ch-card-root .card-type-tag.card-type-Habitual   { background: rgb(175,136,79); color: white; }
.ch-card-root .card-type-tag.card-type-Temptation { background: #ffb2b2; }

/* ─── Tall-art (fulltext tallart) — game-side glue only ──────────────────── */
/* designerstyles.css provides the full layout; we only override what the     */
/* game needs differently (card-inner must stay absolutely positioned within  */
/* the transform-scaled .ch-card-root, not relative/offset like designer).    */

.ch-card-root.fulltext.tallart .card-inner {
    position: absolute !important;
    inset: 24px !important;
    left: 24px !important;
    height: auto !important;
    display: block !important;
    /* Let the tilted type-tag icon extend toward the card's silver frame
       instead of being clipped at the inner 24px boundary. */
    overflow: visible !important;
}

/* Designer targets #previewArt / #previewType / #previewCopyrightText by ID;
   CardRenderer's shared-mode output has no such IDs, so we replicate those
   rules with class selectors scoped to the game's ch-card-root tallart mode. */
.ch-card-root.fulltext.tallart .card-art img {
    height: 150%;
    max-height: 1000px;
    /* --art-overlay-opacity: per-theme Card Designer override; default = 0.5.
       (kittens forces opacity:1 !important elsewhere, so it's unaffected.) */
    opacity: var(--art-overlay-opacity, 0.5);
}
.ch-card-root.fulltext.tallart .copyright-line {
    /* --copyright-scale: per-theme Card Designer footer size multiplier (1 = default). */
    font-size: calc(1.1rem * var(--font-scale, 1.3) * var(--copyright-scale, 1));
}

/* ── Card Designer: cost-gem nudge / resize (per-theme; default no-op) ─────────
   The cost badge has no base transform, so translate(0,0) scale(1) is a no-op
   until an admin moves/resizes the gem in the Card Designer. */
.ch-card-root .cost-badge {
    transform: translate(var(--cost-gem-dx, 0px), var(--cost-gem-dy, 0px)) scale(var(--cost-gem-scale, 1));
    transform-origin: bottom left;
}

/* ══════════════════════════════════════════════════════════════════════════
   CARD DESIGNER — ELEMENT PLACEMENT (Round 3 P1)
   ───────────────────────────────────────────────────────────────────────────
   Additive transforms / insets driven by CSS vars on the card root. Every var
   defaults to a NO-OP so the base layout is untouched until an admin nudges an
   element in the Designer. Transforms don't change sibling layout, so autoFit +
   the footer/cost anchoring keep working.
   ══════════════════════════════════════════════════════════════════════════ */
.ch-card-root .card-title-bar {
    transform: translate(var(--title-dx, 0px), var(--title-dy, 0px)) scale(var(--title-scale, 1));
    transform-origin: top center;
    /* default = the base `center`; the Designer sets flex-start/center/flex-end. */
    justify-content: var(--title-align, center);
}
.ch-card-root.fulltext.tallart .card-rules {
    transform: translate(var(--rules-dx, 0px), var(--rules-dy, 0px));
}
.ch-card-root.fulltext.tallart .card-art {
    transform: translateY(var(--art-dy, 0px)) scale(var(--art-scale, 1));
    transform-origin: top center;
}
.ch-card-root.fulltext.tallart .card-footer {
    transform: translate(var(--footer-dx, 0px), var(--footer-dy, 0px));
}

/* COST-GEM CORNER (P1) — reposition the cost gem to any corner. Default 'bl'
   keeps the base left:11px/bottom:11px. The rules-text cutout follows via
   --cost-corner (autoFit). transform-origin flips so scaling stays in-corner. */
.ch-card-root.cost-corner-br .cost-badge { left: auto; right: 11px; bottom: 11px; top: auto; transform-origin: bottom right; }
.ch-card-root.cost-corner-tl .cost-badge { left: 11px; right: auto; top: 11px; bottom: auto; transform-origin: top left; }
.ch-card-root.cost-corner-tr .cost-badge { left: auto; right: 11px; top: 11px; bottom: auto; transform-origin: top right; }

/* CARD NUMBER element (P2) — its own positioned element, independent of the
   copyright. Hidden by default (only created when the Designer enables it).
   Position corners / footer; three styles (plain / badge / edge). */
.ch-card-root .card-number-badge {
    position: absolute;
    z-index: 7;
    font-family: 'BEAGLB', 'Cinzel', serif;
    font-size: calc(2.2rem * var(--cardnum-scale, 1));
    font-weight: 700;
    color: #1a0e00;
    line-height: 1;
    pointer-events: none;
    white-space: nowrap;
}
.ch-card-root .card-number-badge.cardnum-pos-tl { top: 26px;  left: 30px;  }
.ch-card-root .card-number-badge.cardnum-pos-tr { top: 26px;  right: 30px; }
.ch-card-root .card-number-badge.cardnum-pos-bl { bottom: 30px; left: 30px; }
.ch-card-root .card-number-badge.cardnum-pos-br { bottom: 30px; right: 30px; }
.ch-card-root .card-number-badge.cardnum-pos-footer { bottom: 28px; right: 70px; left: auto; top: auto; }
/* Badge style: pill plate behind the number. */
.ch-card-root .card-number-badge.cardnum-style-badge {
    background: linear-gradient(180deg, rgba(255,255,255,0.94), rgba(255,255,255,0.82));
    border: 2px solid rgba(0,0,0,0.35);
    border-radius: 12px;
    padding: 4px 14px;
    box-shadow: 0 3px 8px rgba(0,0,0,0.45);
}
/* Edge style: a compact chip riding the frame edge, light on dark. */
.ch-card-root .card-number-badge.cardnum-style-edge {
    background: rgba(0,0,0,0.6);
    color: #f4e8c8;
    border-radius: 8px;
    padding: 3px 10px;
    font-size: calc(1.7rem * var(--cardnum-scale, 1));
    text-shadow: 0 1px 2px #000;
}

/* COST-GEM CUTOUT — an invisible float that makes the rules text WRAP AROUND
   the cost gem (bottom-left) instead of rendering hidden underneath it. Its
   height + shape-outside polygon are set per-card by autoFitRulesText (only the
   bottom-left square is excluded). No paint, no pointer events. */
.ch-card-root .rules-text .rules-cost-cutout {
    float: left;
    width: 140px;               /* overwritten inline by autoFit (gem scale) */
    height: 0;                  /* overwritten inline by autoFit (box height) */
    margin: 0;
    background: none;
    pointer-events: none;
    /* shape-outside set inline by autoFit; default reserves nothing. */
}

/* ══════════════════════════════════════════════════════════════════════════
   CARD DESIGNER — CARD BACKGROUNDS + NO-ART POLISH  (Task #49 P5)
   ───────────────────────────────────────────────────────────────────────────
   Backgrounds fill the ART region: they tint behind the semi-transparent art
   on illustrated cards and — crucially — make NO-ART cards look intentional
   instead of an empty black hole. Applied as `card-bg-<name>` on the root by
   CardRenderer.applyThemeDesign; colors from --bg-color-1/2 (Designer). The
   `dsg-artfill` class (no-art polish, or any background chosen) keeps the art
   slot visible when a card has no image so its background shows.
   ══════════════════════════════════════════════════════════════════════════ */
.ch-card-root[class*="card-bg-"] .card-art,
.ch-card-root.dsg-artfill .card-art {
    --bg-c1: var(--bg-color-1, #33373f);
    --bg-c2: var(--bg-color-2, #14161b);
}
/* Graceful default fill for a no-art card even when NO explicit background is
   chosen (comes first so an explicit card-bg-* below wins). */
.ch-card-root.dsg-artfill .card-art {
    background:
        radial-gradient(circle at 50% 34%, rgba(255,255,255,0.06), transparent 60%),
        linear-gradient(160deg, rgba(255,255,255,0.05), rgba(0,0,0,0.32));
}
.ch-card-root.card-bg-solid    .card-art { background: var(--bg-c1); }
.ch-card-root.card-bg-gradient .card-art { background: linear-gradient(135deg, var(--bg-c1), var(--bg-c2)); }
.ch-card-root.card-bg-vertical .card-art { background: linear-gradient(180deg, var(--bg-c1), var(--bg-c2)); }
.ch-card-root.card-bg-radial   .card-art { background: radial-gradient(circle at 50% 38%, var(--bg-c1), var(--bg-c2)); }
.ch-card-root.card-bg-dots     .card-art {
    background-color: var(--bg-c2);
    background-image: radial-gradient(var(--bg-c1) 18%, transparent 19%);
    background-size: 46px 46px;
}
.ch-card-root.card-bg-grid     .card-art {
    background-color: var(--bg-c2);
    background-image:
        linear-gradient(var(--bg-c1) 2px, transparent 2px),
        linear-gradient(90deg, var(--bg-c1) 2px, transparent 2px);
    background-size: 60px 60px;
}
.ch-card-root.card-bg-diagonal .card-art {
    background: repeating-linear-gradient(45deg, var(--bg-c1) 0 18px, var(--bg-c2) 18px 36px);
}
.ch-card-root.card-bg-parchment .card-art {
    background:
        radial-gradient(ellipse at 30% 20%, rgba(255,255,255,0.07), transparent 60%),
        radial-gradient(ellipse at 75% 80%, rgba(0,0,0,0.18), transparent 55%),
        linear-gradient(160deg, var(--bg-c1), var(--bg-c2));
}
/* Per-element GENERATED background IMAGE (Round 5 P3): a saved bg-<element>.jpg
   fills the art region. --elem-bg-image is set inline by applyThemeDesign. */
.ch-card-root.card-bg-image .card-art {
    background-image: var(--elem-bg-image);
    background-size: cover;
    background-position: center;
}

/* ══════════════════════════════════════════════════════════════════════════
   CARD DESIGNER — PER-ELEMENT BORDER  (Round 5 P3)
   A ring around the card for cards of a given colour element. Drawn with an
   inset box-shadow on .card-inner (decorative, above art, below content is fine
   since content sits inside .card-inner). --dsg-border-w / --dsg-border-color
   set inline; default none until an admin sets a per-element border.
   ══════════════════════════════════════════════════════════════════════════ */
.ch-card-root.dsg-border .card-inner {
    --dsg-bw: var(--dsg-border-w, 2px);
    --dsg-bc: var(--dsg-border-color, var(--frame-accent, #cda63a));
}
.ch-card-root.dsg-border-solid .card-inner  { box-shadow: inset 0 0 0 var(--dsg-bw) var(--dsg-bc); }
.ch-card-root.dsg-border-double .card-inner { box-shadow: inset 0 0 0 var(--dsg-bw) var(--dsg-bc), inset 0 0 0 calc(var(--dsg-bw) * 2.2) rgba(0,0,0,0.35), inset 0 0 0 calc(var(--dsg-bw) * 3.2) var(--dsg-bc); }
.ch-card-root.dsg-border-dashed .card-inner { border: var(--dsg-bw) dashed var(--dsg-bc); box-sizing: border-box; }
.ch-card-root.dsg-border-glow .card-inner   { box-shadow: inset 0 0 0 var(--dsg-bw) var(--dsg-bc), inset 0 0 calc(var(--dsg-bw) * 6) var(--dsg-bc); }
/* Type-tag tilts out over the art top-right (designer #previewType rotation).
   The inner img (.ctype.ctype-*) is wider than the 70px tag and extends right
   via negative margins. Set `right` and `top` explicitly (overriding base's
   right:4px top:4px and height:68px) so the icon stays inside ch-card-root's
   750px bounds after the rotate+scale expands its visual footprint, which
   matters because card-pin-scaler / card-tile have overflow:hidden that
   clip at the ch-card-root's edge. */
.ch-card-root.fulltext.tallart .card-type-tag {
    position: absolute;
    /* --type-tag-dx/dy/scale: per-theme Card Designer nudge / resize (default no-op). */
    right: calc(50px - var(--type-tag-dx, 0px));
    top: calc(40px + var(--type-tag-dy, 0px));
    width: 70px;
    height: auto;
    overflow: visible;
    transform: rotate(45deg) scale(calc(1.1 * var(--type-tag-scale, 1)));
    border: 1px solid darkgray;
    background: #ffffff;
    padding: 4px 10px;
    border-radius: 8px;
    text-align: center;
}

/* Per-ICON tilt exceptions: some themed icons must NOT take the jaunty 45°
   tag tilt — a BUILDING reads wrong when tipped. The kittens cat tower
   (Good Habitual / Watch Post) stays upright. To exempt another icon, add
   its .cimgref-<IconRef> to this selector list. */
.ch-card-root.fulltext.tallart .card-type-tag:has(.cimgref-Habitual_Good_kittens) {
    transform: rotate(0deg) scale(calc(1.1 * var(--type-tag-scale, 1)));
}

/* Zone sublabel (e.g. "Available / Spent") */
.zone-sublabel {
    font-size: 0.65em;
    opacity: 0.55;
    font-style: italic;
    margin-left: 4px;
}



/* ── Cost zone Available / Spent split ───────────────────────── */
.zone-row > div > .cost-zone-container,
.zone-row .cost-zone-container {
    display: flex;
    align-items: stretch;
    width: 100%;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid rgba(255,255,255,0.12);
    min-height: 70px;
}

.cost-subzone {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.cost-available {
    background: rgba(34, 130, 56, 0.30);
}

.cost-spent {
    background: rgba(200, 85, 50, 0.30);
}

.cost-zone-divider {
    display: flex;
    align-items: center;
    writing-mode: vertical-rl;
    text-orientation: mixed;
    font-size: 0.55rem;
    font-family: 'Cinzel', serif;
    color: rgba(255,255,255,0.45);
    background: rgba(255,255,255,0.07);
    padding: 10px 3px;
    letter-spacing: 0.15em;
    border-left: 1px solid rgba(255,255,255,0.1);
    border-right: 1px solid rgba(255,255,255,0.1);
    text-transform: uppercase;
    white-space: nowrap;
    user-select: none;
}

.cost-subzone > .zone-label {
    font-size: 0.58rem;
    padding: 3px 6px 1px;
    opacity: 0.55;
    letter-spacing: 0.08em;
}

.cost-subzone > .zone-scrollable {
    flex: 1;
    padding: 4px;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-content: flex-start;
}

/* Playmat background option — enabled via .playmat-bg on #board */
#board.playmat-bg {
    background-image: url('img/playmat-chr.png');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

#board.playmat-bg .player-area,
#board.playmat-bg #shared-zones {
    background: rgba(0,0,0,0.6);
    backdrop-filter: blur(2px);
}

/* ─── Context Menu ────────────────────────────────────────────────────────── */

.ctx-menu {
    position: fixed;
    z-index: 12100;               /* above the replay bar (12000) / caption (11999/12010), penalty overlay (9999) and hover zoom so right-click ALWAYS wins */
    min-width: 180px;
    /* Never taller than the viewport; scrolls internally if the menu has more
       items than fit. JS also flips above the cursor when there's no room. */
    max-height: calc(100vh - 16px);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: #1a1a1a;
    border: 1px solid rgba(201,168,76,0.35);
    border-radius: 8px;
    box-shadow: 0 8px 32px rgba(0,0,0,0.7), 0 0 0 1px rgba(0,0,0,0.5);
    padding: 4px 0;
    font-family: 'Nunito Sans', sans-serif;
    animation: ctx-appear 0.12s ease-out;
    /* Mobile long-press on a menu item otherwise raises the text-selection
       magnifier + "Copy / Look Up…" callout, which eats the tap. Suppress
       selection and the iOS callout for the whole menu + its descendants. */
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    -webkit-tap-highlight-color: transparent;
}
.ctx-menu, .ctx-menu * { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }

@keyframes ctx-appear {
    from { opacity: 0; transform: scale(0.92); }
    to   { opacity: 1; transform: scale(1); }
}

.ctx-title {
    font-family: 'Cinzel', serif;
    font-size: 10px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(201,168,76,0.7);
    padding: 6px 14px 4px;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    margin-bottom: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ctx-title.ctx-title-with-thumb {
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: normal;        /* allow the name to wrap next to the thumb */
    padding: 8px 12px;
    /* Pin the title+thumb to the top of the (scrollable) ctx menu so it
     * stays visible while the user scrolls through a long item list —
     * especially useful on mobile where the menu is a bottom sheet. */
    position: sticky;
    top: 0;
    background: #1a1a1a;
    z-index: 2;
    backdrop-filter: blur(6px);
}
.ctx-title .ctx-title-text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ctx-title .ctx-title-name {
    font-family: 'Cinzel', serif;
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(201,168,76,0.85);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Card-type pill under the name (Habitual, Unction, Maturity, etc.). */
.ctx-title .ctx-title-type {
    font-family: 'Nunito Sans', system-ui, sans-serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: rgba(230,220,200,0.9);
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 4px;
    padding: 2px 6px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    width: fit-content;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ctx-title .ctx-title-type .ctx-type-icon {
    height: 14px; width: auto; flex-shrink: 0;
    vertical-align: middle;
    filter: drop-shadow(0 1px 1px rgba(0,0,0,0.5));
}
.ctx-title .ctx-title-type .ctx-type-sep { opacity: 0.5; }
/* Cost rendered as a green pill, matching the rules-text cost-box. */
.ctx-title .ctx-title-type .rules-text-icon {
    display: inline-block;
    border-radius: 9px;
    font-size: 0.9em;
    padding: 0 6px;
    color: #fff;
    font-weight: bold;
    min-width: 10px;
    text-align: center;
    line-height: 1.4;
    vertical-align: middle;
}
.ctx-title .ctx-title-type .cost-box {
    background: #22a12a;
    box-shadow: 0 0 0 1.5px #5a5a5a, 0 1px 0 rgba(0,0,0,0.3);
}
.ctx-title .ctx-title-type .ctx-type-color[data-color="fire"]  { color: #ff9070; }
.ctx-title .ctx-title-type .ctx-type-color[data-color="grass"] { color: #8fe28f; }
.ctx-title .ctx-title-type .ctx-type-color[data-color="ice"]   { color: #8ac5ff; }
.ctx-title .ctx-title-type .ctx-type-color[data-color="stone"] { color: #dcdde0; }  /* Silver */
.ctx-title .ctx-title-type .ctx-type-color[data-color="gold"]  { color: #f0c040; }
/* Per-type tint so the pill reads at a glance. */
.ctx-title .ctx-title-type[data-card-type="habitual"]   { background: rgba(175,136,79,0.25);  border-color: rgba(175,136,79,0.55);  color: #e8c894; }
.ctx-title .ctx-title-type[data-card-type="unction"]    { background: rgba(80,40,140,0.35);   border-color: rgba(160,110,230,0.55); color: #d9c4ff; }
.ctx-title .ctx-title-type[data-card-type="maturity"]   { background: rgba(30,100,40,0.35);   border-color: rgba(120,220,120,0.55); color: #bfeac0; }
.ctx-title .ctx-title-type[data-card-type="resistance"] { background: rgba(30,60,120,0.35);   border-color: rgba(100,160,255,0.55); color: #b8d4ff; }
.ctx-title .ctx-title-type[data-card-type="token"]      { background: rgba(180,140,40,0.25);  border-color: rgba(240,200,80,0.55);  color: #f5d77a; }
.ctx-title .ctx-title-type[data-card-type="temptation"] { background: rgba(180,30,30,0.35);   border-color: rgba(255,100,100,0.55); color: #f7b0b0; }
/* Body-copy rules text under the card name — styled to mirror the pinned
 * card panel (.pcc-rules) so icon boxes and humility triangles render at
 * readable inline sizes even on mobile. */
.ctx-title .ctx-title-rules {
    font-family: 'Nunito Sans', system-ui, sans-serif;
    font-size: 12px;
    font-weight: 500;
    line-height: 1.5;
    color: #f0e8d8;
    text-shadow: 0 1px 3px rgba(0,0,0,0.9);
    text-transform: none;
    letter-spacing: normal;
    max-height: 180px;
    overflow-y: auto;
    white-space: normal;
}
.ctx-title .ctx-title-rules .rules-text-icon {
    display: inline-block;
    border-radius: 9px;
    font-size: 0.9em;
    padding: 1px 6px;
    color: #fff;
    box-shadow: 0 0 0 1.5px #fff, 0 1px 0 rgba(0,0,0,0.3);
    font-weight: bold;
    min-width: 10px;
    text-align: center;
    line-height: 1.3;
    vertical-align: middle;
}
.ctx-title .ctx-title-rules .cost-box            { background: #22a12a; box-shadow: 0 0 0 1.5px #5a5a5a, 0 1px 0 rgba(0,0,0,0.3); }
.ctx-title .ctx-title-rules .draw-to-hand-box    { background: #2892ff; }
.ctx-title .ctx-title-rules .negative-box        { background: #a12222; border-radius: 4px; }
.ctx-title .ctx-title-rules .discard-from-cost-zone-box { background: #958f8f; }
.ctx-title .ctx-title-rules .card-graphics-img { height: 1.1em; width: auto; vertical-align: middle; }
.ctx-title .ctx-title-rules .card-graphics-img.rotate,
.ctx-title .ctx-title-rules .card-graphics-img.refresh { filter: invert(1); }
/* Humility triangle scaled down like in the penalty dialog. `all: unset`
 * strips the .rules-text-icon pill styles (border-radius, padding, box-
 * shadow) that otherwise turn the triangle into a green oval. */
.ctx-title .ctx-title-rules .humility-box {
    all: unset;
    position: relative;
    display: inline-block;
    width: 0; height: 0;
    border-left:  8px solid transparent;
    border-right: 8px solid transparent;
    border-bottom: 12px solid #05d587;
    margin: 0 14px 0 6px;
    vertical-align: -2px;
}
.ctx-title .ctx-title-rules .humility-box::before,
.ctx-title .ctx-title-rules .humility-box::after {
    content: "";
    position: absolute;
    width: 0; height: 0;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-bottom: 14px solid #004c2b;
    z-index: -1;
}
.ctx-title .ctx-title-rules .humility-box::before { top: -1px; left: -10px; }
.ctx-title .ctx-title-rules .humility-box::after  { top: -2px; left: -10px; }
/* Centre the +N / -N digit inside the triangle: left 50% + translate X
 * handles horizontal centering regardless of width; `top: 8px` places it
 * at the visual centroid of a 12px-tall triangle (2/3 of the way down). */
.ctx-title .ctx-title-rules .humility-box .humility-text {
    all: unset;
    position: absolute;
    left: 50%;
    top: 8px;
    transform: translate(-50%, -50%);
    font-size: 7px;
    font-weight: 700;
    color: #fff;
    line-height: 1;
    -webkit-text-stroke: 0.6px #00170c;
    text-shadow: 0 0 2px rgba(0,0,0,0.8);
    white-space: nowrap;
    pointer-events: none;
}
.ctx-card-thumb {
    flex-shrink: 0;
    position: relative;
    width: 44px;
    height: 64px;
    border-radius: 4px;
    overflow: hidden;
    border: 1px solid rgba(201,168,76,0.4);
    box-shadow: 0 2px 6px rgba(0,0,0,0.5);
    background-color: #000;
    background-size: cover;
    background-position: center;
}
.ctx-card-thumb .ctx-card-thumb-tile {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    cursor: default;
}
.ctx-card-thumb .ch-card-scaler { pointer-events: none; }
/* Face-down thumb is just the background-image-painted card back — no inner
 * tile required. The class is applied when GameUI detects cost-zone or
 * hidden-hand context. */
.ctx-card-thumb.ctx-card-thumb-back { /* styling handled by shared rules + inline bg */ }

/* Mobile: bigger thumb so the card face is actually readable at a glance,
 * and the rules text gets the full row width underneath for easy reading. */
@media (max-width: 820px) {
    .ctx-card-thumb { width: 80px; height: 116px; }
    .ctx-title.ctx-title-with-thumb { padding: 10px 14px; gap: 10px; }
    .ctx-title .ctx-title-name { font-size: 13px; letter-spacing: 0.04em; white-space: normal; }
    .ctx-title .ctx-title-rules { font-size: 13px; max-height: 220px; }
}

.ctx-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px;
    font-size: 12px;
    color: var(--col-text);
    cursor: pointer;
    transition: background 0.1s;
    user-select: none;
}

.ctx-item:hover {
    background: rgba(201,168,76,0.12);
    color: var(--col-divine);
}

.ctx-item.danger { color: var(--col-failed); }
.ctx-item.danger:hover { background: rgba(192,57,43,0.15); }

.ctx-divider {
    height: 1px;
    background: rgba(255,255,255,0.08);
    margin: 3px 0;
}

.ctx-item .ctx-icon { font-size: 14px; flex-shrink: 0; }
.ctx-item.disabled { opacity: 0.45; cursor: default; pointer-events: none; }
.ctx-dbl-hint { font-size: 9px; opacity: 0.55; margin-left: 5px; font-style: italic; vertical-align: middle; }
.ctx-menu.hidden { display: none; }

.ctx-item.ctx-collapsible {
    color: rgba(201,168,76,0.8);
    font-weight: 600;
    cursor: pointer;
}
.ctx-item.ctx-collapsible .ctx-group-label { flex: 1 1 auto; }
.ctx-item.ctx-collapsible .ctx-group-count {
    font-size: 10px;
    opacity: 0.55;
    margin-left: 4px;
    font-weight: 500;
}
.ctx-item.ctx-collapsible .ctx-chevron {
    margin-left: auto;
    transition: transform 0.15s ease;
    font-size: 11px;
    opacity: 0.55;
    display: inline-block;
}
.ctx-item.ctx-collapsible.open .ctx-chevron { transform: rotate(90deg); }
.ctx-group {
    display: none;
    background: rgba(0,0,0,0.18);
    margin-left: 12px;
    border-left: 2px solid rgba(201,168,76,0.2);
}
.ctx-group.open { display: block; }

/* Transient preview for cards about to be bulk-yielded to the Cost Zone. */
.card-tile.yield-preview {
    outline: 3px solid #22a12a;
    outline-offset: 2px;
    box-shadow: 0 0 14px rgba(34,161,42,0.7);
    transition: box-shadow 0.1s ease;
    z-index: 20;
}

/* Themed confirm dialog — reuses .token-creator-panel chrome. */
#confirm-overlay { z-index: 12200; } /* above the ctx-menu (12100) */
.confirm-panel .confirm-body { font-size: 13px; color: #e8e8e8; }
.confirm-panel .confirm-message { margin: 0; line-height: 1.45; }
.confirm-panel .confirm-list {
    margin: 4px 0 0;
    padding-left: 18px;
    max-height: 240px;
    overflow-y: auto;
    color: #f0e8d8;
}
.confirm-panel .confirm-list li {
    padding: 2px 0;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.03em;
    font-size: 12px;
    color: rgba(230,200,140,0.95);
}
.confirm-panel .btn-primary.btn-danger {
    background: #a12222;
    box-shadow: 0 1px 0 rgba(255,255,255,0.1), 0 0 0 1px rgba(0,0,0,0.3);
}

/* Themed number prompt — step buttons + slider + numeric input. */
.num-prompt-panel .num-prompt-row {
    display: flex;
    align-items: stretch;
    gap: 8px;
    margin: 12px 0 8px;
}
.num-prompt-panel .num-prompt-input {
    flex: 1 1 auto;
    min-width: 0;
    text-align: center;
    font-family: 'Cinzel', serif;
    font-size: 22px;
    font-weight: 700;
    color: #f0d07a;
    background: rgba(10,6,0,0.7);
    border: 1px solid rgba(201,168,76,0.45);
    border-radius: 6px;
    padding: 6px 8px;
    -moz-appearance: textfield;
}
.num-prompt-panel .num-prompt-input::-webkit-outer-spin-button,
.num-prompt-panel .num-prompt-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.num-prompt-panel .btn-step {
    min-width: 48px;
    min-height: 48px;
    padding: 0 14px;
    font-family: 'Cinzel', serif;
    font-size: 20px;
    font-weight: 700;
    color: #f0d07a;
    background: linear-gradient(180deg, rgba(80,55,15,0.9), rgba(45,28,0,0.95));
    border: 1px solid rgba(201,168,76,0.55);
    border-radius: 6px;
    cursor: pointer;
    touch-action: manipulation;
}
.num-prompt-panel .btn-step:hover,
.num-prompt-panel .btn-step:focus {
    background: linear-gradient(180deg, rgba(110,75,20,1), rgba(70,40,0,1));
    outline: none;
}
.num-prompt-panel .btn-step:active { transform: scale(0.96); }
.num-prompt-panel .btn-step.btn-max { font-size: 13px; letter-spacing: 0.1em; }
.num-prompt-panel .num-prompt-slider {
    width: 100%;
    margin: 4px 0 8px;
    accent-color: #f0d07a;
}

/* ─── Visual Pile Stats ─────────────────────────────────────────────────────── */

.pile-stat {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10px;
    position: relative;
    cursor: pointer;
    transition: background 0.15s;
}
.pile-stat:hover { background: rgba(201,168,76,0.08); border-radius: 4px; }
.pile-stack-mini {
    display: inline-flex;
    position: relative;
    width: 18px;
    height: 22px;
    flex-shrink: 0;
}
.psm-card {
    position: absolute;
    width: 13px;
    height: 18px;
    border-radius: 2px;
    background: linear-gradient(135deg, #1a2a4a, #0d1828);
    border: 1px solid rgba(201,168,76,0.4);
    bottom: 0;
    left: 0;
}
.psm-card.psm2 { left: 2px; bottom: 2px; opacity: 0.7; }
.psm-card.psm3 { left: 4px; bottom: 4px; opacity: 0.4; }
.pile-stat-label {
    font-family: 'Cinzel', serif;
    font-size: 7px;
    letter-spacing: 0.1em;
    opacity: 0.6;
    text-transform: uppercase;
}
.pile-discard-mini {
    font-size: 12px;
    opacity: 0.7;
    flex-shrink: 0;
}
.discard-stat .pile-stat-label { color: var(--col-text-dim); }
/* Card-pile visuals (kcc.piles=cards): a little stack of real card images —
   face-down backs for the deck, the top card face-up for discard/failed/resisted. */
.pile-mini-cards { position: relative; display: inline-block; width: 24px; height: 32px;
    flex-shrink: 0; vertical-align: middle; overflow: visible; }
.pile-mini-cards .pm-card { position: absolute; width: 22px; height: 30px; border-radius: 3px;
    background-size: cover; background-position: center; background-repeat: no-repeat;
    border: 1px solid rgba(201,168,76,0.55); box-shadow: 0 1px 3px rgba(0,0,0,0.55); }
.pile-mini-cards .pm-card.pm-faceup { border-color: rgba(230,195,74,0.8); }
/* No face-down card-BACK (cross) thumbnail in the stat piles — the count number
   is enough, and the generic cardback graphic just adds clutter. Face-up minis
   (discard / failed / resisted, which show the actual card faces) are kept. If a
   whole mini has only face-down cards it collapses to nothing, leaving the count. */
.pile-mini-cards .pm-card:not(.pm-faceup) { display: none !important; }
.pile-mini-cards:not(:has(.pm-faceup)) { width: 0 !important; margin: 0 !important; }
/* These pile-mini cards are only ~22px — hide the fixed-size "X = n" badge, which
   would otherwise cover the whole tiny card face (discard / failed / resisted). */
.pile-mini-cards .xval-badge { display: none !important; }
.pile-mini-cards .pm-empty { display: inline-block; width: 22px; height: 30px;
    border: 1px dashed rgba(201,168,76,0.3); border-radius: 3px; opacity: 0.5; }
/* Hover-zoom the face-up top card so it can be read at a glance. */
.pile-mini-cards:hover .pm-card.pm-faceup { transform: scale(2.6); transform-origin: bottom center;
    z-index: 200; transition: transform .13s ease; box-shadow: 0 8px 22px rgba(0,0,0,.8); }

/* ─── Mobile / Responsive Board ─────────────────────────────────────────────── */

@media (max-width: 640px) {
    :root {
        --card-w:      clamp(50px, 11vw, 80px);
        --card-h:      clamp(70px, 16vw, 112px);
        --card-w-hand: clamp(60px, 17vw, 90px);
        --card-h-hand: clamp(90px, 25vw, 135px);
        --gap:         4px;
    }
    #board { padding-top: 90px; }
    #phase-bar { padding: 3px 8px 3px; gap: 3px; }
    #turn-round-tag { display: none; }
    .phase-step .ps-label { display: none; }
    .phase-step .ps-emoji { font-size: 13px; }
    #action-bar .btn-primary { padding: 5px 10px; font-size: 10px; }
    .player-stats { flex-wrap: wrap; gap: 3px; }
    .stat-badge { font-size: 8px; padding: 2px 5px; }
    .player-name { font-size: 11px; }
    .zone-label { font-size: 7px; }
    .player-area { padding: 4px; }
    /* Zones scroll horizontally without overflow */
    .card-zone { overflow-x: auto; overflow-y: visible; }
}

@media (max-width: 480px) {
    :root {
        --card-w:      clamp(44px, 10vw, 60px);
        --card-h:      clamp(62px, 14vw, 84px);
        --card-w-hand: clamp(54px, 15vw, 72px);
        --card-h-hand: clamp(80px, 22vw, 108px);
    }
    #board { padding-top: 85px; }
    .phase-instructions { font-size: 9px; }
    #turn-player-name { font-size: 11px; }
    #turn-phase-label { font-size: 9px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   SACRED BATTLEFIELD — Visual Overhaul
   Illuminated manuscript meets spiritual warfare RPG.
   These rules layer on top of existing styles.
═══════════════════════════════════════════════════════════════════════════ */

/* ── Evil zone: corruption atmosphere ───────────────────────────────────── */

.player-area.evil {
    background:
        radial-gradient(ellipse 120% 60% at 50% 0%, rgba(100,0,0,0.4) 0%, transparent 60%),
        linear-gradient(180deg, rgba(60,0,0,0.8) 0%, rgba(10,4,4,0.98) 100%);
    border-color: rgba(160,30,30,0.7);
    box-shadow:
        inset 0 1px 0 rgba(255,60,60,0.15),
        inset 0 -1px 0 rgba(80,0,0,0.4),
        0 4px 32px rgba(0,0,0,0.7),
        0 0 60px rgba(80,0,0,0.15);
    position: relative;
    overflow: visible; /* keep stats visible; ::after glow is cosmetic */
}

/* Dripping corruption glow from top */
.player-area.evil::after {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    pointer-events: none;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(180,0,0,0.8) 20%,
        rgba(255,40,40,1) 50%,
        rgba(180,0,0,0.8) 80%,
        transparent 100%);
    border-radius: var(--radius) var(--radius) 0 0;
    animation: evilGlow 3s ease-in-out infinite alternate;
}
@keyframes evilGlow {
    from { opacity: 0.6; }
    to   { opacity: 1.0; box-shadow: 0 0 20px rgba(255,0,0,0.5); }
}

/* ── Righteous zone: divine light rising from below ─────────────────────── */

.player-area.righteous {
    background:
        radial-gradient(ellipse 100% 50% at 50% 100%, rgba(20,50,120,0.5) 0%, transparent 60%),
        linear-gradient(180deg, rgba(2,8,18,0.98) 0%, rgba(8,20,50,0.9) 100%);
    border-color: rgba(40,80,160,0.6);
    position: relative;
}

/* Sacred light from below */
.player-area.righteous::after {
    content: '';
    position: absolute;
    bottom: 0; left: 0; right: 0;
    height: 2px;
    pointer-events: none;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(60,120,255,0.6) 20%,
        rgba(160,200,255,0.9) 50%,
        rgba(60,120,255,0.6) 80%,
        transparent 100%);
    border-radius: 0 0 var(--radius) var(--radius);
    animation: divineGlow 4s ease-in-out infinite alternate;
}
@keyframes divineGlow {
    from { opacity: 0.5; }
    to   { opacity: 1.0; }
}

/* ── Active player: golden blaze ─────────────────────────────────────────── */

.player-area.righteous.active-player {
    border-color: var(--col-divine) !important;
    background:
        radial-gradient(ellipse 100% 40% at 50% 100%, rgba(201,168,76,0.12) 0%, transparent 70%),
        radial-gradient(ellipse 100% 50% at 50% 100%, rgba(20,50,120,0.5) 0%, transparent 60%),
        linear-gradient(180deg, rgba(2,8,18,0.98) 0%, rgba(8,20,50,0.9) 100%);
}

/* ── Shared/battlefield zone ─────────────────────────────────────────────── */

#shared-zones {
    background:
        radial-gradient(ellipse 60% 80% at 50% 50%, rgba(30,20,0,0.6) 0%, transparent 100%),
        linear-gradient(180deg, rgba(5,3,0,0.95) 0%, rgba(3,5,10,0.95) 100%);
    border: 1px solid rgba(201,168,76,0.1);
    box-shadow:
        inset 0 0 80px rgba(0,0,0,0.6),
        0 0 0 1px rgba(0,0,0,0.8);
}

/* Active temptation field — burning ground */
#zone-evil-field {
    background:
        radial-gradient(ellipse 80% 100% at 50% 50%, rgba(60,0,0,0.35) 0%, transparent 100%);
    border: 1px solid rgba(139,26,26,0.3);
    border-radius: 10px;
    min-height: 24px;
    padding: 6px 14px;
    position: relative;
}
#zone-evil-field:not(:empty) {
    min-height: 220px;
    padding: 10px 14px;
}
#zone-evil-field:not(:empty) {
    border-color: rgba(200,40,40,0.4);
    box-shadow: 0 0 30px rgba(140,0,0,0.25), inset 0 0 20px rgba(80,0,0,0.2);
    animation: fieldBurning 4s ease-in-out infinite alternate;
}
@keyframes fieldBurning {
    from { box-shadow: 0 0 20px rgba(140,0,0,0.2), inset 0 0 15px rgba(60,0,0,0.15); }
    to   { box-shadow: 0 0 40px rgba(200,0,0,0.35), inset 0 0 25px rgba(100,0,0,0.25); }
}

/* Temptation cards — tall-mode so all card text is readable */
#zone-evil-field .card-tile {
    width: 205px;
    height: 300px;
}
/* Evil temptations get the ominous red frame + pulse; righteous plays don't. */
#zone-evil-field .card-tile[data-card-type="Temptation"] {
    border-color: rgba(200,40,40,0.5);
    box-shadow:
        0 0 12px rgba(160,0,0,0.5),
        0 0 0 1px rgba(200,40,40,0.3),
        0 4px 16px rgba(0,0,0,0.8);
    animation: temptPulse 2.5s ease-in-out infinite alternate;
}
/* Righteous card being played: calm gold frame (no red, no pulse). */
#zone-evil-field .card-tile:not([data-card-type="Temptation"]) {
    border-color: rgba(230,195,74,0.55);
    box-shadow:
        0 0 12px rgba(230,195,74,0.35),
        0 0 0 1px rgba(230,195,74,0.3),
        0 4px 16px rgba(0,0,0,0.8);
}
#zone-evil-field .ch-card-root { --ch-scale: 0.273; }
@media (min-width: 768px) {
    #zone-evil-field .card-tile { width: 270px; height: 396px; }
    #zone-evil-field .ch-card-root { --ch-scale: 0.36; }
}
/* COMPACT shared Active zone: small tiles + a short band, so a played card /
   threat is visible WITHOUT the zone pushing the player areas down. Hover a
   card to enlarge it for a closer look. */
.zone-active-shared #zone-evil-field:not(:empty) {
    min-height: 0 !important; padding: 6px 10px !important;
}
.zone-active-shared #zone-evil-field .card-tile { width: 140px !important; height: 206px !important; }
.zone-active-shared #zone-evil-field .ch-card-root { --ch-scale: 0.187 !important; }
@media (min-width: 768px) {
    .zone-active-shared #zone-evil-field .card-tile { width: 172px !important; height: 253px !important; }
    .zone-active-shared #zone-evil-field .ch-card-root { --ch-scale: 0.229 !important; }
}
.zone-active-shared #zone-evil-field .card-tile:hover {
    transform: scale(1.75); z-index: 55; transition: transform .14s ease;
}
@keyframes temptPulse {
    from { box-shadow: 0 0 10px rgba(140,0,0,0.4), 0 0 0 1px rgba(180,30,30,0.25), 0 4px 16px rgba(0,0,0,0.7); }
    to   { box-shadow: 0 0 22px rgba(220,0,0,0.65), 0 0 0 2px rgba(255,40,40,0.4), 0 8px 24px rgba(0,0,0,0.8); }
}
/* Shared ACTIVE zone (one per game): played cards resolve here — GOLD accent so
   it reads as the neutral "in play / resolving" area, not just evil threats.
   FLOATS over a neutral middle spot (position:fixed) and only appears while a
   card is in play, so it NEVER pushes the player areas down. Position + size are
   CSS variables so they're easy to retune. */
:root {
    --active-zone-top: 50%;   /* vertical anchor (viewport middle — the neutral seam) */
    --active-zone-left: 50%;  /* horizontal anchor (centered) */
    --active-zone-shift: 0px; /* extra left shift to re-center over the board when docked L/R */
}
#zone-evil-field-wrap.zone-active-shared {
    position: fixed !important;
    top: var(--active-zone-top); left: calc(var(--active-zone-left) + var(--active-zone-shift));
    transform: translate(-50%, -50%);
    z-index: 9000; max-width: 92vw;   /* above the player areas; below modals */
    display: none !important;       /* shown only when a card is in play (beats the old #shared-zones collapse rules) */
    pointer-events: none;
    /* Prominent so a played card is unmistakable when it lands here. */
    background: rgba(12,9,3,0.9); backdrop-filter: blur(3px);
    border: 2px solid rgba(240,205,90,0.85); border-radius: 16px;
    padding: 8px 16px !important;
    box-shadow: 0 0 34px rgba(240,205,90,0.35), 0 14px 40px rgba(0,0,0,.7);
    animation: activeZonePop .28s ease-out both;
}
@keyframes activeZonePop { from { opacity:0; transform: translate(-50%,-50%) scale(.9); } to { opacity:1; transform: translate(-50%,-50%) scale(1); } }
/* Re-center over the board (not the viewport) when the bar is docked to a side. */
body.replay-dock-right #zone-evil-field-wrap.zone-active-shared { --active-zone-shift: -116px; }
body.replay-dock-left  #zone-evil-field-wrap.zone-active-shared { --active-zone-shift:  116px; }
#zone-evil-field-wrap.zone-active-shared.has-active-cards { display: block !important; }
/* Draggable / resizable Active zone. Wrap is pointer-events:none, so the
   handles carry their own. az-movable hides the ::before label (the bar shows it). */
#zone-evil-field-wrap.az-movable::before { display: none; }
#zone-evil-field-wrap.zone-active-shared .active-zone-drag {
    pointer-events: auto; cursor: grab; user-select: none; touch-action: none;
    display: flex; align-items: center; justify-content: center; gap: 6px;
    font-family: 'Cinzel', serif; font-size: 10px; letter-spacing: 0.14em;
    text-transform: uppercase; color: rgba(240,205,90,0.85);
    padding: 3px 8px; margin: -4px -12px 4px; border-radius: 12px 12px 0 0;
}
#zone-evil-field-wrap.zone-active-shared .active-zone-drag:active { cursor: grabbing; }
.active-zone-drag .azd-grip { opacity: 0.65; letter-spacing: -2px; font-size: 12px; }
.active-zone-drag .azd-reset { cursor: pointer; margin-left: 6px; opacity: 0.55; font-size: 12px; }
.active-zone-drag .azd-reset:hover { opacity: 1; }
#zone-evil-field-wrap.zone-active-shared .active-zone-resize {
    pointer-events: auto; position: absolute; right: 3px; bottom: 3px;
    width: 16px; height: 16px; cursor: nwse-resize; opacity: 0.5;
    background: linear-gradient(135deg, transparent 45%, rgba(240,205,90,0.75) 45%, rgba(240,205,90,0.75) 55%, transparent 55%, transparent 70%, rgba(240,205,90,0.75) 70%, rgba(240,205,90,0.75) 80%, transparent 80%);
}
#zone-evil-field-wrap.zone-active-shared .active-zone-resize:hover { opacity: 0.9; }
#zone-evil-field-wrap.zone-active-shared #zone-evil-field { pointer-events: auto; }
#zone-evil-field-wrap.zone-active-shared .zone-label { color: #e6c34a; }
#zone-evil-field-wrap.zone-active-shared .zone-sub { color: #a99e88; font-weight: 400; font-size: .82em; letter-spacing: 0; }
.zone-active-shared #zone-evil-field:not(:empty) {
    border-color: rgba(230,195,74,0.5) !important;
    box-shadow: 0 0 24px rgba(230,195,74,0.22),
                0 0 0 1px rgba(230,195,74,0.35),
                0 4px 16px rgba(0,0,0,0.75) !important;
    animation: activePulse 2.6s ease-in-out infinite alternate !important;
}
@keyframes activePulse {
    from { box-shadow: 0 0 12px rgba(230,195,74,0.28), 0 0 0 1px rgba(230,195,74,0.30), 0 4px 16px rgba(0,0,0,0.7); }
    to   { box-shadow: 0 0 26px rgba(240,205,90,0.5),  0 0 0 2px rgba(240,205,90,0.5),  0 8px 24px rgba(0,0,0,0.8); }
}

/* ── Phase bar: illuminated codex ────────────────────────────────────────── */

#phase-bar {
    background:
        linear-gradient(180deg,
            rgba(14,10,4,0.97) 0%,
            rgba(8,6,3,0.99)   100%);
    border: 1px solid rgba(201,168,76,0.25);
    border-top: 1px solid rgba(201,168,76,0.4);
    box-shadow:
        0 0 0 1px rgba(0,0,0,0.8),
        0 2px 20px rgba(0,0,0,0.7),
        inset 0 1px 0 rgba(201,168,76,0.12),
        inset 0 0 40px rgba(201,168,76,0.03);
}

/* Phase track: ornamental dividers between steps */
#phase-track {
    position: relative;
    padding: 2px 0;
}
#phase-track::before {
    content: '';
    position: absolute;
    top: 50%; left: 0; right: 0;
    height: 1px;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(201,168,76,0.15) 15%,
        rgba(201,168,76,0.3) 50%,
        rgba(201,168,76,0.15) 85%,
        transparent 100%);
    pointer-events: none;
    transform: translateY(-50%);
    z-index: 0;
}
.phase-step { position: relative; z-index: 1; }

/* Turn player name — larger, more imposing */
#turn-player-name {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-shadow:
        0 0 16px rgba(240,192,64,0.6),
        0 0 32px rgba(240,192,64,0.2);
}

/* Phase label — colored glow per phase */
#turn-phase-label {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-shadow: 0 0 14px currentColor;
}

/* Advance phase button — gold sacred seal */
#action-bar .btn-primary {
    background: linear-gradient(135deg,
        rgba(120,88,20,0.9) 0%,
        rgba(180,140,40,0.95) 40%,
        rgba(201,168,76,0.9) 60%,
        rgba(140,100,20,0.9) 100%);
    color: #0a0600;
    border: 1px solid rgba(255,215,0,0.5);
    font-weight: 700;
    letter-spacing: 0.1em;
    text-shadow: 0 1px 0 rgba(255,240,180,0.4);
    box-shadow:
        0 2px 12px rgba(201,168,76,0.4),
        inset 0 1px 0 rgba(255,240,180,0.3);
    transition: all 0.2s ease;
}
#action-bar .btn-primary:hover {
    background: linear-gradient(135deg,
        rgba(160,120,30,0.95) 0%,
        rgba(220,180,60,1.0)  40%,
        rgba(240,200,80,1.0)  60%,
        rgba(180,130,30,0.95) 100%);
    box-shadow:
        0 4px 20px rgba(201,168,76,0.6),
        inset 0 1px 0 rgba(255,240,180,0.5);
    transform: translateY(-1px);
}
#action-bar .btn-primary:active { transform: translateY(0); }
#action-bar .btn-primary:disabled {
    background: rgba(60,50,30,0.6);
    color: rgba(180,150,80,0.5);
    border-color: rgba(120,90,30,0.3);
    box-shadow: none;
    transform: none;
}

/* Phase-advance blocked by a pending mandatory temptation. Reads as
   disabled (no gold gradient) but stays clickable so the tap redirects
   focus to the temptation window instead of silently no-oping. */
#action-bar .btn-primary.btn-blocked {
    background: rgba(70,40,25,0.7);
    color: #ffb488;
    border: 1px solid rgba(255,120,60,0.55);
    box-shadow: none;
    cursor: help;
    transform: none;
    text-shadow: none;
}
#action-bar .btn-primary.btn-blocked:hover {
    background: rgba(90,50,30,0.85);
    box-shadow: 0 2px 12px rgba(255,120,60,0.35);
    transform: none;
}

/* Focus-redirect pulse on the evil/temptation field. */
.nudge-pulse {
    animation: nudge-pulse 0.7s ease-in-out 2;
    border-radius: 8px;
}
@keyframes nudge-pulse {
    0%,100% { box-shadow: 0 0 0 0 rgba(255,120,60,0.0); }
    50%     { box-shadow: 0 0 0 4px rgba(255,120,60,0.75), 0 0 22px 6px rgba(255,90,40,0.45); }
}
@media (prefers-reduced-motion: reduce) {
    .nudge-pulse { animation: none; }
}

/* Phase instructions — parchment text */
.phase-instructions {
    font-family: 'Nunito Sans', sans-serif;
    font-size: 10px;
    color: rgba(230,210,160,0.9);
    line-height: 1.3;
    border-left: 2px solid rgba(201,168,76,0.35);
    padding-left: 6px;
    font-style: italic;
}
.phase-hint {
    font-size: 9px;
    color: rgba(180,160,110,0.75);
    font-style: normal;
}

/* ── Pile displays ────────────────────────────────────────────────────────── */

.pile-display {
    min-width: 60px;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    transition: opacity 0.15s;
}
.pile-display:hover { opacity: 0.8; }

/* ── Pile Modal — review failed / resisted cards ──────────────────────────
 * Non-modal floating dialog (no backdrop) — drag by the header, resize by
 * the bottom-right corner. The board stays interactive behind it. */
.pile-modal-floating {
    background: #0d0b08;
    border: 1px solid rgba(201,168,76,0.35);
    border-radius: 8px;
    box-shadow: 0 10px 40px rgba(0,0,0,0.7);
}
/* Legacy .pile-modal-overlay / .pile-modal-box classes kept as an alias
 * in case some older code path still uses them. */
.pile-modal-overlay {
    position: fixed; inset: 0; z-index: 2200;
    background: rgba(0,0,0,0.75);
    display: flex; align-items: center; justify-content: center;
}
.pile-modal-box {
    background: #0d0b08;
    border: 1px solid rgba(201,168,76,0.25);
    border-radius: 8px;
    width: min(520px, 94vw);
    max-height: 80vh;
    display: flex; flex-direction: column;
    box-shadow: 0 8px 40px rgba(0,0,0,0.7);
    overflow: hidden;
}
.pile-modal-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 14px;
    background: rgba(201,168,76,0.08);
    border-bottom: 1px solid rgba(201,168,76,0.15);
    font-family: 'Cinzel', serif;
    font-size: 13px;
    color: var(--col-divine);
    flex-shrink: 0;
    cursor: move;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
}
.pile-modal-floating .pile-modal-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pile-modal-close { /* legacy; dlg-btn rules now cover the floating variant */
    background: none; border: none; color: rgba(201,168,76,0.6);
    font-size: 14px; cursor: pointer; padding: 2px 6px; border-radius: 4px;
}
.pile-modal-close:hover { background: rgba(201,168,76,0.12); color: var(--col-divine); }
.pile-modal-body {
    overflow-y: auto;
    overflow-x: hidden;
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1 1 auto;
    min-height: 0;              /* let the flex child shrink so overflow-y actually scrolls */
}
.pile-modal-floating::after {
    content: '';
    position: absolute;
    right: 2px; bottom: 2px;
    width: 14px; height: 14px;
    pointer-events: none;
    background: linear-gradient(135deg, transparent 50%, rgba(201,168,76,0.5) 50%, rgba(201,168,76,0.5) 60%, transparent 60%, transparent 70%, rgba(201,168,76,0.5) 70%, rgba(201,168,76,0.5) 80%, transparent 80%);
}
.pile-modal-empty {
    color: rgba(201,168,76,0.4); font-style: italic; text-align: center; padding: 20px;
    font-family: 'Cinzel', serif; font-size: 12px;
}

/* Mini-card grid view — renders each pile card as a real card face so the
 * player can see art + layout at a glance. Toggled from text view via the
 * 🃏 button in the dialog header. */
.pile-modal-body.pile-modal-body-mini { padding: 10px; }
.pile-modal-mini-grid {
    display: grid;
    /* Fixed 160px cells so the ch-scale below lines up with tile size —
     * grid still wraps to fit the modal width; wider modals just leave
     * more gap between tiles instead of stretching cards out of scale. */
    grid-template-columns: repeat(auto-fill, 160px);
    gap: 10px;
    justify-content: start;
}
.pile-modal-mini-grid .pile-mini-tile {
    position: relative;
    width: 160px;
    height: calc(160px * 1100 / 750);
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid rgba(201,168,76,0.3);
    background: #000;
    cursor: zoom-in;
    transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.pile-modal-mini-grid .pile-mini-tile .ch-card-root { --ch-scale: 0.213; }
.pile-modal-mini-grid .pile-mini-tile:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0,0,0,0.6), 0 0 0 2px rgba(201,168,76,0.45);
    z-index: 1;
}
.pile-modal-mini-grid .pile-mini-tile .ch-card-scaler { pointer-events: none; }

/* Tapped indicator in the pile modal — mini grid gets a small red
   "TAPPED" badge overlay; the tile itself also carries the .rotated class
   which the existing base rule rotates 90deg. Text rows get a "↻ TAPPED"
   chip next to the name. Both make it obvious which of two identical
   Habituals has already been spent this phase. */
.pile-modal-mini-grid .pile-mini-tile.rotated {
    /* mini tiles use scale; the .rotated base rule rotates 90deg, so add a
       subtle red outline so the tap state reads even when the card is
       small enough that orientation alone isn't glance-readable. */
    outline: 2px solid rgba(220,80,80,0.7);
    outline-offset: -2px;
}
.pile-mini-tapped {
    position: absolute;
    bottom: 4px;
    left: 4px;
    font-family: 'Cinzel', serif;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.12em;
    color: #fff;
    background: rgba(220,80,80,0.92);
    border: 1px solid rgba(255,150,150,0.8);
    border-radius: 3px;
    padding: 1px 4px;
    pointer-events: none;
    z-index: 3;
}
.pmr-tapped {
    display: inline-block;
    font-family: 'Cinzel', serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: #fff;
    background: rgba(220,80,80,0.9);
    border: 1px solid rgba(255,150,150,0.8);
    border-radius: 3px;
    padding: 1px 5px;
    margin-left: 6px;
}

/* Face-down mini tiles in a peek-protected pile modal (Cost Zone ⊞ view).
   No pointer / hover — the user explicitly clicks the Peek button in the
   header to flip everything face-up (which fires the logged peek callback). */
.pile-modal-mini-grid .pile-mini-tile.pile-mini-back {
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    cursor: default;
    outline: none;
}
.pile-modal-row.pile-modal-row-hidden {
    background-image: linear-gradient(90deg, rgba(40,40,40,0.4), rgba(30,30,30,0.2));
    border-color: rgba(255,255,255,0.1);
    color: rgba(255,255,255,0.5);
}
.pile-peek-btn { font-size: 14px; }

/* Caution variant — used for peek-at-deck and other integrity-breaking views. */
.pile-modal-overlay.caution .pile-modal-box {
    border: 2px solid #ffb84d;
    box-shadow: 0 0 40px rgba(255,184,77,0.35), 0 8px 40px rgba(0,0,0,0.7);
}
.pile-modal-overlay.caution .pile-modal-header {
    background: linear-gradient(90deg, rgba(255,184,77,0.18), rgba(220,120,40,0.12));
    border-bottom-color: rgba(255,184,77,0.45);
    color: #ffb84d;
    text-shadow: 0 0 8px rgba(255,120,40,0.5);
}
.pile-modal-hint {
    padding: 6px 14px;
    background: rgba(255,184,77,0.08);
    border-bottom: 1px solid rgba(255,184,77,0.2);
    color: rgba(255,220,160,0.85);
    font-size: 11px;
    font-style: italic;
    font-family: 'Nunito Sans', sans-serif;
    text-align: center;
}
.pile-modal-row {
    border-radius: 6px; padding: 8px 10px; cursor: pointer;
    display: flex; flex-direction: column; gap: 4px;
    transition: filter 0.15s;
    background-size: cover; background-position: center;
    position: relative; overflow: hidden;
}
/* Dark overlay for readability */
.pile-modal-row::before {
    content: ''; position: absolute; inset: 0; border-radius: 6px;
    background: linear-gradient(180deg, rgba(0,0,0,0.72) 0%, rgba(0,0,0,0.60) 100%);
    pointer-events: none; z-index: 0;
}
.pile-modal-row > * { position: relative; z-index: 1; }
.pile-modal-row:hover { filter: brightness(1.18); }
.pmr-top {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.pmr-type-icon {
    width: 22px; height: 22px; object-fit: contain;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.8)); flex-shrink: 0;
}
.pmr-type {
    font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; opacity: 0.9;
}
.pmr-name {
    font-size: 12px; font-weight: 700; font-family: 'Cinzel', serif; flex: 1; color: #fff;
    text-shadow: 0 1px 3px rgba(0,0,0,0.9);
}
.pmr-cost {
    font-size: 12px; font-weight: 900; border: 2px solid; border-radius: 4px;
    padding: 1px 5px; flex-shrink: 0; background: rgba(0,0,0,0.4);
    text-shadow: 0 1px 2px rgba(0,0,0,0.8);
}
.pmr-rules {
    font-size: 12px; color: #f0e8d8; line-height: 1.5;
    text-shadow: 0 1px 2px rgba(0,0,0,0.8);
}

/* ── Player stats bar ────────────────────────────────────────────────────── */

.player-name {
    font-family: 'Cinzel', serif;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 2px 8px;
    border-radius: 4px;
    background: rgba(0,0,0,0.35);
}

.player-area.evil .player-name { color: #e06060; text-shadow: 0 0 12px rgba(200,60,60,0.5); }
.player-area.righteous .player-name { color: var(--col-divine); text-shadow: 0 0 10px rgba(201,168,76,0.4); }
/* Active player's name gets a golden halo so it's readable at a glance
   whether you look at the player area, the tab bar, or the phase-bar. */
.player-area.active-player .player-name {
    box-shadow: 0 0 0 1px rgba(240,192,64,0.7), 0 0 10px rgba(240,192,64,0.35);
    background: rgba(240,192,64,0.16);
}



/* ── Board zone labels — etched look ─────────────────────────────────────── */

.zone-label {
    font-family: 'Cinzel', serif;
    font-size: 8px;
    letter-spacing: 0.18em;
    color: rgba(201,168,76,0.4);
    text-transform: uppercase;
}

/* ── Log panel — scripture scroll ────────────────────────────────────────── */

#log-panel {
    background:
        linear-gradient(180deg, rgba(8,6,2,0.96) 0%, rgba(4,6,12,0.97) 100%);
    border: 1px solid rgba(201,168,76,0.12);
    font-family: 'Nunito Sans', sans-serif;
}

.log-entry {
    font-family: 'Nunito Sans', sans-serif;
    font-size: 10px;
    line-height: 1.5;
    padding: 4px 0;
    border-bottom: 1px solid rgba(201,168,76,0.06);
    color: rgba(180,160,120,0.7);
}
.log-entry:last-child {
    color: rgba(230,210,160,0.9);
    border-bottom: none;
}

/* ── Hand zone visual divider ─────────────────────────────────────────────── */

.player-area.righteous .zone-row.hand-row {
    border-top: 1px solid rgba(40,80,160,0.25);
    padding-top: 6px;
    margin-top: 2px;
}

/* ── Scroll snapping for hand ─────────────────────────────────────────────── */

[id$="-hand"].hand-fan {
    scroll-snap-type: x mandatory;
    scroll-padding: 8px;
}
[id$="-hand"].hand-fan .card-tile {
    scroll-snap-align: start;
}

/* ── Keyboard shortcut hint ───────────────────────────────────────────────── */

#phase-bar::after {
    content: 'SPACE to advance phase';
    display: block;
    font-family: 'Cinzel', serif;
    font-size: 7px;
    letter-spacing: 0.14em;
    color: rgba(201,168,76,0.2);
    text-align: right;
    padding: 0 2px 2px;
    pointer-events: none;
}

@media (max-width: 768px) {
    #phase-bar::after { display: none; }
}

/* ── Resist/fail action buttons on temptation cards ─────────────────────── */

/* On an active temptation both the RESIST and FAIL buttons must be fully
   readable (incl. the wider "Swat — pay C3" cost-tap label), so stack them
   centered across the card bottom instead of squeezing into corners. */
#zone-evil-field .card-tile .resist-btn,
#zone-evil-field .card-tile .fail-btn {
    opacity: 0.95;  /* always clearly visible on active temptations */
    font-size: 9px;
    padding: 4px 8px;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    max-width: 94%;
    white-space: nowrap;
}
#zone-evil-field .card-tile .resist-btn { bottom: 24px; }
#zone-evil-field .card-tile .fail-btn   { bottom: 4px;  }
#zone-evil-field .card-tile:hover .resist-btn,
#zone-evil-field .card-tile:hover .fail-btn {
    opacity: 1;
}
/* Cost-tap fallback resist ("Swat — pay C3") — distinct deeper green so it
   reads as the alternate path when no Resistance card is available. */
#zone-evil-field .card-tile .resist-cost-btn {
    background: linear-gradient(135deg,#1f8a5b,#155e3f);
    box-shadow: 0 2px 8px rgba(31,138,91,0.55);
}
#zone-evil-field .card-tile .resist-btn[disabled] {
    opacity: 0.45;
    cursor: not-allowed;
    filter: grayscale(0.5);
    box-shadow: none;
}

/* ── Maturity progress subtle glow on level up ─────────────────────────── */

.player-area .stat-badge {
    font-family: 'Cinzel', serif;
    font-size: 9px;
    letter-spacing: 0.06em;
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.07);
    border-radius: 4px;
    padding: 2px 6px;
    color: rgba(210,190,140,0.8);
}

/* ── Evil Deck Reveal Modal ──────────────────────────────────────────────── */

.evil-reveal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.75);
    z-index: 9000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

.evil-reveal-panel {
    background: #1a0808;
    border: 1px solid rgba(180,30,30,0.6);
    border-radius: 10px;
    box-shadow: 0 0 40px rgba(160,0,0,0.5), 0 8px 32px rgba(0,0,0,0.9);
    width: min(720px, 96vw);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.evil-reveal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 18px;
    border-bottom: 1px solid rgba(180,30,30,0.35);
    font-family: 'Cinzel', serif;
    font-size: 15px;
    color: #e87070;
    letter-spacing: 0.08em;
}

.evil-reveal-close {
    background: none;
    border: none;
    color: rgba(220,100,100,0.7);
    font-size: 18px;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 4px;
    transition: color 0.15s, background 0.15s;
}
.evil-reveal-close:hover { color: #fff; background: rgba(200,40,40,0.4); }

.evil-reveal-body {
    overflow-y: auto;
    flex: 1;
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.evil-reveal-row {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 12px;
    background: rgba(255,255,255,0.03);
    border: 1px solid rgba(180,30,30,0.2);
    border-radius: 8px;
}

.evil-reveal-card-wrap {
    flex-shrink: 0;
    /* 750 × 0.173 = 130px, 1100 × 0.173 ≈ 190px */
    width: 130px;
    height: 190px;
    overflow: hidden;
    border-radius: 6px;
    position: relative;
}

.evil-reveal-card-wrap .ch-card-root {
    --ch-scale: 0.173;
}

.evil-reveal-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex: 1;
}

.evil-reveal-btn {
    padding: 10px 18px;
    border: none;
    border-radius: 6px;
    font-family: 'Cinzel', serif;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.05em;
    cursor: pointer;
    transition: filter 0.15s, transform 0.1s;
}
.evil-reveal-btn:hover { filter: brightness(1.15); transform: translateY(-1px); }
.evil-reveal-btn:active { transform: translateY(0); filter: brightness(0.9); }

.evil-reveal-btn.play-btn {
    background: linear-gradient(135deg, #8b0000, #c0392b);
    color: #fff;
    box-shadow: 0 2px 8px rgba(160,0,0,0.5);
}

.evil-reveal-btn.return-btn {
    background: rgba(255,255,255,0.08);
    color: rgba(220,200,180,0.85);
    border: 1px solid rgba(255,255,255,0.12);
}

.evil-reveal-footer {
    padding: 10px 18px;
    border-top: 1px solid rgba(180,30,30,0.25);
    font-size: 11px;
    color: rgba(200,160,160,0.6);
    font-style: italic;
}

.evil-reveal-empty {
    color: rgba(200,160,160,0.6);
    text-align: center;
    padding: 32px;
    font-style: italic;
}

@media (max-width: 600px) {
    .evil-reveal-row { flex-direction: column; align-items: flex-start; }
    .evil-reveal-card-wrap { width: 100px; height: 147px; }
    .evil-reveal-card-wrap .ch-card-root { --ch-scale: 0.133; }
}

/* ── Evil Habituals Zone ─────────────────────────────────────────────────── */

#zone-evil-habituals-wrap {
    width: 100%;
    padding: 10px 16px 6px;
    background: rgba(80,0,0,0.18);
    border-top: 1px solid rgba(180,30,30,0.3);
    border-bottom: 1px solid rgba(180,30,30,0.3);
}

#zone-evil-habituals-wrap .zone-label {
    display: block;
    font-family: 'Cinzel', serif;
    font-size: 10px;
    letter-spacing: 0.1em;
    color: rgba(220,80,80,0.7);
    text-transform: uppercase;
    margin-bottom: 8px;
    text-align: center;
}

#zone-evil-habituals {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    justify-content: center;
    min-height: 60px;
}

/* Same sizing as evil field cards */
#zone-evil-habituals .card-tile {
    width: 205px;
    height: 300px;
    border-color: rgba(180,0,0,0.5);
    box-shadow: 0 0 10px rgba(120,0,0,0.4), 0 0 0 1px rgba(180,0,0,0.25), 0 4px 14px rgba(0,0,0,0.7);
    animation: temptPulse 3.5s ease-in-out infinite alternate;
}
#zone-evil-habituals .ch-card-root { --ch-scale: 0.273; }
@media (min-width: 768px) {
    #zone-evil-habituals .card-tile { width: 270px; height: 396px; }
    #zone-evil-habituals .ch-card-root { --ch-scale: 0.36; }
}

/* ── Playmat Grid Layout ─────────────────────────────────────────────────── */

.playmat-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto;
    gap: 0;
    width: 100%;
    background-image: url('../img/playmat-chr.png');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    border-radius: 10px;
    overflow: hidden;
    border: 2px solid rgba(255,255,255,0.12);
    min-height: 180px;
}

.playmat-quad {
    display: flex;
    flex-direction: column;
    padding: 6px 8px 8px;
    min-height: 90px;
    position: relative;
}

.playmat-quad .quad-label {
    font-family: 'Cinzel', serif;
    font-size: 0.55rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: rgba(255,255,255,0.75);
    text-shadow: 0 1px 3px rgba(0,0,0,0.9);
    margin-bottom: 4px;
    padding-bottom: 3px;
    border-bottom: 1px solid rgba(255,255,255,0.18);
    /* Flex so controls (zoom group + ⊞) sit on the right; the label text
       is wrapped in .quad-label-text (JS) and allowed to shrink so the
       buttons never get pushed off the quad on narrow screens. */
    display: flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
}
.quad-label-text {
    flex: 1 1 auto;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Per-turn Cost-Zone counter ("2/4"): how many hand cards the active
   player has laid into the Cost Zone this turn vs the per-turn cap.
   Sits at the right edge of the Available label / zone-label. */
.cost-turn-badge {
    flex: 0 0 auto;
    margin-left: auto;
    font-family: 'Cinzel', serif;
    font-size: 0.62rem;
    line-height: 1;
    letter-spacing: 0.02em;
    font-weight: 700;
    color: #f0e2b0;
    background: rgba(201,168,76,0.22);
    border: 1px solid rgba(201,168,76,0.55);
    border-radius: 999px;
    padding: 2px 7px;
    text-shadow: 0 1px 2px rgba(0,0,0,0.85);
    white-space: nowrap;
}
.cost-turn-badge.cost-turn-full {
    color: #ffd9c2;
    background: rgba(150,60,40,0.30);
    border-color: rgba(210,110,80,0.7);
}
.cost-subzone > .zone-label .cost-turn-badge {
    font-size: 0.55rem;
    padding: 1px 5px;
}
/* Spent-count badge on the Spent label — how many cost cards are tapped/spent. */
.cost-spent-badge {
    flex: 0 0 auto; margin-left: auto;
    font-family: 'Cinzel', serif; font-size: 0.62rem; line-height: 1; font-weight: 700;
    color: #d9c58e; background: rgba(120,96,40,0.28); border: 1px solid rgba(150,120,60,0.55);
    border-radius: 999px; padding: 2px 7px; text-shadow: 0 1px 2px rgba(0,0,0,0.85); white-space: nowrap;
}
.cost-subzone > .zone-label .cost-spent-badge { font-size: 0.55rem; padding: 1px 5px; }

/* Small "pop out" button in each zone header (Good Habituals, Evil
   Habituals, Available, Spent) — opens the zone in a floating pile modal
   so on mobile every card is reachable even when the in-zone scroll is
   narrow and the third card gets clipped off the right edge. */
.quad-expand-btn {
    margin-left: 0;
    background: rgba(201,168,76,0.12);
    border: 1px solid rgba(201,168,76,0.35);
    color: #e8d199;
    border-radius: 4px;
    min-width: 24px;
    height: 18px;
    padding: 0 5px;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.quad-expand-btn:hover:not(:disabled) { background: rgba(201,168,76,0.28); }
.quad-expand-btn:disabled { cursor: default; }
@media (max-width: 640px) {
    .quad-expand-btn { min-width: 32px; height: 24px; font-size: 14px; }
}

/* Habituals & Tokens display-mode toggle (stacked → fan → grid). */
.quad-mode-btn {
    margin-left: 4px;
    background: rgba(201,168,76,0.12);
    border: 1px solid rgba(201,168,76,0.35);
    color: #e8d199;
    border-radius: 4px;
    min-width: 24px; height: 18px; padding: 0 5px;
    font-size: 12px; line-height: 1; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.quad-mode-btn:hover { background: rgba(201,168,76,0.28); }
@media (max-width: 640px) { .quad-mode-btn { min-width: 32px; height: 24px; font-size: 14px; } }

/* ── Compact TOKEN nameplate tile ─────────────────────────────────────────
   A token renders as a colour-framed nameplate with its name in a big font
   STRETCHED to fill the tile width (SVG textLength). The full card render is
   kept but hidden — it powers hover-zoom + the ability action menu. Tiles
   SHRINK as more habituals+tokens accumulate (var(--field-count)), clamped. */
.token-tile { --tw: clamp(46px, calc(120px - (var(--field-count, 1) - 1) * 9px), 120px); }
.token-tile { width: var(--tw); height: auto; aspect-ratio: 3 / 4; }
.token-tile .token-fullcard { display: none; }
.token-tile .card-cost-overlay { display: none; }   /* tokens have no cost */
.token-nameplate {
    position: relative;
    width: 100%; height: 100%;
    border-radius: 8px;
    overflow: hidden;
    box-sizing: border-box;
    padding: 5px;
    display: flex; align-items: center; justify-content: center;
    box-shadow: 0 2px 8px rgba(0,0,0,0.55), inset 0 0 0 2px rgba(255,255,255,0.14);
    background: linear-gradient(160deg, #5a4712, #c9a84c);   /* default (gold) */
}
.token-nameplate-svg { width: 100%; height: 100%; display: block; }
.token-nameplate-svg text {
    fill: #fdf6df;
    font-family: 'Cinzel', serif;
    font-weight: 800;
    paint-order: stroke;
    stroke: rgba(0,0,0,0.6);
    stroke-width: 1.4px;
}
.token-nameplate[data-card-class="grass"] { background: linear-gradient(160deg,#123f1b,#2f8a3f); }
.token-nameplate[data-card-class="fire"]  { background: linear-gradient(160deg,#4a1410,#a5342a); }
.token-nameplate[data-card-class="ice"]   { background: linear-gradient(160deg,#10344a,#2a72a5); }
.token-nameplate[data-card-class="stone"] { background: linear-gradient(160deg,#3a3a3a,#8f8f8f); }
.token-nameplate[data-card-class="gold"]  { background: linear-gradient(160deg,#5a4712,#c9a84c); }

/* Habituals & Tokens zone: display modes (overlap tightness), like Cost Zone. */
.playmat-quad.quad-good-habituals.field-spread-stacked .card-tile { margin-left: -34px; }
.playmat-quad.quad-good-habituals.field-spread-fan     .card-tile { margin-left: -12px; }
.playmat-quad.quad-good-habituals.field-spread-grid    .card-tile { margin-left: 5px; }
.playmat-quad.quad-good-habituals.field-spread-grid .zone-scrollable { flex-wrap: wrap; }
.playmat-quad.quad-good-habituals .card-tile:first-child { margin-left: 0; }

/* Per-zone zoom controls (−  100%  +) live in the .quad-label alongside
   the ⊞ expand button. Clicking −/+ bumps a --zone-zoom CSS variable on
   the quad, which scales every card tile inside. State persists in
   localStorage so a player who shrinks Good Habituals to see 12 cards at
   once keeps that zoom across refreshes. */
.quad-zoom-group {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    margin-right: 4px;
    flex: 0 0 auto;
    white-space: nowrap;
}
.quad-zoom-btn.quad-zoom-auto { min-width: 22px; }
.quad-zoom-btn {
    background: rgba(201,168,76,0.10);
    border: 1px solid rgba(201,168,76,0.3);
    color: #e8d199;
    border-radius: 3px;
    width: 20px;
    height: 18px;
    padding: 0;
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.quad-zoom-btn:hover { background: rgba(201,168,76,0.25); }
.quad-zoom-readout {
    font-family: 'Nunito Sans', sans-serif;
    font-size: 9px;
    color: rgba(201,168,76,0.6);
    min-width: 28px;
    text-align: center;
    letter-spacing: 0;
    text-transform: none;
}
@media (max-width: 640px) {
    .quad-zoom-btn     { width: 26px; height: 22px; font-size: 15px; }
    .quad-zoom-readout { font-size: 10px; min-width: 32px; }
}

/* Per-zone zoom: scales the card-tile's *actual* width/height via CSS
   calc() so layout reflects the zoom (smaller tiles genuinely fit more).
   Using the width/height path (rather than transform:scale) preserves the
   base .rotated transform on tapped cost-zone cards — transform:scale was
   overwriting the rotate(90deg) and left tapped cards looking un-tapped.
   !important is required to beat the per-quad fixed-size rules further
   down this file (and their mobile.css counterparts). */
.playmat-quad { --zone-zoom: 1; }
.playmat-quad .card-tile {
    width:  calc(var(--base-tile-w, 90px)  * var(--zone-zoom)) !important;
    height: calc(var(--base-tile-h, 132px) * var(--zone-zoom)) !important;
}
.playmat-quad.quad-good-habituals { --base-tile-w: 90px;  --base-tile-h: 132px; }
.playmat-quad.quad-evil-habituals { --base-tile-w: 90px;  --base-tile-h: 132px; }
.playmat-quad.quad-available,
.playmat-quad.quad-spent           { --base-tile-w: 90px;  --base-tile-h: 132px; }
@media (max-width: 820px) {
    .playmat-quad.quad-good-habituals,
    .playmat-quad.quad-evil-habituals { --base-tile-w: 54px; --base-tile-h: 78px; }
    .playmat-quad.quad-available,
    .playmat-quad.quad-spent          { --base-tile-w: 72px; --base-tile-h: 104px; }
}

.playmat-quad .zone-scrollable {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-content: flex-start;
    overflow: auto;
    min-height: 55px;
}

/* Quadrant color overlays matching physical playmat */
.quad-good-habituals {
    background: rgba(20, 80, 60, 0.85);
    border-right: 1px solid rgba(255,255,255,0.1);
    border-bottom: 1px solid rgba(255,255,255,0.1);
}
.quad-evil-habituals {
    background: rgba(100, 20, 20, 0.85);
    border-bottom: 1px solid rgba(255,255,255,0.1);
}
.quad-available {
    background: rgba(30, 100, 50, 0.85);
    border-right: 1px solid rgba(255,255,255,0.1);
}
.quad-spent {
    background: rgba(120, 60, 20, 0.85);
}

/* Evil habituals in the quad — same animation as evil field */
.quad-evil-habituals .card-tile {
    border-color: rgba(180,0,0,0.5);
    box-shadow: 0 0 8px rgba(120,0,0,0.4), 0 0 0 1px rgba(180,0,0,0.25);
    animation: temptPulse 3.5s ease-in-out infinite alternate;
}

/* Card sizing inside the quad zones */
.playmat-quad .card-tile {
    width: 120px;
    height: 176px;
}
.playmat-quad .ch-card-root { --ch-scale: 0.16; }

.playmat-quad.quad-good-habituals .card-tile {
    width: 90px;
    height: 132px;
}
.playmat-quad.quad-good-habituals .ch-card-root { --ch-scale: 0.12; }

/* Stacked same-named field cards: small overlap badge + a subtle layered
   shadow so it reads as "more than one" even before the ×N label loads. */
.card-tile.stacked {
    box-shadow: 4px 4px 0 -1px rgba(201,168,76,0.35), 7px 7px 0 -2px rgba(201,168,76,0.2);
}
.card-tile-stack-count {
    position: absolute;
    top: 2px;
    right: 2px;
    background: rgba(0,0,0,0.85);
    color: #f0d07a;
    border: 1px solid rgba(201,168,76,0.55);
    border-radius: 10px;
    padding: 1px 6px;
    font-size: 11px;
    font-weight: 700;
    font-family: 'Cinzel', serif;
    line-height: 1.2;
    pointer-events: none;
    z-index: 2;
}

/* Mobile: shrink the card art scaler so the ch-card-root sizes match the
 * reduced --base-tile-w/h set by mobile.css. Tile width/height is owned
 * by the .playmat-quad .card-tile calc() rule above so --zone-zoom takes
 * effect; do not re-hardcode width/height here. */
@media (max-width: 640px) {
    .playmat-quad.quad-good-habituals .ch-card-root,
    .playmat-quad.quad-evil-habituals .ch-card-root { --ch-scale: 0.072; }
    .card-tile-stack-count { font-size: 9px; padding: 1px 4px; }
}

/* Evil habituals: compact — hover to read full text */
.playmat-quad.quad-evil-habituals .card-tile {
    width: 90px;
    height: 132px;
}
.playmat-quad.quad-evil-habituals .ch-card-root { --ch-scale: 0.12; }

/* Cost zone quads: match the evil-habituals tile size so the zone uses its
 * full vertical band instead of leaving a huge empty strip above/below a
 * row of tiny thumbnails. */
.playmat-quad.quad-available .card-tile,
.playmat-quad.quad-spent .card-tile {
    width: 90px;
    height: 132px;
}
.playmat-quad.quad-available .ch-card-root,
.playmat-quad.quad-spent .ch-card-root { --ch-scale: 0.12; }

/* Compact stacking: once cards start to overflow, overlap them horizontally.
   The Spent quad's tiles are rotated 90° so they're taller than wide; overlap
   via negative margin so only a sliver of each card peeks out, preserving
   horizontal space in a single row. Available uses a similar stack for symmetry.
   A per-quad ::after count badge appears automatically when overflow is risky. */
.playmat-quad.quad-spent .zone-scrollable,
.playmat-quad.quad-available .zone-scrollable {
    flex-wrap: nowrap;
    overflow: hidden;
    align-items: center;
    padding-right: 40px;   /* leave room for the count badge */
    position: relative;
}
/* Rotated spent cards take ~180px tall at the new scale; overlap them so
 * they still fit across the quad. */
.playmat-quad.quad-spent .card-tile.rotated {
    margin-left: -56px;
    transition: margin-left 0.15s ease, transform 0.15s ease;
}
.playmat-quad.quad-spent .card-tile.rotated:first-child { margin-left: 0; }
.playmat-quad.quad-spent .card-tile.rotated:hover {
    margin-left: -16px;
    z-index: 5;
    transform: rotate(90deg) translateY(-4px) scale(1.08);
}
/* Available cards upright; overlap similarly */
.playmat-quad.quad-available .card-tile {
    margin-left: -36px;
}
.playmat-quad.quad-available .card-tile:first-child { margin-left: 0; }
/* Cost-zone spread modes (override the base overlap above). Values are
 * ~0.4 / 0.15 / 0 × card-width so the visual overlap ratio stays constant
 * across tile sizes. */
.playmat-quad.quad-available.cost-spread-stacked .card-tile { margin-left: -36px; }
.playmat-quad.quad-available.cost-spread-fan     .card-tile { margin-left: -14px; }
.playmat-quad.quad-available.cost-spread-grid    .card-tile { margin-left: 4px; }
.playmat-quad.quad-spent.cost-spread-stacked .card-tile.rotated { margin-left: -56px; }
.playmat-quad.quad-spent.cost-spread-fan     .card-tile.rotated { margin-left: -22px; }
.playmat-quad.quad-spent.cost-spread-grid    .card-tile.rotated { margin-left: 4px; }
.playmat-quad.cost-spread-stacked .card-tile:first-child,
.playmat-quad.cost-spread-fan     .card-tile:first-child,
.playmat-quad.cost-spread-grid    .card-tile:first-child,
.playmat-quad.cost-spread-stacked .card-tile.rotated:first-child,
.playmat-quad.cost-spread-fan     .card-tile.rotated:first-child,
.playmat-quad.cost-spread-grid    .card-tile.rotated:first-child { margin-left: 0; }
.playmat-quad.cost-spread-grid > :is(.zone-scrollable, *) { flex-wrap: wrap; }

/* Split-peek layout — when one or more face-down cost-zone cards
 * get flipped face-up (via Flip / peek), show them in a dedicated
 * row above the remaining face-down stack so the revealed cards
 * aren't buried by the negative-margin overlap. */
.zone-scrollable.zone-split-peek {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 4px !important;
    overflow-x: visible !important;
    overflow-y: auto !important;
}
.zone-scrollable.zone-split-peek .zone-faceup-row,
.zone-scrollable.zone-split-peek .zone-facedown-row {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-end;
    width: 100%;
}
.zone-scrollable.zone-split-peek .zone-faceup-row {
    gap: 4px;
    overflow-x: auto;
    padding-bottom: 2px;
    border-bottom: 1px dashed rgba(201,168,76,0.35);
}
.zone-scrollable.zone-split-peek .zone-facedown-row {
    overflow-x: auto;
    padding-top: 2px;
}
/* Re-apply the existing stacked overlap to the face-down row only —
 * the face-up row uses normal gap spacing so each revealed card is
 * fully visible. */
.zone-scrollable.zone-split-peek .zone-facedown-row .card-tile { margin-left: -36px; }
.zone-scrollable.zone-split-peek .zone-facedown-row .card-tile:first-child { margin-left: 0; }
.playmat-quad.quad-available .card-tile:hover {
    margin-left: -4px;
    z-index: 5;
    transform: translateY(-4px) scale(1.08);
}
/* Count badge on the right edge of each quad */
.playmat-quad.quad-spent::after,
.playmat-quad.quad-available::after {
    content: attr(data-count);
    position: absolute;
    right: 8px;
    bottom: 8px;
    min-width: 26px;
    height: 22px;
    padding: 0 8px;
    border-radius: 11px;
    background: rgba(0,0,0,0.72);
    color: #f0c040;
    font-family: 'Cinzel', serif;
    font-size: 12px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    border: 1px solid rgba(201,168,76,0.4);
    z-index: 6;
}
.playmat-quad.quad-spent:not([data-count])::after,
.playmat-quad.quad-available:not([data-count])::after,
.playmat-quad.quad-spent[data-count="0"]::after,
.playmat-quad.quad-available[data-count="0"]::after {
    display: none;
}

/* Floating mana badge — pre-tapped cost-zone cards whose mana is still
   spendable this phase. Sits at the top-right of the Available quad in a
   distinct green so it reads separately from the bottom-right count. */
/* CSS-only fallback badge — kept in case JS hasn't rendered the real
 * .quad-float-btn yet (e.g. during the first paint). The interactive
 * button below replaces it as soon as JS runs. */
.playmat-quad.quad-available[data-floating]:not(:has(.quad-float-btn))::before {
    content: "+" attr(data-floating) " floating";
    position: absolute;
    right: 8px;
    top: 8px;
    padding: 2px 10px;
    border-radius: 11px;
    background: rgba(40, 120, 50, 0.85);
    color: #d8f0b8;
    font-family: 'Cinzel', serif;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
    pointer-events: none;
    border: 1px solid rgba(180, 220, 140, 0.45);
    box-shadow: 0 0 6px rgba(80, 200, 100, 0.35);
    z-index: 6;
}
/* Real interactive pill that opens the clear-floating menu. */
.playmat-quad.quad-available .quad-float-btn {
    position: absolute;
    right: 8px;
    top: 8px;
    padding: 3px 10px;
    border-radius: 11px;
    background: rgba(40, 120, 50, 0.9);
    color: #d8f0b8;
    font-family: 'Cinzel', serif;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
    border: 1px solid rgba(180, 220, 140, 0.5);
    box-shadow: 0 0 6px rgba(80, 200, 100, 0.35);
    z-index: 7;
    cursor: pointer;
    min-height: 24px;
    touch-action: manipulation;
}
.playmat-quad.quad-available .quad-float-btn:hover,
.playmat-quad.quad-available .quad-float-btn:focus {
    background: rgba(60, 150, 70, 1);
    outline: none;
}

/* Floating-mana tag inside the player's Cost stat badge. Mirrors the
 * quad corner badge's green so it's recognisable, but lives in the
 * always-visible stat bar at the top of each player area - the mobile
 * playmat is often too cramped to rely on the quad corner alone. */
.stat-badge.cost-stat.has-floating {
    box-shadow: 0 0 0 1px rgba(120, 220, 140, 0.55) inset;
}
.stat-badge .cost-float-tag {
    margin-left: 4px;
    padding: 1px 6px;
    border-radius: 8px;
    background: rgba(40, 120, 50, 0.85);
    color: #d8f0b8;
    font-weight: 700;
    font-size: 0.9em;
    border: 1px solid rgba(180, 220, 140, 0.45);
    cursor: pointer;
    font-family: inherit;
}
.stat-badge .cost-float-tag:hover,
.stat-badge .cost-float-tag:focus {
    background: rgba(60, 150, 70, 0.95);
    outline: none;
}

/* Hand-view stat button — injected by _renderPlayerArea so every
 * player has a one-tap shortcut to the full-hand modal, since the
 * bottom hand-row is often off-screen on 2-player mobile layouts. */
.stat-badge.stat-hand-btn {
    cursor: pointer;
    background: rgba(60, 40, 10, 0.85);
    border-color: rgba(201, 168, 76, 0.5);
    color: #f0d07a;
}
.stat-badge.stat-hand-btn:hover,
.stat-badge.stat-hand-btn:focus {
    background: rgba(90, 60, 20, 0.95);
    outline: none;
}
.stat-badge.stat-hand-btn .stat-hand-count {
    display: inline-block;
    min-width: 18px;
    margin-left: 4px;
    padding: 0 5px;
    border-radius: 9px;
    background: rgba(0, 0, 0, 0.55);
    font-weight: 700;
    text-align: center;
}

/* Per-player collapse toggle — lets you fold one player's playmat +
 * evil strip + hand-row out of the way so the other player's area
 * has room to breathe. Stats bar stays visible so pile counts and
 * the Hand button remain reachable. */
.stat-badge.stat-collapse-btn {
    cursor: pointer;
    background: rgba(30, 30, 40, 0.85);
    border-color: rgba(180, 180, 200, 0.35);
    color: #d0d0e0;
    font-weight: 700;
}
.stat-badge.stat-collapse-btn:hover,
.stat-badge.stat-collapse-btn:focus {
    background: rgba(50, 50, 70, 0.95);
    outline: none;
}
.player-area.area-collapsed > :not(.player-stats):not(.player-name) {
    display: none !important;
}

/* ─── Multi-player view modes ────────────────────────────────────────────── */
/* Tabs mode: show one righteous player area at a time. The tab bar
 * (#player-tabs) lives at the top of the viewport; JS sets
 * .player-area-tab-active on the selected player. */
.player-tabs {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 920;
    gap: 4px;
    padding: 4px 8px;
    flex-wrap: nowrap;
    overflow-x: auto;
    border-bottom: 1px solid rgba(201,168,76,0.25);
    background: rgba(0,0,0,0.85);
}
body.view-tabs .player-tabs { display: flex; }
.player-tabs .player-tab {
    flex: 0 0 auto;
    padding: 6px 14px;
    border: 1px solid rgba(201,168,76,0.4);
    background: rgba(20,10,0,0.7);
    color: #d0b070;
    font-family: 'Cinzel', serif;
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border-radius: 6px 6px 0 0;
    cursor: pointer;
    min-height: 36px;
}
.player-tabs .player-tab.active {
    background: linear-gradient(180deg, rgba(70,50,10,0.95), rgba(35,20,0,0.95));
    color: #f0d07a;
    border-color: rgba(240,208,122,0.65);
    box-shadow: 0 0 10px rgba(240,208,122,0.2);
}
.player-tabs .player-tab.taking-turn::after {
    content: ' ▶';
    color: #f0c040;
    animation: turnPulse 2s ease-in-out infinite;
}
body.view-tabs .player-area.righteous { display: none !important; }
body.view-tabs .player-area.righteous.player-area-tab-active {
    display: flex !important;
    grid-column: 1 / -1 !important;
    grid-row: auto !important;
}
.player-area.area-collapsed {
    min-height: 0 !important;
    max-height: none !important;
    flex: 0 0 auto !important;
    padding: 0 !important;
    cursor: pointer;
}
.player-area.area-collapsed .player-stats {
    padding: 2px 6px !important;
    gap: 4px !important;
    min-height: 0 !important;
    flex-wrap: wrap !important;
    align-items: center !important;
}
/* Ultra-compact mode: only the essentials on a collapsed area so two
 * collapsed players take ~60px combined instead of 180px. */
.player-area.area-collapsed .player-stats .stat-badge:not(.stat-hand-btn):not(.stat-collapse-btn):not(.pile-stat) {
    display: none !important;
}
/* Scale down the surviving badges so the whole strip is ~30px tall. */
.player-area.area-collapsed .player-stats .stat-badge {
    padding: 2px 6px !important;
    font-size: 10px !important;
    min-height: 22px !important;
}

@media (min-width: 768px) {
    .playmat-grid {
        min-height: 280px;
    }
    .playmat-quad {
        min-height: 140px;
        padding: 8px 12px 10px;
    }
    .playmat-quad .quad-label {
        font-size: 0.65rem;
    }
    .playmat-quad.quad-good-habituals .card-tile {
        width: 110px;
        height: 161px;
    }
    .playmat-quad.quad-good-habituals .ch-card-root { --ch-scale: 0.147; }
    .playmat-quad.quad-evil-habituals .card-tile {
        width: 110px;
        height: 161px;
    }
    .playmat-quad.quad-evil-habituals .ch-card-root { --ch-scale: 0.147; }
    .playmat-quad.quad-available .card-tile,
    .playmat-quad.quad-spent .card-tile {
        width: 58px;
        height: 85px;
    }
    .playmat-quad.quad-available .ch-card-root,
    .playmat-quad.quad-spent .ch-card-root { --ch-scale: 0.077; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Hand Zone Header + Count Badge + Expand Button
   ═══════════════════════════════════════════════════════════════════════════ */

.hand-zone-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    margin-bottom: 4px;
}

.hand-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    background: rgba(201,168,76,0.18);
    border: 1px solid rgba(201,168,76,0.35);
    border-radius: 8px;
    font-size: 9px;
    font-family: 'Cinzel', serif;
    color: rgba(201,168,76,0.85);
    font-weight: 600;
    line-height: 1;
    vertical-align: middle;
}

.hand-expand-btn {
    background: rgba(201,168,76,0.08);
    border: 1px solid rgba(201,168,76,0.25);
    border-radius: 4px;
    color: rgba(201,168,76,0.6);
    font-size: 13px;
    line-height: 1;
    padding: 2px 5px;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    flex-shrink: 0;
}
.hand-expand-btn:hover {
    background: rgba(201,168,76,0.18);
    border-color: rgba(201,168,76,0.55);
    color: rgba(201,168,76,1);
}

/* ═══════════════════════════════════════════════════════════════════════════
   Hand Pop-out Modal
   ═══════════════════════════════════════════════════════════════════════════ */

.hand-modal {
    position: fixed;
    inset: 0;
    z-index: 2000;
    pointer-events: none; /* board stays clickable behind the floating/docked panel */
}
.hand-modal.hidden { display: none; }

/* Backdrop left in the DOM (role=aria-modal), but no dim — the modal is
 * a dockable panel, not a focus-trap sheet. */
.hand-modal-backdrop { display: none; }

.hand-modal-panel {
    position: fixed;
    pointer-events: auto;
    z-index: 1;
    background: linear-gradient(180deg, #1a1610 0%, #110f0a 100%);
    border: 1px solid rgba(201,168,76,0.25);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    box-shadow: 0 -8px 40px rgba(0,0,0,0.7), 0 -1px 0 rgba(201,168,76,0.12) inset;
}

/* ── Hand modal dock modes ─────────────────────────────────────────────
 * Each mode applies a fixed-position snap against an edge. `free` is a
 * draggable/resizable floating window. Defaults live here so the JS only
 * needs to toggle a class. */
.hand-modal-panel.dock-bottom {
    left: 50%; right: auto; bottom: 0; top: auto;
    transform: translateX(-50%);
    width: 100%;
    max-width: 900px;
    max-height: 80vh;
    border-bottom: none;
    border-radius: 16px 16px 0 0;
}
.hand-modal-panel.dock-top {
    left: 50%; right: auto; top: 0; bottom: auto;
    transform: translateX(-50%);
    width: 100%;
    max-width: 900px;
    max-height: 80vh;
    border-top: none;
    border-radius: 0 0 16px 16px;
}
.hand-modal-panel.dock-left {
    left: 0; right: auto; top: 0; bottom: 0;
    width: min(42vw, 720px);
    max-height: 100vh;
    border-left: none;
    border-radius: 0 16px 16px 0;
}
.hand-modal-panel.dock-right {
    right: 0; left: auto; top: 0; bottom: 0;
    width: min(42vw, 720px);
    max-height: 100vh;
    border-right: none;
    border-radius: 16px 0 0 16px;
}

/* Mobile: a 42vw side panel is too narrow to fit the header's dock
   buttons + close button, which was pushing the ✕ off-screen. Take the
   full viewport so the whole header is reachable; keep dock-right's
   semantic state so the user's preference persists for desktop. Also
   let the header wrap if absolutely needed so ✕ never gets clipped. */
@media (max-width: 820px) {
    .hand-modal-panel.dock-right,
    .hand-modal-panel.dock-left {
        width: 100vw !important;
        max-width: 100vw !important;
        left: 0 !important; right: 0 !important;
        border-radius: 0 !important;
    }
    .hand-modal-header { flex-wrap: wrap; }
    .hand-modal-close  { position: relative; z-index: 2; }
}
.hand-modal-panel.dock-free {
    left: 80px; top: 80px; right: auto; bottom: auto;
    width: 780px; height: 520px;
    min-width: 340px; min-height: 220px;
    max-width: 100vw; max-height: 100vh;
    border-radius: 14px;
    resize: both;
}
.hand-modal-panel.dock-free .hand-modal-header { cursor: move; }

/* Dock button group in the header. */
.hand-modal-dock { display: inline-flex; gap: 3px; margin-left: auto; }
.hand-modal-dock-btn {
    background: rgba(201,168,76,0.08);
    border: 1px solid rgba(201,168,76,0.25);
    color: #e8d199;
    border-radius: 5px;
    width: 26px; height: 22px;
    padding: 0;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    transition: background 0.1s ease;
}
.hand-modal-dock-btn:hover { background: rgba(201,168,76,0.2); }
.hand-modal-dock-btn.active {
    background: rgba(201,168,76,0.35);
    border-color: rgba(201,168,76,0.6);
    color: #fff;
}

@keyframes hand-modal-slide-up {
    from { transform: translateY(40px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}

.hand-modal-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border-bottom: 1px solid rgba(201,168,76,0.12);
    flex-shrink: 0;
    background: linear-gradient(90deg, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0.2) 100%);
    border-top: 2px solid rgba(201,168,76,0.3);
}

.hand-modal-header[data-card-type="fire"] {
    background: linear-gradient(90deg, rgba(122,38,0,0.6) 0%, rgba(80,20,0,0.3) 100%);
    border-top-color: rgba(255,100,50,0.5);
}
.hand-modal-header[data-card-type="grass"] {
    background: linear-gradient(90deg, rgba(26,90,26,0.6) 0%, rgba(15,60,15,0.3) 100%);
    border-top-color: rgba(100,200,100,0.5);
}
.hand-modal-header[data-card-type="ice"] {
    background: linear-gradient(90deg, rgba(0,48,96,0.6) 0%, rgba(0,30,60,0.3) 100%);
    border-top-color: rgba(100,150,255,0.5);
}
.hand-modal-header[data-card-type="stone"] {
    background: linear-gradient(90deg, rgba(48,48,48,0.6) 0%, rgba(30,30,30,0.3) 100%);
    border-top-color: rgba(150,150,150,0.5);
}
.hand-modal-header[data-card-type="gold"] {
    background: linear-gradient(90deg, rgba(122,102,30,0.6) 0%, rgba(80,70,20,0.3) 100%);
    border-top-color: rgba(255,200,80,0.5);
}

.hand-modal-type-icon {
    width: 24px;
    height: 24px;
    object-fit: contain;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.6));
    flex-shrink: 0;
}

.hand-modal-title {
    font-family: 'Cinzel', serif;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: rgba(201,168,76,0.95);
    text-transform: uppercase;
    flex-shrink: 0;
}

.hand-modal-hint {
    font-family: 'Cinzel', serif;
    font-size: 8px;
    letter-spacing: 0.08em;
    color: rgba(201,168,76,0.4);
    flex: 1;
    text-transform: uppercase;
    min-width: 0;
}

.hand-modal-cost {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    background: #22a12a;
    border: 2px solid rgba(0,0,0,0.4);
    border-radius: 4px;
    color: #fff;
    font-family: 'Cinzel', serif;
    font-size: 12px;
    font-weight: 700;
    flex-shrink: 0;
    box-shadow: 0 2px 4px rgba(0,0,0,0.5);
}

.hand-modal-close {
    background: none;
    border: 1px solid rgba(201,168,76,0.2);
    border-radius: 3px;
    color: rgba(201,168,76,0.5);
    font-size: 12px;
    width: 22px;
    height: 22px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.15s;
    flex-shrink: 0;
}
.hand-modal-close:hover {
    background: rgba(201,168,76,0.12);
    border-color: rgba(201,168,76,0.5);
    color: rgba(201,168,76,1);
}

.hand-modal-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 6px 8px;
    overflow-y: auto;
    align-content: center;
    justify-content: center;
    flex: 1 1 auto;
    min-height: 0;
    scrollbar-width: thin;
    scrollbar-color: rgba(201,168,76,0.25) transparent;
}
.hand-modal-grid::-webkit-scrollbar { width: 4px; }
.hand-modal-grid::-webkit-scrollbar-thumb {
    background: rgba(201,168,76,0.25);
    border-radius: 2px;
}

/* Card tiles track the panel size — JS writes --hm-card-h on the panel
 * from a ResizeObserver, and width/scale are derived from the card's
 * 750×1100 aspect ratio so cards stay in proportion as the user drags
 * the resize handle. Fallbacks keep the old fixed size working before
 * the observer fires. */
/* JS writes --hm-card-h (px length) and --hm-card-scale (unitless number)
 * on the panel from a ResizeObserver. Width is derived from height via
 * the card's 750×1100 aspect ratio. The scale MUST be unitless — a
 * length fails silently in `transform: scale(...)` and leaves the root
 * un-scaled at 750×1100 so the tile clips to a solid frame colour. */
.hand-modal-panel {
    --hm-card-h: 177px;
    --hm-card-scale: 0.16;
    --hm-card-w: calc(var(--hm-card-h) * 750 / 1100);
}
.hand-modal-grid .card-tile {
    width: var(--hm-card-w);
    height: var(--hm-card-h);
}
.hand-modal-grid .ch-card-root {
    --ch-scale: var(--hm-card-scale);
}

/* Empty state */
.hand-modal-empty {
    width: 100%;
    text-align: center;
    font-family: 'Cinzel', serif;
    font-size: 11px;
    letter-spacing: 0.12em;
    color: rgba(201,168,76,0.3);
    padding: 32px 0;
    text-transform: uppercase;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Temptation / Habitual icons in rules text — larger for readability
   ═══════════════════════════════════════════════════════════════════════════ */

.ch-card-root .card-graphics-img.temptation,
.ch-card-root .card-graphics-img.temptation_romanwar,
.ch-card-root .card-graphics-img.habitual_good,
.ch-card-root .card-graphics-img.habitual_evil,
.ch-card-root .card-graphics-img.habitual_good_romanwar,
.ch-card-root .card-graphics-img.habitual_evil_romanwar {
    /* Scale with the surrounding rules text (~4rem on card face) so the
     * icon reads at roughly the same visual weight as adjacent words
     * instead of shrinking to a tiny glyph. */
    height: 1.15em;
    width: auto;
    vertical-align: -0.18em;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Pinned Card Inspect Panel
   ═══════════════════════════════════════════════════════════════════════════ */

.card-pin-panel {
    position: fixed !important;
    /* High enough to clear the phase-bar (1000), penalty overlay (9999),
     * and hover zoom (10050), but below the ctx-menu (10100) -- the
     * right-click menu must always win. body.pin-panel-open drops the
     * phase-bar to z-index 1 as belt-and-braces against the backdrop-
     * filter compositor ordering bug that originally motivated using the
     * 32-bit max z-index here. */
    z-index: 10090 !important;
    isolation: isolate;
    will-change: transform;
    background: linear-gradient(180deg, #1c1a14 0%, #110f0a 100%);
    border: 1px solid rgba(201,168,76,0.35);
    border-radius: 14px;
    box-shadow: 0 12px 48px rgba(0,0,0,0.85), 0 0 0 1px rgba(201,168,76,0.1) inset;
    overflow: hidden;
    min-width: 180px;
    min-height: 100px;
    max-width: 92vw;
    max-height: 95vh;
    resize: both;
    animation: pin-panel-pop 0.2s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.card-pin-panel { display: none; flex-direction: column; }
.card-pin-panel.visible { display: flex; }

/* Mobile safety net: clamp pinned panels into the viewport so the close
   button never sits off-screen, even if a cached desktop-size carried over
   into a narrow session. */
@media (max-width: 820px) {
    .card-pin-panel {
        max-width: calc(100vw - 12px) !important;
        max-height: calc(100vh - 12px) !important;
    }
    .card-pin-close { position: relative; z-index: 5; }
}

/* Belt-and-suspenders: when a pin panel exists, kick phase-bar's stacking
   context below it. Targeted at the rare case where compositor/backdrop-
   filter ordering wins over our z-index. */
body.pin-panel-open #phase-bar { z-index: 1 !important; }

@keyframes pin-panel-pop {
    from { transform: scale(0.88); opacity: 0; }
    to   { transform: scale(1);    opacity: 1; }
}

.card-pin-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-bottom: 2px solid rgba(201,168,76,0.2);
    cursor: move;
    user-select: none;
    -webkit-user-select: none;
    flex-shrink: 0;
    position: relative;
    /* Art background set by JS; fallback color below */
    background-color: #1c1a14;
    background-size: cover;
    background-position: center top;
    border-top: 2px solid rgba(201,168,76,0.4);
    min-height: 40px;
}
/* Dark overlay so art stays readable */
.card-pin-header::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, rgba(0,0,0,0.78) 0%, rgba(0,0,0,0.5) 60%, rgba(0,0,0,0.35) 100%);
    pointer-events: none;
    z-index: 0;
}
/* All direct children sit above the overlay */
.card-pin-header > * {
    position: relative;
    z-index: 1;
}

/* Border accent per card type (art handles the color; border adds type hint) */
.card-pin-header[data-card-type="fire"]  { border-top-color: rgba(255,100,50,0.6);  border-bottom-color: rgba(255,100,50,0.25); }
.card-pin-header[data-card-type="grass"] { border-top-color: rgba(80,200,80,0.6);   border-bottom-color: rgba(80,200,80,0.25); }
.card-pin-header[data-card-type="ice"]   { border-top-color: rgba(100,150,255,0.6); border-bottom-color: rgba(100,150,255,0.25); }
.card-pin-header[data-card-type="stone"] { border-top-color: rgba(160,160,160,0.6); border-bottom-color: rgba(160,160,160,0.25); }
.card-pin-header[data-card-type="gold"]  { border-top-color: rgba(255,200,80,0.6);  border-bottom-color: rgba(255,200,80,0.25); }

.card-pin-type-icon {
    width: 20px;
    height: 20px;
    object-fit: contain;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.6));
    flex-shrink: 0;
}

.card-pin-name {
    font-family: 'Cinzel', serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.09em;
    color: rgba(201,168,76,0.9);
    text-transform: uppercase;
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Token creator modal (right-click any card → Create Token…). */
.token-creator-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9000;
}
.token-creator-panel {
    background: linear-gradient(180deg, #1c1a14 0%, #110f0a 100%);
    border: 1px solid rgba(201,168,76,0.45);
    border-radius: 10px;
    min-width: 340px;
    max-width: 460px;
    box-shadow: 0 12px 48px rgba(0,0,0,0.85);
    color: #eee;
}
.token-creator-header {
    font-family: 'Cinzel', serif;
    font-size: 13px;
    letter-spacing: 0.1em;
    padding: 10px 14px;
    border-bottom: 1px solid rgba(201,168,76,0.2);
    color: rgba(230,200,140,0.95);
}
.token-creator-body {
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.token-creator-body label {
    display: flex;
    flex-direction: column;
    gap: 3px;
    font-size: 11px;
    color: #bbb;
    font-family: 'Nunito Sans', sans-serif;
}
.token-creator-body input,
.token-creator-body select,
.token-creator-body textarea {
    background: #0c0c0c;
    border: 1px solid #333;
    border-radius: 5px;
    color: #fff;
    font-size: 13px;
    padding: 6px 8px;
    font-family: inherit;
}
.token-creator-body textarea { resize: vertical; min-height: 50px; }

/* Admin Edit-Card explicit paste/drop zone — the reliable, focus-first target
   for setting card art. Click it to arm (visible focus ring), then Ctrl/Cmd+V
   or drop an image; both route through the shared upload flow. */
.ace-art-zone {
    margin: 6px 0 2px;
    padding: 12px 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    min-height: 44px;
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.35;
    color: #ffe6a3;
    background: rgba(20, 16, 10, 0.55);
    border: 2px dashed rgba(240, 208, 122, 0.6);
    border-radius: 8px;
    cursor: pointer;
    user-select: none;
    outline: none;
    transition: border-color 0.12s ease, background 0.12s ease, box-shadow 0.12s ease, color 0.12s ease;
}
.ace-art-zone:hover { border-color: rgba(240, 208, 122, 0.9); background: rgba(30, 24, 14, 0.7); }
.ace-art-zone:focus,
.ace-art-zone:focus-visible {
    border-color: #f0d07a;
    border-style: solid;
    background: rgba(40, 32, 16, 0.8);
    box-shadow: 0 0 0 3px rgba(240, 208, 122, 0.35);
    color: #fff2cf;
}
.ace-art-zone.is-drag {
    border-color: #f0d07a;
    border-style: solid;
    background: rgba(52, 42, 20, 0.85);
    box-shadow: 0 0 0 3px rgba(240, 208, 122, 0.45);
}
.ace-art-zone.is-ok {
    border-color: #7ddf8e;
    border-style: solid;
    background: rgba(20, 44, 24, 0.85);
    box-shadow: 0 0 0 3px rgba(125, 223, 142, 0.4);
    color: #baf5c6;
}

/* Admin-only "unparseable rules" badge — small yellow ⚠ on the card's
   top-right (cost badge is bottom-left, so no overlap). Lives on the scaler
   (real pixels) so it stays ~14px regardless of the card's transform scale. */
.card-unparseable-badge {
    position: absolute;
    top: 2px;
    right: 2px;
    z-index: 40;
    width: 15px;
    height: 15px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    line-height: 1;
    color: #1a1208;
    background: radial-gradient(circle at 35% 30%, #ffe27a, #e6b400);
    border: 1px solid rgba(90,60,0,0.85);
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0,0,0,0.6);
    cursor: pointer;
    pointer-events: auto;
    opacity: 0.9;
    transition: transform 0.1s ease-out, opacity 0.1s ease-out;
}
.card-unparseable-badge:hover { opacity: 1; transform: scale(1.15); }

/* Activated-counter charge badge (top-left; cost badge is bottom-left, ⚠ is
   top-right, so no overlap). */
/* Clock-icon counter badge (overrides the earlier .card-counter-badge for
   board tiles rendered later in the cascade). The blue clock is the base;
   the count sits centered on its face — no pill background. */
.card-counter-badge {
    position: absolute;
    top: 2px;
    left: 2px;
    z-index: 40;
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
    pointer-events: none;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.65));
}

/* Inline COUNTER glyph: clock icon (theme-neutral, all themes) with an
   optional sign/number overlaid on the face, scaling with font-size. */
.counter-glyph {
    position: relative;
    display: inline-block;
    vertical-align: middle;
    line-height: 1;
    /* Scale the WHOLE glyph (clock dial + its centered value scale off em) so
       the counter clock reads bigger while staying proportioned & aligned. */
    font-size: 1.4em;
}
.counter-glyph img.card-graphics-img.counter {
    height: 1.15em;
    width: auto;
    min-height: 0;
    vertical-align: middle;
    display: inline-block;
}
.counter-glyph-overlay {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-family: 'Cinzel', serif;
    font-weight: 900;
    font-size: 1.08em;          /* BIG — a single glyph nearly fills the dial edge-to-edge */
    letter-spacing: -0.03em;
    line-height: 1;
    /* White fill with a crisp dark-navy outline so the value pops over the busy
       blue/white clock face (light dial + dark rim ticks). paint-order paints the
       stroke behind the fill; text-shadow is the fallback halo for engines that
       ignore -webkit-text-stroke. */
    color: #ffffff;
    /* Thick PURE-BLACK outline so the white value reads over the light-blue/white
       clock dial (the thin navy stroke washed out). */
    -webkit-text-stroke: 0.16em #000000;
    paint-order: stroke fill;
    text-shadow:
        0 0 2px #000, 0 0 3px #000,
        1.5px 1.5px 0 #000, -1.5px -1.5px 0 #000,
        1.5px -1.5px 0 #000, -1.5px 1.5px 0 #000;
    white-space: nowrap;
    pointer-events: none;
}
/* Shrink as the value gets wider so it still fits the dial. 1 char (X, 5) is
   the biggest; a signed pair ("+2"/"−X") or "12" is medium; 3+ ("X−1") smaller. */
.counter-glyph-overlay.cg-len1 { font-size: 1.08em; }
.counter-glyph-overlay.cg-len2 { font-size: 0.78em; letter-spacing: -0.05em; }
.counter-glyph-overlay.cg-len3 { font-size: 0.60em; letter-spacing: -0.06em; }

/* Admin card editor — two-pane layout: live card render beside the form. */
.token-creator-panel.ace-panel-wide {
    max-width: 760px;
    width: min(760px, 94vw);
    max-height: 92vh;
    display: flex;
    flex-direction: column;
}
/* NON-MODAL floating editor: a free-standing panel (no full-screen backdrop),
   so the admin can keep interacting with the board and other panels while it's
   open. Positioned top-right by default; draggable by its header. */
.ace-floating {
    position: fixed;
    top: 54px;
    right: 16px;
    z-index: 9500;
    box-shadow: 0 16px 60px rgba(0,0,0,0.9);
}
.ace-floating .token-creator-header.ace-drag-handle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    cursor: move;
    user-select: none;
}
.ace-floating .ace-close {
    background: transparent;
    border: 1px solid rgba(201,168,76,0.5);
    color: #f0d07a;
    border-radius: 5px;
    width: 24px;
    height: 22px;
    /* Center the ✕ glyph both axes — line-height alone left it off-center. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    line-height: 1;
    font-size: 13px;
    cursor: pointer;
    flex: 0 0 auto;
}
.ace-floating .ace-close:hover { background: rgba(201,168,76,0.18); border-color: #f0d07a; }
.ace-two-pane {
    display: flex;
    gap: 14px;
    padding: 12px 14px;
    overflow: auto;
}
.ace-card-pane {
    flex: 0 0 auto;
    display: flex;
    /* Keep the live card preview visible while the (long) form pane scrolls:
       pin the card pane to the top of the scrolling .ace-two-pane. align-self
       flex-start so it doesn't stretch the full row height (needed for sticky
       inside a flex row). Reset to static in the mobile column stack below. */
    position: sticky;
    top: 0;
    align-self: flex-start;
    z-index: 2;
    /* Column: the view-as pills stack ABOVE the render. Keeps the pane at
       the render's width — with the pills beside the card the pane grew to
       the bar's natural width and squeezed the form fields. */
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
}
.ace-card-render {
    position: relative;
    width: 225px;   /* 750 * 0.30 */
    height: 330px;  /* 1100 * 0.30 */
    flex: 0 0 auto;
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 4px 18px rgba(0,0,0,0.6);
}
/* ART/TEXT split divider — HOVER-ONLY so the preview reads as the true card.
   Hidden by default; fades in when the admin hovers the card preview (or while
   actively dragging via the .ace-splitting flag JS sets on pointerdown). The
   handle keeps a generous invisible hit-area (its 18px height, set inline) so
   it stays easy to grab, and pointer-events stay on so it's always draggable. */
.ace-split-divider,
.ace-split-label,
.ace-split-clear {
    opacity: 0;
    transition: opacity 0.15s ease;
}
.ace-card-render:hover .ace-split-divider,
.ace-card-render:hover .ace-split-label,
.ace-card-render:hover .ace-split-clear,
.ace-card-render.ace-splitting .ace-split-divider,
.ace-card-render.ace-splitting .ace-split-label,
.ace-card-render.ace-splitting .ace-split-clear {
    opacity: 1;
}
/* FRAME PICKER — per-theme frame-style / corner-motif override, mounted under
   the live preview render. Compact rows of pills (styled inline in JS to match
   the view-as pills); this just caps the box to the render width so it never
   widens the card pane and squeezes the form. */
.ace-frame-picker {
    width: 225px;
    max-width: 225px;
    margin: 5px 0 2px;
    padding: 3px 0;
    flex: 0 0 auto;
}
/* Wikimedia Commons art picker (in the editor's art section). */
.ace-wiki-panel {
    margin-top: 8px;
    padding: 8px;
    border: 1px solid rgba(201,168,76,0.4);
    border-radius: 8px;
    background: rgba(0,0,0,0.25);
}
.ace-wiki-search { display: flex; gap: 6px; align-items: center; }
.ace-wiki-search input {
    flex: 1;
    font-size: 12px;
    padding: 4px 8px;
    background: #0c0c0c;
    border: 1px solid #333;
    border-radius: 5px;
    color: #fff;
}
.ace-wiki-results {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 6px;
    max-height: 320px;
    overflow-y: auto;
}
.ace-wiki-tile {
    position: relative;
    padding: 0;
    border: 2px solid #444;
    border-radius: 6px;
    overflow: hidden;
    background: #111;
    cursor: pointer;
    aspect-ratio: 1 / 1;
    transition: border-color 0.12s ease, transform 0.12s ease;
}
.ace-wiki-tile:hover { transform: translateY(-1px); border-color: #c9a84c; }
.ace-wiki-tile.is-safe { border-color: #4c9a5a; }
.ace-wiki-tile.is-safe:hover { border-color: #7ddf8e; }
.ace-wiki-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ace-wiki-lic {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    font: 9px/1.3 ui-monospace, monospace;
    color: #fff;
    background: rgba(0,0,0,0.78);
    padding: 2px 4px;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* ✨ IMAGE EFFECTS panel — art-transform buttons + undo stack in the editor. */
.ace-fx-panel {
    margin-top: 8px;
    padding: 8px;
    border: 1px solid rgba(201,168,76,0.4);
    border-radius: 8px;
    background: rgba(0,0,0,0.25);
}
.ace-fx-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    font-size: 12px;
    font-weight: 600;
    margin-bottom: 6px;
}
.ace-fx-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 5px;
}
.ace-fx-btn {
    font-size: 11px;
    line-height: 1.3;
    padding: 5px 6px;
    border: 1px solid #4a4433;
    border-radius: 6px;
    background: rgba(30, 24, 14, 0.55);
    color: #eadfc4;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: border-color 0.12s ease, transform 0.12s ease, background 0.12s ease;
}
.ace-fx-btn:hover:not(:disabled) {
    border-color: #d4af37;
    background: rgba(201,168,76,0.16);
    transform: translateY(-1px);
}
.ace-fx-btn:disabled { opacity: 0.5; cursor: default; }
.ace-fx-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 7px;
    padding-top: 7px;
    border-top: 1px solid rgba(255,255,255,0.1);
}
.ace-fx-actions button { font-size: 12px; padding: 3px 10px; }
.ace-fx-revert { border-color: #a76 !important; color: #e6b39a !important; }
#ace-fx-status { flex: 1 1 100%; }
/* Rules-text editor sits DIRECTLY UNDER the card preview (same left column). */
.ace-rules-under {
    width: 260px;
    max-width: 100%;
    margin-top: 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ace-rules-under > label { display: block; font-size: 12px; }
.ace-rules-under textarea {
    width: 100%;
    box-sizing: border-box;
    resize: vertical;
    /* Match the dark field styling of the other dialog inputs — this box
       moved OUT of .token-creator-body into the preview pane, so it lost the
       .token-creator-body input/textarea rule and fell back to browser white. */
    background: #0c0c0c;
    border: 1px solid #333;
    border-radius: 5px;
    color: #fff;
    font-size: 13px;
    padding: 6px 8px;
    font-family: inherit;
    min-height: 90px;
}
.ace-form-pane {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0 !important;
}
.ace-form-pane .ace-sub { color: #7c766a; font-weight: 400; }

/* ══════════════════════════════════════════════════════════════════════════
   CARD DESIGNER tab (Task #49) — a per-theme "look & feel" template editor
   living as a tab in the admin card editor's form pane. Dark admin styling to
   match the rest of the .ace-* dialog.
   ══════════════════════════════════════════════════════════════════════════ */
.ace-tabbar {
    display: flex;
    gap: 4px;
    margin: 0 0 8px;
    border-bottom: 1px solid rgba(201,168,76,0.30);
}
.ace-tab {
    appearance: none;
    background: transparent;
    border: 1px solid transparent;
    border-bottom: none;
    border-radius: 8px 8px 0 0;
    color: #b9b0a0;
    font: 600 13px/1.4 'Nunito Sans', system-ui, sans-serif;
    padding: 6px 14px;
    cursor: pointer;
    margin-bottom: -1px;
}
.ace-tab:hover { color: #f0d07a; }
.ace-tab.on {
    color: #f5d98a;
    background: rgba(201,168,76,0.12);
    border-color: rgba(201,168,76,0.40);
    border-bottom: 1px solid #191612;
}
.ace-tabpane[hidden] { display: none; }

.ace-designer { display: flex; flex-direction: column; gap: 10px; }
.ace-designer-theme {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 12px;
    color: #d8cfbc;
}
.ace-designer-theme select {
    background: #12100d;
    color: #f0e6cf;
    border: 1px solid rgba(201,168,76,0.45);
    border-radius: 6px;
    padding: 3px 8px;
    font-size: 12px;
}
.ace-designer-note {
    font-size: 11px;
    color: #8f8778;
    line-height: 1.5;
    margin: -2px 0 2px;
}
.ace-dsg-group {
    border: 1px solid rgba(255,255,255,0.10);
    border-radius: 8px;
    padding: 8px 10px 10px;
    background: rgba(255,255,255,0.02);
}
.ace-dsg-group > h4 {
    margin: 0 0 6px;
    font: 700 11px/1.4 ui-monospace, monospace;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #ffe08a;
    opacity: 0.9;
}
/* Collapsible sections: clickable header + caret; collapsed hides the body. */
.ace-dsg-group > h4.ace-dsg-h {
    cursor: pointer;
    margin: 0;
    user-select: none;
    display: flex;
    align-items: center;
    gap: 6px;
}
.ace-dsg-group > h4.ace-dsg-h:hover { color: #fff0b8; }
.ace-dsg-group .ace-dsg-caret { display: inline-block; width: 12px; opacity: 0.8; }
.ace-dsg-group .ace-dsg-body { margin-top: 6px; }
.ace-dsg-group.collapsed .ace-dsg-body { display: none; }
.ace-dsg-group.collapsed > h4.ace-dsg-h { margin: 0; }

/* Prev / Next preview nav. */
.ace-dsg-nav {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 2px 0 8px;
}
.ace-dsg-nav .ace-dsg-navlabel {
    flex: 1;
    min-width: 0;
    font-size: 11px;
    color: #cfc6b4;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-align: center;
}
.ace-dsg-nav button { font-size: 11px; padding: 2px 10px; }

/* Generate-from-colour block. */
.ace-dsg-gen {
    border: 1px dashed rgba(201,168,76,0.30);
    border-radius: 6px;
    padding: 6px 8px;
    margin-top: 6px;
    background: rgba(255,255,255,0.02);
}

/* AI image key rows. */
.ace-dsg-keyrow {
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 6px;
    padding: 6px 8px;
    margin: 4px 0;
    background: rgba(255,255,255,0.02);
}
.ace-dsg-keyhdr { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #d8cfbc; }
.ace-dsg-keyhdr .ace-dsg-keystatus { font-size: 13px; }
.ace-dsg-keyedit { display: flex; gap: 6px; margin-top: 5px; }
.ace-dsg-keyedit .dsg-key-input {
    flex: 1; min-width: 0;
    background: #12100d; color: #f0e6cf;
    border: 1px solid rgba(201,168,76,0.35);
    border-radius: 6px; padding: 3px 7px; font-size: 12px;
}
.ace-dsg-keyedit button { font-size: 11px; padding: 2px 10px; }
.ace-dsg-row {
    display: grid;
    grid-template-columns: 96px 1fr 46px;
    align-items: center;
    gap: 8px;
    margin: 4px 0;
    font-size: 12px;
    color: #cfc6b4;
}
.ace-dsg-row > label { color: #cfc6b4; font-size: 12px; margin: 0; }
.ace-dsg-row input[type="range"] { width: 100%; }
.ace-dsg-row .ace-dsg-val {
    font: 600 11px/1.4 ui-monospace, monospace;
    color: #f0d07a;
    text-align: right;
}
.ace-dsg-row.ace-dsg-wide { grid-template-columns: 96px 1fr; }
.ace-dsg-row input[type="text"] {
    background: #12100d;
    color: #f0e6cf;
    border: 1px solid rgba(201,168,76,0.35);
    border-radius: 6px;
    padding: 3px 7px;
    font-size: 12px;
    width: 100%;
    box-sizing: border-box;
}
.ace-dsg-color {
    display: flex;
    align-items: center;
    gap: 6px;
}
.ace-dsg-color input[type="color"] {
    width: 30px; height: 24px;
    padding: 0; border: 1px solid rgba(201,168,76,0.4);
    border-radius: 5px; background: #12100d; cursor: pointer;
}
.ace-dsg-color .ace-dsg-clear {
    font-size: 10px; padding: 1px 6px; line-height: 1.5;
}
.ace-dsg-color .ace-dsg-swatch-off { font-size: 11px; color: #8f8778; }
.ace-dsg-toggle { display: flex; align-items: center; gap: 8px; }
.ace-dsg-select {
    background: #12100d;
    color: #f0e6cf;
    border: 1px solid rgba(201,168,76,0.40);
    border-radius: 6px;
    padding: 3px 8px;
    font-size: 12px;
    width: 100%;
    box-sizing: border-box;
}
.ace-dsg-typetag {
    border: 1px dashed rgba(201,168,76,0.30);
    border-radius: 6px;
    padding: 6px 8px;
    margin-top: 6px;
    background: rgba(255,255,255,0.02);
}
.ace-dsg-actions {
    display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
    margin-top: 4px; padding-top: 8px;
    border-top: 1px solid rgba(255,255,255,0.10);
}
.ace-dsg-status { font-size: 12px; color: #9a9;  }
/* Wider variant: room for the docked shorthand-legend column. Below 1100px
   the legend hides (the ❔ Shorthands button remains as the fallback) and
   the panel narrows back to the two-pane width. */
.token-creator-panel.ace-panel-xwide {
    max-width: 1010px;
    width: min(1010px, 96vw);
}
/* Docked shorthand legend (third column, right of the fields) — the same
   rows the ❔ floating panel shows, always visible while editing rules
   text; click a row to insert its shorthand at the cursor. */
.ace-legend-pane {
    flex: 0 0 220px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    border-left: 1px solid rgba(255,255,255,0.12);
    padding-left: 10px;
}
.ace-legend-pane .ace-legend-head { font-weight: 700; font-size: 12px; margin-bottom: 4px; opacity: .85; }
.ace-legend-pane .ace-legend-body { overflow-y: auto; min-height: 0; }
.ace-legend-pane .shh-head { font-weight: 700; margin: 8px 0 3px; opacity: .7; font-size: 10.5px;
                             text-transform: uppercase; letter-spacing: .06em; }
.ace-legend-pane .shh-row { display: flex; align-items: center; gap: 6px; padding: 2px 2px;
                            border-bottom: 1px solid rgba(255,255,255,.06); cursor: pointer; border-radius: 4px; }
.ace-legend-pane .shh-row:hover { background: rgba(201,168,76,0.12); }
.ace-legend-pane .shh-code { flex: 0 0 76px; color: #f0d07a; font-size: 11px; word-break: break-all; }
.ace-legend-pane .shh-out { flex: 1 1 auto; font-size: 11.5px; line-height: 1.45; }
.ace-legend-pane .shh-out img.card-graphics-img { height: 15px; width: auto; vertical-align: middle; }
.ace-legend-pane .shh-out .rules-text-icon { font-size: 10px; }
.ace-legend-pane .shh-out .cost-colon { font-size: 11px; }
.ace-legend-pane .shh-out .humility-box .humility-text { font-size: 9px; }
@media (max-width: 1100px) {
    .ace-legend-pane { display: none; }
    .token-creator-panel.ace-panel-xwide { max-width: 760px; width: min(760px, 94vw); }
}
/* Narrow screens: stack the render above the form (keep the 0.30 render box
   so the fixed --ch-scale isn't clipped). */
@media (max-width: 640px) {
    .ace-two-pane { flex-direction: column; align-items: center; }
    /* Stacked layout: don't pin the card (it would overlap the form below). */
    .ace-card-pane { position: static; }
}
/* ── Card-specific dialogs: thumbnail beside the text ─────────────────────
   Used by _uiChoose (Cost Zone or Play?), promptXAmount, promptChoice. */
.dlg-flex {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 16px 20px 4px;
}
.dlg-thumb-slot { flex: 0 0 auto; }
.dlg-card-panel .dlg-flex .token-creator-body,
.dlg-card-panel .dlg-flex .confirm-body {
    padding: 0 !important;
    align-self: center;
}
.dlg-card-thumb {
    position: relative;
    flex: 0 0 auto;
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0 4px 16px rgba(0,0,0,0.55);
    background: #0d0b08;
}
/* Narrow screens: stack the thumbnail above the text. */
@media (max-width: 560px) {
    .dlg-flex { flex-direction: column; align-items: center; text-align: center; }
    .dlg-flex .token-creator-body { width: 100%; }
}

/* ─── Response-window fast-card THUMBNAILS (priority window play buttons) ───── */
/* Each playable fast card is shown as a mini card thumb with a cost badge; hover
   pops the full pinned preview, click plays it. Replaces the old text buttons. */
.stack-fast-thumb {
    position: relative;
    display: inline-block;
    cursor: pointer;
    border-radius: 10px;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
    line-height: 0;
}
.stack-fast-thumb:hover { transform: translateY(-2px); box-shadow: 0 4px 14px rgba(120,180,240,0.4); }
.stack-fast-thumb .stack-thumb-fill { display: inline-block; line-height: 0; }
.stack-fast-thumb.is-disabled { cursor: not-allowed; opacity: 0.45; filter: grayscale(0.45); }
.stack-fast-thumb.is-disabled:hover { transform: none; box-shadow: none; }
.stack-fast-cost {
    position: absolute;
    top: 3px;
    left: 3px;
    z-index: 2;
    background: linear-gradient(180deg, #bfe3ff, #5a97d6);
    color: #0b1626;
    font-weight: 800;
    font-size: 11px;
    line-height: 1;
    padding: 2px 5px;
    border-radius: 6px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.5);
    pointer-events: none;
}
/* promptPickCard rows: mini-thumb + label */
.pick-card-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    /* Long search/tutor results (e.g. "Focus on Christ" revealing many cards)
       must stay on-screen and scrollable instead of running off the bottom. */
    max-height: 62vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 4px;
}
.pick-card {
    display: flex !important;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left !important;
    margin: 0 !important;
}
.pick-card .dlg-card-thumb { box-shadow: 0 2px 8px rgba(0,0,0,0.5); flex: 0 0 auto; }

/* ── Admin game replayer control bar ─────────────────────────────────────── */
#replay-bar {
    position: fixed; left: 50%; bottom: 14px; transform: translateX(-50%);
    z-index: 12000; display: flex; align-items: center; gap: 8px;
    padding: 8px 12px;
    /* STABLE width so the bar never resizes/shifts as the step label changes. */
    width: min(1180px, 96vw); box-sizing: border-box;
    background: rgba(13,11,8,0.96); border: 1px solid rgba(201,168,76,0.5);
    border-radius: 12px; box-shadow: 0 6px 28px rgba(0,0,0,0.7);
    font-family: system-ui, sans-serif;
}
#replay-bar button, #replay-bar select {
    background: #1d180f; color: #e9dcc0; border: 1px solid rgba(201,168,76,0.4);
    border-radius: 8px; padding: 6px 10px; cursor: pointer; font-size: 14px;
}
#replay-bar button:hover { border-color: #e0b84c; background: #241d10; }
#replay-bar button[data-a="exit"] { border-color: #c0685c; color: #f0b0a0; }
#replay-bar input[data-a="slider"] { flex: 1 1 auto; min-width: 80px; accent-color: #e0b84c; }
/* Clips (highlight reel) picker + the hot-frame glow when a key moment is on screen. */
#replay-bar select[data-a="clips"] { border-color: #d1483a; color: #f4b8a8; background: #241010; font-weight: 600; }
#replay-bar select[data-a="clips"]:hover { border-color: #f47a56; }
#replay-bar.rb-hot { box-shadow: 0 0 0 2px rgba(212,72,58,.7), 0 6px 24px rgba(212,72,58,.4); }
#replay-bar.rb-hot span[data-a="lbl"] { color: #f9c; text-shadow: 0 0 10px rgba(212,72,58,.7); }
/* STEP-THROUGH clip: pulse the Next button so the viewer knows to click toward
   the key moment. Cleared once they land on it (rb-stepping removed). */
#replay-bar.rb-stepping button[data-a="next"] {
    background: #2a1a0a; border-color: #d8a63e; color: #ffd98a;
    animation: rbStepPulse 1.15s ease-in-out infinite; }
@keyframes rbStepPulse {
    0%,100% { box-shadow: 0 0 0 0 rgba(216,166,62,.55); }
    50%     { box-shadow: 0 0 0 5px rgba(216,166,62,0); } }
@media (prefers-reduced-motion: reduce) { #replay-bar.rb-stepping button[data-a="next"] { animation: none; } }
/* Stepped outside the highlighted clip range — dim the label so it's clear you
   left the reel. */
#replay-bar.rb-outside-clip span[data-a="lbl"] { color: #98a2b3; }

/* ─── Replay annotations (arrows + notes for tutorials) ────────────────────
 * A layer positioned exactly over #board (JS keeps it in sync). Pointer events
 * are OFF except while authoring, so it never blocks playback. Annotations show
 * only on their own frame — they pop in/out as you step. */
#replay-anno-layer { position: fixed; z-index: 1400; pointer-events: none; overflow: visible; }
#replay-anno-layer .anno-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
#replay-anno-layer .anno-arrow { stroke: #ffd24a; stroke-width: 4; stroke-linecap: round; filter: drop-shadow(0 1px 3px rgba(0,0,0,.6)); }
#replay-anno-layer .anno-arrow.anno-ghost { opacity: .6; stroke-dasharray: 6 5; }
#replay-anno-layer .anno-circle { fill: none; stroke: #ffd24a; stroke-width: 4; filter: drop-shadow(0 1px 3px rgba(0,0,0,.6)); }
#replay-anno-layer .anno-circle.anno-ghost { opacity: .6; stroke-dasharray: 6 5; }
#replay-anno-layer #anno-arrow-head path { fill: #ffd24a; }
#replay-anno-layer .anno-notes { position: absolute; inset: 0; }
#replay-anno-layer .anno-note {
    position: absolute; transform: translate(-6px, -50%); max-width: 260px;
    background: rgba(20,18,10,.94); color: #ffe9a8; border: 1.5px solid #ffd24a;
    border-radius: 9px; padding: 5px 9px; font-size: 13px; font-weight: 600; line-height: 1.3;
    box-shadow: 0 4px 16px rgba(0,0,0,.5); white-space: pre-wrap; }
#replay-anno-layer .anno-note-arrow { transform: translate(-50%, -130%); font-size: 12px; }
#replay-anno-layer.anno-authoring { pointer-events: auto; cursor: crosshair; outline: 2px dashed rgba(255,210,74,.4); outline-offset: -2px; }
#replay-anno-layer.anno-authoring .anno-note { cursor: pointer; pointer-events: auto; }
#replay-anno-layer.anno-authoring .anno-note:hover { border-color: #ff6a6a; color: #ffb3b3; }
#replay-bar button[data-a="anno"].anno-on,
#replay-bar button[data-a="anno-vis"].anno-on { background: rgba(255,210,74,.28); border-color: #ffd24a; color: #ffe9a8; }
#replay-bar button.rb-hidden { display: none; }

#replay-anno-palette {
    /* Dock at the TOP (below the phase bar) with a z-index above the replay
       caption/bar so it's never hidden behind the status pill; draggable via JS. */
    position: fixed; z-index: 12150; left: 50%; top: 118px; bottom: auto; transform: translateX(-50%);
    display: flex; gap: 7px; align-items: center; flex-wrap: wrap; justify-content: center;
    background: rgba(16,14,8,.96); border: 1.5px solid #ffd24a; border-radius: 12px;
    padding: 7px 11px; box-shadow: 0 8px 30px rgba(0,0,0,.55); cursor: grab; user-select: none; }
#replay-anno-palette.dragging { cursor: grabbing; }
#replay-anno-palette.hidden { display: none; }
#replay-anno-palette .ap-hint { color: #ffe9a8; font-size: 12px; margin-right: 3px; }
#replay-anno-palette button {
    background: #2a2415; color: #ffe9a8; border: 1px solid #6b5a2a; border-radius: 8px;
    padding: 5px 10px; font-size: 13px; font-weight: 700; cursor: pointer; }
#replay-anno-palette button:hover { border-color: #ffd24a; }
#replay-anno-palette button[data-tool].sel { background: #ffd24a; color: #1a1508; border-color: #ffd24a; }

/* Annotation compose dialog (replaces window.prompt) — text + how long to show. */
.anno-dialog-back { position: fixed; inset: 0; z-index: 2147483000; background: rgba(0,0,0,.5);
    display: flex; align-items: center; justify-content: center; }
.anno-dialog { width: min(420px, 92vw); background: #16140c; color: #ffe9a8;
    border: 1.5px solid #ffd24a; border-radius: 14px; padding: 16px 16px 14px;
    box-shadow: 0 14px 50px rgba(0,0,0,.6); font: 14px/1.4 system-ui, sans-serif; }
.anno-dialog .ad-title { font-size: 16px; font-weight: 800; margin-bottom: 9px; }
.anno-dialog .ad-text { width: 100%; box-sizing: border-box; resize: vertical; min-height: 44px;
    background: #221d10; color: #fff; border: 1px solid #6b5a2a; border-radius: 8px; padding: 8px 10px;
    font: 14px/1.4 system-ui, sans-serif; }
.anno-dialog .ad-text:focus { outline: 2px solid #ffd24a; outline-offset: 1px; }
.anno-dialog .ad-row { display: flex; align-items: center; gap: 7px; margin: 11px 0 4px; flex-wrap: wrap; }
.anno-dialog .ad-lbl { opacity: .85; }
.anno-dialog .ad-mode, .anno-dialog .ad-n { background: #221d10; color: #fff; border: 1px solid #6b5a2a;
    border-radius: 7px; padding: 5px 7px; font: 13px system-ui, sans-serif; }
.anno-dialog .ad-n { width: 62px; }
.anno-dialog .ad-unit { opacity: .8; font-size: 13px; }
.anno-dialog .ad-btns { display: flex; justify-content: flex-end; gap: 8px; margin-top: 13px; }
.anno-dialog .ad-btns button { border-radius: 8px; padding: 7px 14px; font-weight: 700; cursor: pointer;
    font-size: 14px; border: 1px solid #6b5a2a; background: #2a2415; color: #ffe9a8; }
.anno-dialog .ad-btns .ad-ok { background: #ffd24a; color: #1a1508; border-color: #ffd24a; }
.anno-dialog .ad-btns button:hover { filter: brightness(1.08); }

/* ─── Sides are ALWAYS top/bottom ──────────────────────────────────────────
 * A 1v1 on a wide screen would otherwise use the side-split (left/right) layout.
 * body.sides-stacked (set by GameUI for any duel) overrides that into a vertical
 * stack so "evil on top" means TOP: evil (foe) band on top by default, and
 * body.sides-flip puts evil on the BOTTOM. Applies at all widths. */
body.sides-stacked.placement-side-split #board {
    grid-template-columns: 1fr !important;
    /* The LOCAL player (always the bottom band, row 4) gets the LARGER share so
       their own zones + hand have room; the opponent (row 3) is compact — their
       hand is only a small cardback strip, so they need far less. */
    grid-template-rows: auto auto minmax(0, 0.72fr) minmax(0, 1.5fr) !important;
    grid-template-areas: "shared" "phase" "foe" "me" !important;   /* evil on top */
}
body.sides-stacked.placement-side-split.sides-flip #board {
    grid-template-areas: "shared" "phase" "me" "foe" !important;   /* evil on bottom */
}
/* CRITICAL: name→band assignments for the stacked layout. The side-by-side
 * (min-width:1000px) block also assigns these, but BELOW 1000px only the stacked
 * TEMPLATE applied — the bands had no grid-area, so they auto-placed in DOM order
 * and the evil seat stayed pinned to the TOP even for an evil viewer (its own
 * hand pushed off-screen). Assign them at ALL widths so the flip actually lands
 * each band in its named row. `me` = the local player, `foe` = the opponent —
 * the sides-flip template swaps which row (top/bottom) each occupies, and the
 * local player is ALWAYS the bottom band. */
body.sides-stacked #shared-zones          { grid-area: shared !important; }
body.sides-stacked #phase-bar             { grid-area: phase  !important; }
body.sides-stacked .player-area.righteous { grid-area: me  !important; }
body.sides-stacked .player-area.evil      { grid-area: foe !important; }
/* RESPONSIVE PRIORITY: even tighter for the local player when space is scarce. */
@media (max-width: 999px) {
    body.sides-stacked.placement-side-split #board {
        grid-template-rows: auto auto minmax(0, 0.62fr) minmax(0, 1.6fr) !important;
    }
}
/* ── FACING-TABLE layout: opponent's hand at THEIR edge (the top), kept small ──
 * Players sit across a table: the LOCAL player's hand is at their bottom edge
 * (normal order), and the OPPONENT (top band) shows their hand at the very TOP,
 * always compact — an opponent's hand is face-down cardbacks, so it never needs
 * to be big. The space freed below their hand fills with what actually matters:
 * their play area (playmat) + tapped/untapped Cost Zone. */
body.sides-stacked .player-area:not(.player-area-local) {
    display: flex !important;
    flex-direction: column !important;
}
body.sides-stacked .player-area:not(.player-area-local) > .player-stats { order: 1 !important; flex: 0 0 auto !important; }
body.sides-stacked .player-area:not(.player-area-local) > .zone-row.hand-row {
    order: 0 !important;              /* cards at the VERY TOP, above the stat bar */
    /* A THIN clipping window: only the TOP SLIVER of each cardback peeks from the
       top edge (MTG-Arena style) — the rest is clipped, so the opponent's hand
       barely uses any vertical space while staying recognizable. */
    flex: 0 0 46px !important;
    height: 46px !important;
    max-height: 46px !important;
    min-height: 0 !important;
    overflow: hidden !important;
    padding: 0 6px !important;
    align-items: flex-start !important;
}
body.sides-stacked .player-area:not(.player-area-local) > .zone-active-strip,
body.sides-stacked .player-area:not(.player-area-local) > .zone-row.cost-zone-row,
body.sides-stacked .player-area:not(.player-area-local) > .playmat-grid {
    order: 2 !important;             /* play area + cost zone fill the rest */
}
/* The opponent's hand is just a "they hold N cards" indicator — hide the
   Hand/expand header so the thin strip is purely the peeking cardbacks. */
body.sides-stacked .player-area:not(.player-area-local) > .zone-row.hand-row > .hand-zone-header {
    display: none !important;
}
/* The opponent hand FANS (arc, tops toward the viewer) but is anchored at the
   TOP and clipped to the thin 46px strip, so only the fanned TOP EDGES peek
   through — like an opponent's held hand in MTG Arena. Cards small + tightly
   overlapped so a full hand fits without wasted space. The .hand-backs-fan arc
   (--fan-rot/--fan-dip/-tiltx from _applyFanArc) is KEPT — we no longer flatten
   it. Cards pivot from the top so the tops stay put as they fan. */
body.sides-stacked .player-area:not(.player-area-local) > .zone-row.hand-row [id$="-hand"] {
    --fan-card-scale: 0.62 !important;
    align-items: flex-start !important;
    align-self: flex-start !important;
    justify-content: safe center !important;
    height: auto !important;
    max-height: none !important;
    overflow: visible !important;
}
body.sides-stacked .player-area:not(.player-area-local) > .zone-row.hand-row .card-tile {
    transform-origin: top center !important;   /* fan pivots from the top → tops stay */
    margin: 0 -46px 0 0 !important;             /* tight overlap → no wasted width */
    align-self: flex-start !important;
}
/* COMPACT top bar for any stacked duel: the phase bar is a single short row
 * (advance + undo + Failed/Resisted + menu), never a tall wrapped stack that
 * steals vertical space from the play areas. Scrolls horizontally if narrow. */
body.sides-stacked #phase-bar {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center !important;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    max-height: 44px !important;
    padding: 2px 8px !important;
    gap: 6px !important;
}
body.sides-stacked #phase-bar::-webkit-scrollbar { display: none; }
body.sides-stacked #phase-bar > *  { flex-shrink: 0 !important; }
body.sides-stacked #phase-bar button,
body.sides-stacked #phase-bar .btn-primary,
body.sides-stacked #phase-bar .btn-icon,
body.sides-stacked #phase-bar .ch-round-btn {
    min-height: 30px !important;
    max-height: 34px !important;
    padding: 2px 8px !important;
    white-space: nowrap !important;
}
/* The horizontal resize handle is meaningless once stacked. */
body.sides-stacked #board-split-handle { display: none !important; }
/* FIXED-width label with ellipsis → the bar's total width can't change per step. */
#replay-bar span[data-a="lbl"] { color: #f0d07a; font-size: 12px; white-space: nowrap;
    flex: 0 0 250px; width: 250px; max-width: 250px; overflow: hidden; text-overflow: ellipsis; }
/* Resize grip — only shown when docked left/right (vertical column). Sits on the
   bar's INNER edge (toward the board) so dragging it widens/narrows the bar. */
#replay-bar .replay-grip { display: none; }
body.replay-dock-left  #replay-bar .replay-grip,
body.replay-dock-right #replay-bar .replay-grip {
    display: block; position: absolute; top: 0; bottom: 0; width: 10px;
    cursor: ew-resize; z-index: 2; background: transparent;
}
body.replay-dock-left  #replay-bar .replay-grip { right: -1px; }
body.replay-dock-right #replay-bar .replay-grip { left: -1px; }
body.replay-dock-left  #replay-bar .replay-grip:hover,
body.replay-dock-right #replay-bar .replay-grip:hover { background: rgba(224,184,76,0.35); }
#replay-bar { position: fixed; }  /* ensure abs grip anchors to the bar */
#replay-bar button.replay-last { font-weight: 700; letter-spacing: .02em; }
#replay-bar button[data-a="min"] { font-weight: 700; opacity: .75; }
#replay-bar button[data-a="min"]:hover { opacity: 1; }
/* Minimized: collapse to just the restore button so playback controls stop
   covering the board — keyboard (← → Space Home End Esc) still drives it. */
#replay-bar.mini { padding: 4px 6px; gap: 0; }
#replay-bar.mini > * { display: none !important; }

/* Progressive disclosure — as the bar narrows, drop controls in priority order
   so nothing overflows or truncates to an ugly "…". Core transport always stays. */
#replay-bar.rb-w-med    span[data-a="lbl"],
#replay-bar.rb-w-med    select[data-a="dock"]     { display: none; }
#replay-bar.rb-w-narrow select[data-a="view"],
#replay-bar.rb-w-narrow select[data-a="speed"],
#replay-bar.rb-w-narrow button[data-a="share"],
#replay-bar.rb-w-narrow button[data-a="playhere"] { display: none; }
#replay-bar.rb-w-mini   input[data-a="slider"],
#replay-bar.rb-w-mini   button[data-a="exit"]     { display: none; }

/* Compact mode (size button, state 1): show ONLY the step buttons + size button,
   and shrink the bar to fit them (overrides the fixed full width). */
#replay-bar.rb-compact { width: auto !important; }
#replay-bar.rb-compact > * { display: none !important; }
#replay-bar.rb-compact > button[data-a="first"],
#replay-bar.rb-compact > button[data-a="prev"],
#replay-bar.rb-compact > button[data-a="play"],
#replay-bar.rb-compact > button[data-a="next"],
#replay-bar.rb-compact > button[data-a="last"],
#replay-bar.rb-compact > button[data-a="min"],
#replay-bar.rb-compact > .replay-grip { display: inline-flex !important; }
#replay-bar.mini > [data-a="min"] { display: inline-block !important; }
/* ── Replay bar docking ──────────────────────────────────────────────────────
   The bar can dock to bottom (default), top, left or right, and the board is
   shrunk to reserve that edge so the bar never hovers over the playing field. */
body.replay-dock-top    #replay-bar { top: 8px; bottom: auto; }
body.replay-dock-bottom #replay-bar { bottom: 8px; top: auto; }
body.replay-dock-left  #replay-bar,
body.replay-dock-right #replay-bar {
    flex-direction: column; align-items: stretch;
    width: var(--replay-bar-w, 208px); max-width: 90vw; min-width: 0;
    /* TOP-anchored (NOT vertically centered) so the bar's top edge — and every
       button — stays put as the per-step label changes length. A centered bar
       shifted every button whenever the label wrapped to more/fewer lines. */
    top: 8px; bottom: auto; left: auto; right: auto; transform: none;
    max-height: 96vh; overflow: auto;
}
/* Let the bar shrink VERY small (drag the grip) without its button/select text
   forcing a minimum width — text clips cleanly instead of blocking the resize. */
body.replay-dock-left  #replay-bar button, body.replay-dock-left  #replay-bar select,
body.replay-dock-right #replay-bar button, body.replay-dock-right #replay-bar select {
    min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding-left: 4px; padding-right: 4px;
}
body.replay-dock-left  #replay-bar { left: 8px; }
body.replay-dock-right #replay-bar { right: 8px; }
/* FIXED-height label (up to 3 lines, clamped) so the controls BELOW it never
   move as the step text changes — keeps Step-forward under the cursor. */
body.replay-dock-left  #replay-bar span[data-a="lbl"],
body.replay-dock-right #replay-bar span[data-a="lbl"] {
    flex: 0 0 auto; width: auto; max-width: none; white-space: normal; text-align: center;
    height: 3.9em; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical;
    -webkit-line-clamp: 3; line-clamp: 3; line-height: 1.3; }
body.replay-dock-left  #replay-bar input[data-a="slider"],
body.replay-dock-right #replay-bar input[data-a="slider"] { flex: 0 0 auto; width: 100%; }
/* Reserve board space so the bar doesn't overlap the field. */
body.replay-dock-bottom #board { height: calc(100dvh - 74px) !important; }
body.replay-dock-top    #board { height: calc(100dvh - 74px) !important; margin-top: 66px !important; }
body.replay-dock-left   #board { width: calc(100vw - var(--replay-bar-w, 208px) - 24px) !important; margin-left: calc(var(--replay-bar-w, 208px) + 24px) !important; max-width: calc(100vw - var(--replay-bar-w, 208px) - 24px) !important; }
body.replay-dock-right  #board { width: calc(100vw - var(--replay-bar-w, 208px) - 24px) !important; max-width: calc(100vw - var(--replay-bar-w, 208px) - 24px) !important; }
/* Replay is VIEW-ONLY: hide every in-board action control so a watcher can't
   (and can't try to) interfere. Inspecting cards still works. To actually play,
   exit to Live — or share the position and open it in a fresh window. */
body.replay-active #action-bar,
body.replay-active .card-action-btn,
body.replay-active .play-btn, body.replay-active .yield-btn,
body.replay-active .resist-btn, body.replay-active .fail-btn,
body.replay-active .rotate-btn, body.replay-active .discard-btn {
    display: none !important;
}

/* ── Replay playback animations ───────────────────────────────────────────
   During a replay we repaint the whole board per step (no live FLIP), so we
   fake "a real player is playing" by animating the card that just changed:
   it pops into the Active zone, its targets pulse, and on resolve it flashes
   as it heads to Discard/Habitual. Classes are added by openGameReplayer's
   render() to the tile with the matching data-instance-id. */
/* Smoother card-play: the card glides down from above, gently overshoots and
   settles — reads as "placed", not a jarring pop (matters most in replays). */
@keyframes replayPlayIn {
    0%   { transform: scale(.74) translateY(-34px) rotate(-4deg); opacity: 0; filter: brightness(1.45); }
    45%  { transform: scale(1.055) translateY(3px)  rotate(1.2deg); opacity: 1; filter: brightness(1.22); }
    72%  { transform: scale(.99)  translateY(-1px)  rotate(-.4deg); }
    100% { transform: scale(1)     translateY(0)    rotate(0deg);   opacity: 1; filter: brightness(1); }
}
@keyframes replayGlow {
    0%,100% { box-shadow: 0 0 0 0 rgba(224,184,76,0); }
    45%     { box-shadow: 0 0 22px 5px rgba(224,184,76,.85), 0 0 40px 10px rgba(224,184,76,.35); }
}
@keyframes replayTargetPulse {
    0%,100% { box-shadow: inset 0 0 0 0 rgba(224,120,111,0); outline-color: rgba(224,120,111,0); }
    50%     { box-shadow: inset 0 0 26px 2px rgba(224,120,111,.5); outline-color: rgba(224,120,111,.95); }
}
@keyframes replayResolveFlash {
    0%   { filter: brightness(1); transform: scale(1); }
    40%  { filter: brightness(1.7) saturate(1.3); transform: scale(1.08); }
    100% { filter: brightness(1); transform: scale(1); }
}
.card-tile.replay-focus {
    /* Glow only — the card's MOVEMENT is handled by the FLIP animation (which
       owns the transform), so we must not also run a transform keyframe here. */
    animation: replayGlow 1.2s ease-in-out .1s;
    z-index: 40; position: relative;
}
.card-tile.replay-resolve { animation: replayResolveFlash .55s ease-in-out both; z-index: 40; position: relative; }
.player-area.replay-target, .card-tile.replay-target {
    animation: replayTargetPulse 1s ease-in-out .05s 2;
    outline: 2px solid rgba(224,120,111,.95); outline-offset: 1px; border-radius: 10px;
}
/* A floating caption above the board narrating the current replay step. */
#replay-caption {
    position: fixed; left: 50%; bottom: 74px; transform: translateX(-50%);
    z-index: 11999; max-width: min(560px, 92vw); pointer-events: none;
    padding: 8px 18px; border-radius: 999px;
    background: rgba(13,11,8,.94); border: 1px solid rgba(201,168,76,.55);
    color: #f4e2ab; font-family: system-ui, sans-serif; font-size: 13.5px; font-weight: 600;
    letter-spacing: .01em; line-height: 1.32; box-shadow: 0 4px 20px rgba(0,0,0,.6);
    opacity: 0; transition: opacity .25s ease;
    display: flex; flex-direction: column; align-items: center; gap: 8px;
}
#replay-caption.show { opacity: 1; }
/* When a card is named, the caption relaxes the pill into a rounded card and
   stacks a concise (clamped) line of text over a tidy centered row of thumbs. */
#replay-caption:has(.rc-thumbs) { border-radius: 15px; padding: 11px 16px 12px; gap: 10px; }
#replay-caption .rc-text {
    text-align: center; max-width: 100%;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
/* Bulleted caption — a "lead: a; b; c" label reads as a heading + quick bullets. */
#replay-caption .rc-head { display: block; text-align: center; font-weight: 700; margin-bottom: 3px; }
#replay-caption .rc-bullets { margin: 0; padding: 0 0 0 2px; list-style: none; text-align: left;
    max-width: 100%; font-weight: 500; }
#replay-caption .rc-bullets li { position: relative; padding-left: 15px; margin: 2px 0; line-height: 1.28; }
#replay-caption .rc-bullets li::before { content: '▪'; position: absolute; left: 2px; color: #d8a63e; }
#replay-caption .rc-thumbs { display: flex; gap: 10px; pointer-events: auto; justify-content: center; align-items: flex-end; }
#replay-caption .rc-more {
    align-self: center; font-size: 13px; font-weight: 700; color: #d8c58a;
    padding: 4px 8px; border: 1px solid rgba(201,168,76,.4); border-radius: 8px;
    background: rgba(255,255,255,.04);
}
#replay-caption .rc-thumb {
    width: 82px; height: 120px; border: 1.5px solid rgba(201,168,76,.55);
    border-radius: 7px; background: #0a0806; overflow: hidden; pointer-events: auto;
    transition: transform .16s ease, box-shadow .16s ease; transform-origin: bottom center;
    cursor: zoom-in;
}
#replay-caption .rc-thumb:hover {
    transform: scale(2.9); z-index: 12010; position: relative;
    box-shadow: 0 12px 40px rgba(0,0,0,.85); border-color: rgba(240,205,90,.9);
}
/* Graceful thumbnail: a dark placeholder covers the iframe by DEFAULT (so the
   card view's white loading flash is never seen), then:
     • .rc-thumb-ok      → card confirmed loaded: hide placeholder, show card.
     • .rc-thumb-failed  → error/blank/timeout: keep placeholder, show "couldn't
                           load" message. */
#replay-caption .rc-thumb-wrap { position: relative; display: inline-flex; }
#replay-caption .rc-thumb-fallback {
    display: flex; position: absolute; inset: 0; z-index: 2;
    width: 82px; height: 120px; border-radius: 7px;
    border: 1.5px solid rgba(201,168,76,.45);
    background: linear-gradient(160deg, #1a140b 0%, #0a0806 100%);
    flex-direction: column; align-items: center; justify-content: center; gap: 5px;
    text-align: center; padding: 6px; box-sizing: border-box;
}
#replay-caption .rc-thumb-wrap.rc-thumb-ok .rc-thumb-fallback { display: none; }
#replay-caption .rc-thumb-wrap.rc-thumb-failed .rc-thumb-fallback {
    border-style: dashed; border-color: rgba(210,120,90,.5);
}
#replay-caption .rc-fb-icon { font-size: 26px; opacity: .55; line-height: 1; }
#replay-caption .rc-thumb-wrap.rc-thumb-failed .rc-fb-icon { opacity: .8; }
/* The "couldn't load" text only shows on genuine failure; while loading the
   placeholder is just the dimmed card icon (reads as intentional, not broken). */
#replay-caption .rc-fb-text {
    display: none;
    font-size: 9px; font-weight: 600; line-height: 1.25; letter-spacing: .02em;
    color: #d0a487; text-transform: uppercase;
}
#replay-caption .rc-thumb-wrap.rc-thumb-failed .rc-fb-text { display: block; }
/* Soft pulse on the loading icon so it reads as "working", not frozen. */
@media (prefers-reduced-motion: no-preference) {
    #replay-caption .rc-thumb-wrap:not(.rc-thumb-ok):not(.rc-thumb-failed) .rc-fb-icon {
        animation: rc-fb-pulse 1.1s ease-in-out infinite;
    }
}
@keyframes rc-fb-pulse { 0%,100% { opacity: .35; } 50% { opacity: .7; } }
@media (prefers-reduced-motion: reduce) {
    .card-tile.replay-focus, .card-tile.replay-resolve,
    .player-area.replay-target, .card-tile.replay-target { animation: none; }
}
.pick-card .pick-card-label { flex: 1 1 auto; min-width: 0; }

/* ── Card-dialog buttons: themed to the game's gold aesthetic ─────────────
   Overrides the generic blue footer .btn-primary + grey ghost .btn-cancel
   for the card dialogs, using the theme's --col-accent so romanwar /
   plantlover / blockbuilding each get their own accent. */
.dlg-card-panel .token-creator-footer .btn-primary {
    background: linear-gradient(135deg, #a87b20, var(--col-accent, #c9a84c), #d4b060);
    color: #0a0600;
    border: none;
    border-radius: 8px;
    padding: 9px 18px;
    font-size: 12px;
    font-weight: 700;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.03em;
    box-shadow: 0 2px 10px rgba(201,168,76,0.35), inset 0 1px 0 rgba(255,255,255,0.2);
    transition: all 0.15s;
}
.dlg-card-panel .token-creator-footer .btn-primary:hover {
    box-shadow: 0 4px 16px rgba(201,168,76,0.5), inset 0 1px 0 rgba(255,255,255,0.25);
    transform: translateY(-1px);
}
.dlg-card-panel .token-creator-footer .btn-primary:active { transform: scale(0.98) translateY(0); }
.dlg-card-panel .token-creator-footer .btn-cancel {
    background: rgba(201,168,76,0.06);
    color: var(--col-accent, #d8bd72);
    border: 1px solid rgba(201,168,76,0.45);
    border-radius: 8px;
    padding: 9px 18px;
    font-size: 12px;
    font-weight: 600;
    font-family: 'Cinzel', serif;
    letter-spacing: 0.03em;
    cursor: pointer;
    transition: all 0.15s;
}
.dlg-card-panel .token-creator-footer .btn-cancel:hover {
    background: rgba(201,168,76,0.16);
    border-color: rgba(201,168,76,0.7);
    color: #f0e0a8;
}
/* _uiChoose choices live in the footer: full-width block buttons stacked
   vertically with identical left/right edges (consistent alignment). */
.dlg-card-panel .dlg-choice-stack {
    flex-direction: column;
    align-items: stretch;
    justify-content: stretch;
    gap: 8px;
}
.dlg-card-panel .dlg-choice-stack .btn-primary,
.dlg-card-panel .dlg-choice-stack .btn-cancel {
    width: 100%;
    text-align: center;
    white-space: normal;
    text-transform: none;   /* choice labels are sentences, not headings */
}

/* ── "Effects" strip: active until-end-of-turn cost effects ─────────────── */
.active-effects-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 6px auto;
    padding: 5px 8px;
    max-width: 100%;
    background: rgba(20,14,6,0.85);
    border: 1px solid rgba(201,168,76,0.4);
    border-radius: 9px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.4);
    font-family: 'Cinzel', serif;
}
.active-effects-strip .ae-head {
    font-size: 10px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--col-accent, #d8bd72);
    font-weight: 700;
    padding-right: 4px;
}
.active-effect {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 8px;
    background: rgba(201,168,76,0.08);
    border: 1px solid rgba(201,168,76,0.3);
    border-radius: 7px;
    font-size: 11px;
    color: #efe4c6;
}
.active-effect .ae-icon { font-size: 12px; }
.active-effect .ae-text b { color: #7bd88f; }
/* Evil taxes / cost increases read RED (pricier). */
.active-effect.ae-pricier { border-color: rgba(226,103,95,0.45); }
.active-effect.ae-pricier .ae-text b { color: #e2675f; }
.active-effect .ae-scope { opacity: 0.6; font-size: 10px; }
/* Flag badge — a small pill on a card showing its [Flag] markers (Speed /
   Weakness / CZDraw / New Creature). Top-left of the card, gold to match. */
.card-flag-badge {
    position: absolute; top: 4px; left: 4px; z-index: 6;
    background: rgba(20,22,30,0.9); color: #f4d27a;
    border: 1px solid #b9932f; border-radius: 9px;
    padding: 1px 6px; font: 700 9.5px/1.3 system-ui, sans-serif;
    max-width: 88%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    pointer-events: none; box-shadow: 0 1px 4px rgba(0,0,0,0.4);
}
/* Maturity Abilities ("Mature Together") read GOLD — team-wide ongoing perks. */
.active-effect.ae-ability { border-color: rgba(201,168,76,0.6); background: rgba(201,168,76,0.14); }
.active-effect.ae-ability .ae-icon { color: #f4d27a; }
.active-effect.ae-ability .ae-text b { color: #f4d27a; }
.active-effect .ae-ends {
    opacity: 0.7;
    font-size: 9.5px;
    font-style: italic;
    padding-left: 3px;
    border-left: 1px solid rgba(255,255,255,0.15);
}

/* Resolved-X hint: a small faded "(X-1)" annotation shown right after the
   number an X-cost card was resolved to, so the player still sees where X was. */
.x-orig {
    font-size: 0.62em;
    opacity: 0.5;
    vertical-align: super;
    margin-left: 1px;
    font-weight: 600;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

/* ── Modify-a-number picker ───────────────────────────────────────────── */
.mn-label { font-size: 12px; opacity: 0.8; margin-bottom: 6px; }
.mn-nums { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.mn-num { min-width: 34px; height: 30px; font-weight: 800; font-size: 15px; border-radius: 7px; }
.mn-dir { display: flex; gap: 8px; margin-bottom: 8px; }
.mn-dir .mn-sign { flex: 1 1 auto; }
.mn-mag { display: flex; align-items: center; gap: 8px; font-size: 12px; margin-bottom: 8px; }
.mn-mag .btn-cancel { width: 28px; height: 28px; padding: 0; border-radius: 6px; }
.mn-selected { background: linear-gradient(180deg,#f4e9c1,#d4af37) !important; color: #1a1208 !important; border-color: #d4af37 !important; }
.mn-result { font-size: 13px; margin-top: 4px; }
.mn-result b { color: #7bd88f; }

/* ── Redistribute-Humility dialog ─────────────────────────────────────── */
.redist-total { font-size: 13px; margin: 2px 0 10px; color: var(--col-text, #e8dcc0); }
.redist-total b, .redist-remaining b { color: var(--col-accent, #d8bd72); }
.redist-rows { display: flex; flex-direction: column; gap: 7px; }
.redist-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; padding: 4px 2px;
}
.redist-name { font-weight: 600; font-family: 'Cinzel', serif; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.redist-stepper { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.redist-stepper .btn-cancel {
    width: 30px; height: 30px; padding: 0; font-size: 18px; line-height: 1;
    border-radius: 7px; display: flex; align-items: center; justify-content: center;
}
.redist-input {
    width: 56px; text-align: center; font-size: 16px; font-weight: 700;
    padding: 5px 4px; border-radius: 7px;
    background: rgba(0,0,0,0.35); color: #f0d07a;
    border: 1px solid rgba(201,168,76,0.4);
    -moz-appearance: textfield;
}
.redist-input::-webkit-outer-spin-button,
.redist-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.redist-remaining {
    margin-top: 12px; padding-top: 9px; font-size: 13px; text-align: center;
    border-top: 1px solid rgba(255,255,255,0.07);
}
.redist-remaining.redist-ok  b { color: #7bd88f; }
.redist-remaining.redist-bad b { color: #e2675f; }
.token-creator-footer {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 10px 14px;
    border-top: 1px solid rgba(255,255,255,0.05);
}
.token-creator-footer .btn-cancel {
    background: transparent;
    color: #bbb;
    border: 1px solid #444;
    border-radius: 5px;
    padding: 6px 12px;
    cursor: pointer;
}
.token-creator-footer .btn-primary {
    background: #2563eb;
    color: #fff;
    border: 0;
    border-radius: 5px;
    padding: 6px 14px;
    font-weight: 600;
    cursor: pointer;
}

/* Face-up top-of-deck tile — shown next to the deck stat when
   player.topCardFaceUp is on. Small inline card with a subtle accent ring. */
.deck-face-up-host {
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
}
.deck-face-up-host:empty { display: none; }
.deck-face-up-tile {
    width: 72px;
    height: 105px;
    border-radius: 6px;
    overflow: hidden;
    box-shadow: 0 0 0 2px rgba(255,220,120,0.65), 0 4px 10px rgba(0,0,0,0.5);
    margin-left: 6px;
    cursor: default;
    position: relative;
}
.deck-face-up-tile::before {
    content: 'TOP';
    position: absolute;
    top: 2px; left: 2px;
    font-family: 'Cinzel', serif;
    font-size: 8px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: #3a2900;
    background: rgba(255,220,120,0.95);
    padding: 1px 4px;
    border-radius: 3px;
    z-index: 5;
    pointer-events: none;
}

/* Cost overlay pill on card tiles. Hidden by default (the full card already
   shows cost in its bottom-left badge); revealed inside the hand fan where
   overlap hides the original badge. */
.card-cost-overlay {
    position: absolute;
    top: 2px;
    left: 2px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    display: none;
    align-items: center;
    justify-content: center;
    font-family: 'Cinzel', serif;
    font-weight: 900;
    font-size: 11px;
    line-height: 1;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.7);
    background: #1e6b1e;
    border: 1px solid rgba(255,255,255,0.35);
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.5);
    z-index: 6;
    pointer-events: none;
}
/* Only render the cost overlay inside the hand fan (where overlap hides
   the printed cost). Other zones show the full card badge already. */
.hand-fan .card-tile .card-cost-overlay { display: inline-flex; }

/* Modified-cost chip: struck printed cost + net value (green cheaper /
   red pricier) — the compact twin of the full badge's 7→4 treatment. */
.card-cost-overlay.cost-modified { gap: 3px; }
.card-cost-overlay .cost-orig {
    opacity: 0.65;
    font-size: 9px;
    text-decoration: line-through;
}
.card-cost-overlay.cost-cheaper .cost-new { color: #8dff9d; }
.card-cost-overlay.cost-pricier .cost-new { color: #ffb0a8; }

/* Tint the overlay by card color so the color code is preserved. */
.card-cost-overlay[data-card-class="fire"]   { background: #a7271f; }
.card-cost-overlay[data-card-class="grass"]  { background: #1e6b1e; }
.card-cost-overlay[data-card-class="ice"]    { background: #2966a0; }
.card-cost-overlay[data-card-class="stone"]  { background: #5e5e5e; }
.card-cost-overlay[data-card-class="gold"]   { background: #a07c00; }

/* Undo button in action bar */
.btn-undo {
    background: rgba(0,0,0,0.5);
    color: rgba(230,200,140,0.9);
    border: 1px solid rgba(201,168,76,0.35);
    border-radius: 6px;
    padding: 5px 10px;
    font-family: 'Cinzel', serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.06em;
    cursor: pointer;
    margin-left: 6px;
}
.btn-undo:hover {
    background: rgba(201,168,76,0.18);
    border-color: rgba(201,168,76,0.7);
}

/* Zone badge: shows the card's current zone next to the name. */
.card-pin-zone-badge {
    flex: 0 0 auto;
    font-family: 'Cinzel', serif;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 3px 7px;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,0.15);
    background: rgba(0,0,0,0.4);
    color: rgba(230,220,200,0.85);
    white-space: nowrap;
}
.card-pin-zone-badge[data-zone-type="hand"]           { background: rgba(30,60,120,0.55); border-color: rgba(100,160,255,0.45); color: #b8d4ff; }
.card-pin-zone-badge[data-zone-type="field"]          { background: rgba(30,100,40,0.55); border-color: rgba(120,220,120,0.45); color: #bfeac0; }
.card-pin-zone-badge[data-zone-type="cost-available"] { background: rgba(100,80,20,0.55); border-color: rgba(220,180,60,0.45); color: #f5d77a; }
.card-pin-zone-badge[data-zone-type="cost-spent"]     { background: rgba(120,60,20,0.55); border-color: rgba(220,130,60,0.45); color: #f3b27a; }
.card-pin-zone-badge[data-zone-type="evil-habituals"],
.card-pin-zone-badge[data-zone-type="evil-field"]     { background: rgba(100,20,20,0.55); border-color: rgba(220,60,60,0.45); color: #f7b0b0; }
.card-pin-zone-badge[data-zone-type="discard"]        { background: rgba(60,60,60,0.55); border-color: rgba(150,150,150,0.4); color: #d6d6d6; }
.card-pin-zone-badge[data-zone-type="deck"]           { background: rgba(40,40,60,0.55); border-color: rgba(130,130,170,0.4); color: #c7c7e0; }
.card-pin-zone-badge[data-zone-type="active"]         { background: rgba(160,120,20,0.55); border-color: rgba(240,210,80,0.55); color: #ffe48a; }
.card-pin-zone-badge[data-zone-type="failed-pile"]    { background: rgba(100,20,20,0.55); border-color: rgba(220,60,60,0.45); color: #f7b0b0; }
.card-pin-zone-badge[data-zone-type="resisted-pile"]  { background: rgba(30,100,40,0.55); border-color: rgba(120,220,120,0.45); color: #bfeac0; }
.card-pin-zone-badge[data-zone-type="none"]           { background: rgba(60,60,60,0.35); border-color: rgba(150,150,150,0.25); color: rgba(200,200,200,0.6); font-style: italic; }

.card-pin-cost {
    width: 30px;
    height: 30px;
    background: #22a12a;
    border: 2px solid rgba(255,255,255,0.3);
    border-radius: 5px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 900;
    line-height: 1;
    color: #fff !important;
    text-shadow: 0 1px 3px rgba(0,0,0,0.6);
    flex-shrink: 0;
    box-shadow: 0 0 0 1px #5a5a5a, 0 2px 4px rgba(0,0,0,0.4);
}

.card-pin-close {
    background: none;
    border: 1px solid rgba(201,168,76,0.2);
    border-radius: 4px;
    color: rgba(201,168,76,0.5);
    font-size: 11px;
    width: 22px;
    height: 22px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 0.15s;
}
.card-pin-close:hover {
    background: rgba(201,168,76,0.12);
    border-color: rgba(201,168,76,0.5);
    color: rgba(201,168,76,1);
}

.card-pin-match-all {
    background: none;
    border: 1px solid rgba(201,168,76,0.2);
    border-radius: 4px;
    color: rgba(201,168,76,0.5);
    font-size: 13px;
    width: 22px;
    height: 22px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 0.15s;
}
.card-pin-match-all:hover {
    background: rgba(201,168,76,0.12);
    border-color: rgba(201,168,76,0.5);
    color: rgba(201,168,76,1);
}

/* Admin-only "Edit card" button — same footprint as match-all, greenish
   tint so it reads as an editorial/admin control distinct from view/close. */
.card-pin-edit {
    background: none;
    border: 1px solid rgba(120,200,140,0.35);
    border-radius: 4px;
    color: rgba(150,220,170,0.8);
    font-size: 13px;
    width: 22px;
    height: 22px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 0.15s;
}
.card-pin-edit:hover {
    background: rgba(90,200,120,0.16);
    border-color: rgba(120,220,150,0.7);
    color: #baf5cf;
}
.card-pin-panel.pin-tiny .card-pin-edit {
    width: 18px;
    height: 18px;
    font-size: 10px;
}

/* ── Panel background per card type ── */
.card-pin-panel[data-card-type="fire"]  { background: linear-gradient(180deg, #1e0a04 0%, #120402 100%); border-color: rgba(255,90,30,0.4); }
.card-pin-panel[data-card-type="grass"] { background: linear-gradient(180deg, #061408 0%, #030c04 100%); border-color: rgba(80,200,80,0.4); }
.card-pin-panel[data-card-type="ice"]   { background: linear-gradient(180deg, #020c1e 0%, #010812 100%); border-color: rgba(80,140,255,0.4); }
.card-pin-panel[data-card-type="stone"] { background: linear-gradient(180deg, #111111 0%, #0a0a0a 100%); border-color: rgba(160,160,160,0.4); }
.card-pin-panel[data-card-type="gold"]  { background: linear-gradient(180deg, #1c1400 0%, #100c00 100%); border-color: rgba(255,190,50,0.4); }

/* ── Tiny mode: compact header when panel is very small (< 220px) ── */
.card-pin-panel.pin-tiny .card-pin-header {
    padding: 3px 6px;
    gap: 5px;
}
/* Tighten overlay in tiny mode so more art shows through */
.card-pin-panel.pin-tiny .card-pin-header::before {
    background: linear-gradient(90deg, rgba(0,0,0,0.70) 0%, rgba(0,0,0,0.42) 100%);
}
.card-pin-panel.pin-tiny .card-pin-name {
    font-size: 9px;
    letter-spacing: 0.06em;
}
.card-pin-panel.pin-tiny .card-pin-type-icon {
    width: 16px;
    height: 16px;
}
.card-pin-panel.pin-tiny .card-pin-cost {
    width: 22px;
    height: 22px;
    font-size: 11px;
}
.card-pin-panel.pin-tiny .card-pin-close,
.card-pin-panel.pin-tiny .card-pin-match-all {
    width: 18px;
    height: 18px;
    font-size: 10px;
    padding: 0;
}
/* Hide card-internal type header and name when panel is tiny — shown in panel header already */
.card-pin-panel.pin-tiny .pcc-header,
.card-pin-panel.pin-tiny .pcc-name,
.card-pin-panel.pin-tiny .pcc-divider {
    display: none;
}
/* Give rules text more room and tighten card padding in tiny mode */
.card-pin-panel.pin-tiny .pin-compact-card {
    padding: 6px 8px 8px;
    gap: 0;
}
.card-pin-panel.pin-tiny .pcc-rules {
    font-size: 11px;
    line-height: 1.5;
}

/* Contextual action bar at the bottom of a pinned card — e.g. Resist /
 * Fail / Skip for an evil-field temptation. Horizontal row of compact
 * buttons that wrap on narrow panels. */
.card-pin-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 8px 10px;
    border-top: 1px solid rgba(201,168,76,0.25);
    background: rgba(0,0,0,0.35);
    flex-shrink: 0;
}
.card-pin-action-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    flex: 1 1 auto;                 /* fill the bar so Resist/Fail read as a clear pair */
    min-width: 44%;
    padding: 10px 14px;
    font-size: 13px;
    font-weight: 700;
    font-family: 'Nunito Sans', system-ui, sans-serif;
    color: #f0e8d8;
    background: linear-gradient(180deg, rgba(201,168,76,0.22) 0%, rgba(201,168,76,0.08) 100%);
    border: 1px solid rgba(201,168,76,0.45);
    border-radius: 8px;
    cursor: pointer;
    letter-spacing: 0.02em;
    box-shadow: 0 1px 2px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.08);
    transition: background 0.12s ease, transform 0.08s ease, box-shadow 0.12s ease;
}
.card-pin-action-btn:hover:not(:disabled) {
    background: linear-gradient(180deg, rgba(201,168,76,0.4) 0%, rgba(201,168,76,0.18) 100%);
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.12);
}
.card-pin-action-btn:active:not(:disabled) { transform: translateY(0); box-shadow: 0 1px 2px rgba(0,0,0,0.35); }
.card-pin-action-btn:disabled { opacity: 0.45; cursor: not-allowed; }
/* RESIST — the good, defensive choice: emerald. */
.card-pin-action-btn.resist {
    color: #d8ffe4;
    background: linear-gradient(180deg, rgba(38,140,80,0.5) 0%, rgba(24,96,56,0.28) 100%);
    border-color: rgba(80,210,140,0.6);
    text-shadow: 0 1px 1px rgba(0,0,0,0.4);
}
.card-pin-action-btn.resist:hover:not(:disabled) {
    background: linear-gradient(180deg, rgba(46,170,96,0.65) 0%, rgba(30,120,70,0.35) 100%);
    box-shadow: 0 3px 10px rgba(30,160,90,0.35), inset 0 1px 0 rgba(255,255,255,0.14);
}
/* FAIL — giving in: danger red. */
.card-pin-action-btn.danger {
    color: #ffd2ce;
    background: linear-gradient(180deg, rgba(178,42,42,0.5) 0%, rgba(120,26,26,0.28) 100%);
    border-color: rgba(239,110,100,0.6);
    text-shadow: 0 1px 1px rgba(0,0,0,0.4);
}
.card-pin-action-btn.danger:hover:not(:disabled) {
    background: linear-gradient(180deg, rgba(200,57,43,0.65) 0%, rgba(150,30,30,0.35) 100%);
    box-shadow: 0 3px 10px rgba(190,50,40,0.35), inset 0 1px 0 rgba(255,255,255,0.12);
}
.card-pin-action-icon { font-size: 15px; line-height: 1; }

/* Duel response window — the enemy paused for a human resist (init.js). */
#duel-resp-banner {
    position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
    z-index: 4000; display: flex; align-items: center; gap: 12px;
    padding: 10px 14px; border-radius: 12px;
    background: linear-gradient(180deg, rgba(40,20,20,0.97), rgba(26,12,12,0.97));
    border: 1px solid rgba(239,110,100,0.55);
    box-shadow: 0 8px 26px rgba(0,0,0,0.5);
    color: #f6e8e6; font-family: 'Nunito Sans', system-ui, sans-serif; font-size: 14px;
    max-width: calc(100vw - 28px);
}
#duel-resp-banner .drb-dot {
    width: 9px; height: 9px; border-radius: 50%; background: #ef6a5e; flex: 0 0 auto;
    box-shadow: 0 0 0 0 rgba(239,106,94,0.6); animation: drbPulse 1.4s infinite;
}
#duel-resp-banner .drb-text b { color: #ffd2ce; }
#duel-resp-banner .drb-count {
    font-family: ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums;
    font-size: 13px; color: #ffb0a8; min-width: 34px; text-align: right;
}
#duel-resp-banner .drb-go {
    appearance: none; cursor: pointer; white-space: nowrap;
    padding: 6px 12px; border-radius: 8px; font-weight: 700; font-size: 13px;
    color: #f0e8d8; background: rgba(201,168,76,0.22);
    border: 1px solid rgba(201,168,76,0.5); font-family: inherit;
}
#duel-resp-banner .drb-go:hover { background: rgba(201,168,76,0.4); }
@keyframes drbPulse {
    0%   { box-shadow: 0 0 0 0 rgba(239,106,94,0.55); }
    70%  { box-shadow: 0 0 0 8px rgba(239,106,94,0); }
    100% { box-shadow: 0 0 0 0 rgba(239,106,94,0); }
}
@media (prefers-reduced-motion: reduce) {
    #duel-resp-banner .drb-dot { animation: none; }
}

/* ── "Created by" token provenance row ──────────────────────────────────── */
.card-pin-createdby {
    padding: 8px 10px;
    border-top: 1px solid rgba(201,168,76,0.25);
    background: rgba(0,0,0,0.35);
    flex-shrink: 0;
}
.card-pin-createdby-btn {
    display: flex;
    align-items: center;
    gap: 7px;
    width: 100%;
    padding: 7px 10px;
    font-size: 12px;
    font-weight: 600;
    font-family: 'Nunito Sans', system-ui, sans-serif;
    text-align: left;
    color: #f4ecda;
    background: linear-gradient(180deg, rgba(201,168,76,0.20) 0%, rgba(201,168,76,0.07) 100%);
    border: 1px solid rgba(201,168,76,0.42);
    border-radius: 7px;
    cursor: pointer;
    letter-spacing: 0.01em;
    transition: background 0.12s ease, transform 0.08s ease;
}
.card-pin-createdby-btn:hover {
    background: linear-gradient(180deg, rgba(201,168,76,0.36) 0%, rgba(201,168,76,0.15) 100%);
    transform: translateY(-1px);
}
.card-pin-createdby-btn:active { transform: translateY(0); }
.card-pin-createdby-btn .cb-label { flex: 1; min-width: 0; }
.card-pin-createdby-btn .cb-label b { color: #ffe6a3; font-weight: 800; }
.card-pin-createdby-btn .cb-spark { font-size: 14px; line-height: 1; }
.card-pin-createdby-btn .cb-caret {
    flex: 0 0 auto;
    font-size: 11px;
    opacity: 0.75;
    transition: transform 0.15s ease;
}
.card-pin-createdby-btn.open .cb-caret { transform: rotate(180deg); }

.card-pin-createdby-detail {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 10px 4px 4px;
    animation: cbFadeIn 0.18s ease;
}
@keyframes cbFadeIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
.cb-mini-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}
/* ch-card-root is 750×1100 scaled by --ch-scale (0.24) → 180×264 box. The
   wrapper must be explicitly sized because the root is position:absolute. */
.cb-mini-card {
    position: relative;
    width: 180px;
    height: 264px;
    flex: 0 0 auto;
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0 3px 12px rgba(0,0,0,0.5), 0 0 0 1px rgba(201,168,76,0.35);
}
.cb-mini-caption {
    font-size: 11.5px;
    color: #d8cdb4;
    text-align: center;
    font-family: 'Nunito Sans', system-ui, sans-serif;
}
.cb-mini-caption b { color: #ffe6a3; }
@media (prefers-reduced-motion: reduce) {
    .card-pin-createdby-detail { animation: none; }
    .card-pin-createdby-btn { transition: none; }
    .card-pin-createdby-btn .cb-caret { transition: none; }
}

.card-pin-body {
    padding: 10px;
    overflow: hidden;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 0;
}

/* Scaler: sized to the visual card dimensions so layout matches visual */
.card-pin-scaler {
    position: relative;
    overflow: hidden;
    flex-shrink: 0;
}
.card-pin-scaler .ch-card-root {
    position: absolute;
    top: 0;
    left: 0;
}

/* ── Compact modes: rules text is always kept (most important info) ─────────
   pin-small  (0.18–0.30): hide art + bible verse → rules fills the card
   pin-micro  (< 0.18):    hide art + title + bible verse → color+type+rules+cost only
   ─────────────────────────────────────────────────────────────────────────── */

/* pin-small: drop art and flavor text, rules text gets the space */
.card-pin-scaler .ch-card-root.pin-small .card-art,
.card-pin-scaler .ch-card-root.pin-small .bible-verse { display: none !important; }
.card-pin-scaler .ch-card-root.pin-small .card-rules {
    margin-top: 0;
    padding-top: 16px;
    background: linear-gradient(to bottom, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.15) 100%) !important;
}
.card-pin-scaler .ch-card-root.pin-small .rules-text {
    font-size: clamp(2rem, 3vw, 4.18rem);
    line-height: 1.3;
    font-weight: 600;
    text-shadow: 0 1px 2px rgba(0,0,0,0.3);
}

/* pin-micro: strip everything except color bg, type icon, rules text, cost */
.card-pin-scaler .ch-card-root.pin-micro .card-art,
.card-pin-scaler .ch-card-root.pin-micro .card-title-bar,
.card-pin-scaler .ch-card-root.pin-micro .bible-verse { display: none !important; }
.card-pin-scaler .ch-card-root.pin-micro .card-rules {
    margin-top: 0;
    padding-top: 4px;
    padding-left: 4px;
    padding-right: 4px;
    padding-bottom: 4px;
    background: linear-gradient(to bottom, rgba(0,0,0,0.25) 0%, rgba(0,0,0,0.45) 100%) !important;
    display: flex;
    flex-direction: column;
}
.card-pin-scaler .ch-card-root.pin-micro .rules-text {
    color: #fff;
    text-shadow: 0 2px 4px rgba(0,0,0,0.95), 0 0 2px rgba(0,0,0,0.7);
    font-size: clamp(1.2rem, 2vw, 3rem);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: 0.2px;
    word-break: break-word;
    flex: 1;
    overflow-y: auto;
    scrollbar-width: none;
}
.card-pin-scaler .ch-card-root.pin-micro .rules-text::-webkit-scrollbar { display: none; }

/* Ultra-compact header: type + cost inline */
.card-pin-scaler .ch-card-root.pin-micro::before {
    content: '';
    display: block;
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 32px;
    background: linear-gradient(90deg, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0.3) 100%);
    border-radius: 28px 28px 0 0;
    z-index: 10;
}

/* Type tag moves to compact header */
.card-pin-scaler .ch-card-root.pin-micro .card-type-tag {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 28px;
    height: 28px;
    font-size: 0.9rem;
    border: 1px solid rgba(255,255,255,0.4);
    background: rgba(255,255,255,0.1);
    color: #fff;
    z-index: 11;
}

/* Cost badge moves to header, right side */
.card-pin-scaler .ch-card-root.pin-micro .cost-badge {
    position: absolute;
    top: 1px;
    right: 2px;
    width: 30px;
    height: 30px;
    font-size: 1.2rem !important;
    padding: 0 !important;
    border-radius: 4px;
    z-index: 11;
}

/* ─── Compact card — rendered below COMPACT_THRESHOLD (< 0.40 scale) ────────
   Purpose-built flat layout that fills the panel at actual pixels.
   No transform scaling — text is always the same readable size.
   ─────────────────────────────────────────────────────────────────────────── */
/* ─── Compact card — rendered below COMPACT_THRESHOLD (< 0.40 scale) ────────
   Uses the card's own background image texture with a dark gradient overlay
   so text is always readable. No transform scaling — always actual pixels.
   ─────────────────────────────────────────────────────────────────────────── */
.pin-compact-card {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    border-radius: 6px;
    padding: 10px 12px 12px;
    display: flex;
    flex-direction: column;
    gap: 5px;
    overflow: hidden;
    font-family: 'Georgia', serif;
    background-size: cover;
    background-position: center;
    position: relative;
}
/* Dark overlay so text is legible over the texture */
.pin-compact-card::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 6px;
    background: linear-gradient(
        180deg,
        rgba(0,0,0,0.72) 0%,
        rgba(0,0,0,0.60) 40%,
        rgba(0,0,0,0.55) 100%
    );
    pointer-events: none;
    z-index: 0;
}
.pin-compact-card > * { position: relative; z-index: 1; }

/* Per-color overlay tint */
.pcc-fire::before  { background: linear-gradient(180deg, rgba(80,10,0,0.80) 0%, rgba(60,5,0,0.65) 100%); }
.pcc-grass::before { background: linear-gradient(180deg, rgba(0,40,10,0.80) 0%, rgba(0,30,5,0.65) 100%); }
.pcc-ice::before   { background: linear-gradient(180deg, rgba(0,20,60,0.80) 0%, rgba(0,15,50,0.65) 100%); }
.pcc-stone::before { background: linear-gradient(180deg, rgba(20,20,20,0.85) 0%, rgba(10,10,10,0.70) 100%); }
.pcc-gold::before  { background: linear-gradient(180deg, rgba(30,20,0,0.80) 0%, rgba(20,12,0,0.65) 100%); }

.pcc-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
    gap: 6px;
}
.pcc-type-icon {
    width: 28px;
    height: 28px;
    object-fit: contain;
    filter: drop-shadow(0 1px 3px rgba(0,0,0,0.8));
    flex-shrink: 0;
}
.pcc-type-text {
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1.2px;
}
.pcc-cost {
    font-size: 14px;
    font-weight: 900;
    width: 30px;
    height: 30px;
    border-radius: 5px;
    border: 2px solid rgba(255,255,255,0.3);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    line-height: 1;
    background: #22a12a;  /* green — matches cost-box in full cards */
    color: #fff !important;
    text-shadow: 0 1px 3px rgba(0,0,0,0.6);
    box-shadow: 0 0 0 1px #5a5a5a, 0 2px 4px rgba(0,0,0,0.4);
}
.pcc-name {
    font-size: 13px;
    font-weight: 700;
    line-height: 1.2;
    font-family: 'Cinzel', serif;
    text-shadow: 0 1px 4px rgba(0,0,0,0.9);
    flex-shrink: 0;
    color: #fff;
}
.pcc-divider {
    height: 1px;
    border: none;
    border-top: 1px solid;
    flex-shrink: 0;
    margin: 2px 0;
}
.pcc-rules {
    font-size: clamp(11px, 1.5vw, 13px);
    line-height: 1.6;
    flex: 1;
    overflow-y: auto;
    color: #f0e8d8;
    text-shadow: 0 1px 3px rgba(0,0,0,0.9);
    font-weight: 500;
}
.pcc-rules::-webkit-scrollbar { width: 3px; }
.pcc-rules::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.25); border-radius: 2px; }

/* ── rules-text icons/boxes inside compact panel and pile modal ─────────── */
.pcc-rules .rules-text-icon,
.pmr-rules .rules-text-icon {
    display: inline-block;
    border-radius: 10px;
    font-size: clamp(11px, 1.3vw, 14px);
    padding: 2px 7px;
    color: white;
    box-shadow: 0 0 0 2px #fff, 0 1px 2px rgba(0,0,0,0.5);
    font-weight: bold;
    min-width: 14px;
    text-align: center;
    line-height: 1.4;
    vertical-align: middle;
}
.pcc-rules .cost-box,
.pmr-rules .cost-box {
    background: #22a12a;
    box-shadow: 0 0 0 2px #5a5a5a, 0 1px 0 rgba(0,0,0,0.4);
}
.pcc-rules .draw-to-hand-box,
.pmr-rules .draw-to-hand-box { background: #2892ff; }

.pcc-rules .negative-box,
.pmr-rules .negative-box { background: #a12222; border-radius: 4px; }

.pcc-rules .discard-from-cost-zone-box,
.pmr-rules .discard-from-cost-zone-box { background: #958f8f; }

/* Humility triangle */
.pcc-rules .humility-box,
.pmr-rules .humility-box {
    all: unset;
    position: relative;
    display: inline-block;
    width: 0; height: 0;
    border-left: 14px solid transparent;
    border-right: 14px solid transparent;
    border-bottom: 20px solid #05d587;
    top: -3px;
    vertical-align: middle;
}
.pcc-rules .humility-box::before,
.pmr-rules .humility-box::before {
    content: "";
    position: absolute;
    width: 0; height: 0;
    border-left: 17px solid transparent;
    border-right: 17px solid transparent;
    border-bottom: 24px solid #004c2b;
    top: 0px; left: -17px;
    z-index: -1;
}
.pcc-rules .humility-box::after,
.pmr-rules .humility-box::after {
    content: "";
    position: absolute;
    width: 0; height: 0;
    border-left: 17px solid transparent;
    border-right: 17px solid transparent;
    border-bottom: 24px solid #004c2b;
    top: -5px; left: -17px;
    z-index: -1;
}
.pcc-rules .humility-box .humility-text,
.pmr-rules .humility-box .humility-text {
    all: unset;
    position: absolute;
    left: 50%; top: 14px;
    transform: translate(-50%, -50%);
    font-size: 10px;
    font-weight: bold;
    color: white;
    -webkit-text-stroke: 0.6px #00170c;
    text-shadow: 0 0 2px #000;
    white-space: nowrap;
}

/* Tilde box */
.pcc-rules .tilde-box,
.pmr-rules .tilde-box {
    font-size: 11px;
    background: lightgoldenrodyellow;
    border-radius: 5px;
    display: inline-block;
    padding: 1px 4px;
    color: #333;
}
.pcc-rules .tilde-box.tilde-D,
.pmr-rules .tilde-box.tilde-D { background: #2892ff; color: white; }

.pcc-rules .tilde-box.tilde-BB,
.pmr-rules .tilde-box.tilde-BB {
    background: rgba(208,250,249,0.85);
    display: inline-block;
    padding: 2px 4px;
    width: 97%;
    box-sizing: border-box;
}
.pcc-rules .tilde-box.tilde-U,
.pmr-rules .tilde-box.tilde-U { background: #abecc5; color: black; }

.pcc-rules .tilde-box .desc,
.pmr-rules .tilde-box .desc { display: none; }

/* Inline card-type icons */
.pcc-rules .card-graphics-img,
.pmr-rules .card-graphics-img {
    width: 20px;
    height: auto;
    vertical-align: middle;
    display: inline;
}
/* Math symbol */
.pcc-rules .math-symbol,
.pmr-rules .math-symbol { font-weight: bold; font-size: 1em; }

/* ═══════════════════════════════════════════════════════════════════════════
   Shared Zones — context-aware temptation field visibility
   ═══════════════════════════════════════════════════════════════════════════ */

/* Default: no active temptations, not in evil/resistance phase
   → collapse the temptation wrap entirely; shared-zones becomes a slim pile bar */
#zone-evil-field-wrap {
    display: none;
    flex: 1;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

/* During evil/resistance phase but no cards yet: show a subtle waiting indicator */
#shared-zones.evil-active-phase #zone-evil-field-wrap {
    display: flex;
}
#shared-zones.evil-active-phase:not(.has-temptations) #zone-evil-field-wrap::before {
    content: 'Awaiting temptations…';
    font-family: 'Cinzel', serif;
    font-size: 8px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(200,60,40,0.35);
    padding: 6px 0;
}
#shared-zones.evil-active-phase:not(.has-temptations) #zone-evil-field {
    display: none;
}

/* Active temptations present: full display */
#shared-zones.has-temptations #zone-evil-field-wrap {
    display: flex;
}

/* Slim layout when no temptation wrap showing */
#shared-zones:not(.has-temptations):not(.evil-active-phase) {
    padding: 5px 12px;
    gap: 12px;
}
#shared-zones:not(.has-temptations):not(.evil-active-phase) #zone-evil-field-wrap {
    display: none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Phase-aware card highlighting
   ═══════════════════════════════════════════════════════════════════════════ */
.card-tile.card-playable {
    box-shadow:
        0 2px 8px rgba(0,0,0,0.6),
        0 0 0 2px rgba(245,205,60,0.75),
        0 0 12px rgba(245,205,60,0.35);
    border-color: rgba(245,205,60,0.6);
}
.card-tile.card-playable:hover {
    box-shadow:
        0 12px 30px rgba(0,0,0,0.7),
        0 0 0 2px rgba(255,215,70,0.95),
        0 0 22px rgba(245,205,60,0.5);
    border-color: rgba(255,215,70,0.8);
}
/* COOP "ally can play" secondary tint: a teal/blue glow, distinct from your
   own yellow .card-playable, so it reads as informational — a teammate's
   playable option (chiefly an out-of-turn Unction), not something you can
   play yourself. */
.card-tile.card-playable-ally {
    box-shadow:
        0 2px 8px rgba(0,0,0,0.6),
        0 0 0 2px rgba(64,200,215,0.7),
        0 0 12px rgba(64,200,215,0.32);
    border-color: rgba(64,200,215,0.55);
}
.card-tile.card-playable-ally::after {
    content: '';
    position: absolute;
    top: 3px; right: 3px;
    width: 8px; height: 8px;
    border-radius: 50%;
    background: radial-gradient(circle at 40% 40%, #7fe8f2, #23a3b5);
    box-shadow: 0 0 6px rgba(64,200,215,0.8);
    pointer-events: none;
    z-index: 6;
}
.card-tile.card-playable-ally:hover {
    box-shadow:
        0 12px 30px rgba(0,0,0,0.7),
        0 0 0 2px rgba(96,220,235,0.95),
        0 0 22px rgba(64,200,215,0.45);
    border-color: rgba(96,220,235,0.8);
}
.card-tile.card-dimmed {
    opacity: 0.35;
    filter: grayscale(55%);
}
.card-tile.card-dimmed:hover {
    opacity: 0.65;
    filter: grayscale(25%);
    transform: translateY(-4px) scale(1.02);
}

/* ═══════════════════════════════════════════════════════════════════════════
   Hand modal sort / layout bar
   ═══════════════════════════════════════════════════════════════════════════ */
.hand-modal-sort-bar {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 7px 16px;
    border-bottom: 1px solid rgba(201,168,76,0.12);
    flex-wrap: wrap;
    background: rgba(0,0,0,0.25);
    flex-shrink: 0;
}
.hand-modal-sort-bar .sort-label {
    font-family: 'Cinzel', serif;
    font-size: 9px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(201,168,76,0.4);
    margin-right: 2px;
    flex-shrink: 0;
}
.hand-modal-sort-btn {
    font-family: 'Cinzel', serif;
    font-size: 9px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    background: rgba(201,168,76,0.07);
    border: 1px solid rgba(201,168,76,0.18);
    color: rgba(201,168,76,0.6);
    border-radius: 4px;
    padding: 3px 8px;
    cursor: pointer;
    transition: background 0.14s, color 0.14s, border-color 0.14s;
    white-space: nowrap;
}
.hand-modal-sort-btn:hover {
    background: rgba(201,168,76,0.16);
    color: rgba(201,168,76,0.9);
    border-color: rgba(201,168,76,0.38);
}
.hand-modal-sort-btn.active {
    background: rgba(201,168,76,0.22);
    color: rgba(201,168,76,1);
    border-color: rgba(201,168,76,0.55);
    box-shadow: 0 0 6px rgba(201,168,76,0.2);
}
.hand-modal-sort-divider {
    width: 1px;
    height: 16px;
    background: rgba(201,168,76,0.18);
    flex-shrink: 0;
    margin: 0 2px;
}

/* Fan layout mode — snug overlap so many cards fit in one row; hover
 * lifts the card up out of the stack. Padding keeps a little room for
 * the hover-lift to land without clipping the previous row. */
.hand-modal-grid.layout-fan {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 6px 8px 10px;
    align-items: flex-end;
    gap: 0;
}
.hand-modal-grid.layout-fan .card-tile {
    margin-right: calc(var(--hm-card-w, 120px) * -0.38);
    flex-shrink: 0;
    transition: transform 0.18s, margin-right 0.18s;
}
.hand-modal-grid.layout-fan .card-tile:last-child {
    margin-right: 0;
}
.hand-modal-grid.layout-fan .card-tile:hover {
    transform: translateY(-22px) scale(1.08) !important;
    margin-right: 12px !important;
    z-index: 20;
}

/* ─── "YOU" indicator on locally-controlled player (online mode) ───────────
 * body.is-online is toggled by init.js when GAME_CONFIG.online.enabled.
 * The .player-area-local class is applied by GameUI._markLocalPlayerArea()
 * to every player this browser controls. In pass-and-play the same class
 * is applied to the active player; we scope the badge to online so the
 * label doesn't "follow" the active player during local hot-seat games. */
body.is-online .player-area.player-area-local .player-name::after {
    content: 'YOU';
    display: inline-block;
    margin-left: 8px;
    padding: 1px 7px;
    background: var(--col-divine, #c9a84c);
    color: #111;
    font-family: 'Cinzel', serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    border-radius: 3px;
    vertical-align: 2px;
    box-shadow: 0 0 8px rgba(201,168,76,0.45);
}
body.is-online .player-area.player-area-local {
    outline: 1px solid rgba(201,168,76,0.35);
    outline-offset: -1px;
}

/* ─── Roman War theme playmat ──────────────────────────────────────────────
 * Hannibal-vs-Rome SVG mat on a deep red radial underlay so any transparent
 * or short-edged regions still read as the Roman War theme. */
body.theme-romanwar #board.playmat-bg,
body.theme-romanwar .playmat-grid {
    background-image:
        url('../img/hannibal_vs_rome_mat.svg'),
        radial-gradient(ellipse at 50% 50%, rgba(180,28,28,0.55) 0%, rgba(60,8,8,0.95) 75%);
    background-color: #2e0808 !important;
    background-size: cover, cover;
    background-position: center, center;
    background-repeat: no-repeat, no-repeat;
}
body.theme-romanwar #board.playmat-bg .player-area,
body.theme-romanwar #board.playmat-bg #shared-zones {
    background: rgba(10,0,0,0.55);
}
body.theme-romanwar .playmat-grid {
    border-color: rgba(201,168,76,0.35);
}

/* ─── Kittens theme ────────────────────────────────────────────────────────
 * Full palette for the cats-vs-mice game: warm cream/orange-tabby for the
 * cats (righteous), cool mouse-grey for the mice invasion (evil). Every
 * gold/crimson/sapphire var is overridden so buttons, pills, badges, dialogs
 * and zone frames read as the kittens game, not re-skinned Christianity. */
body.theme-kittens {
    /* accents: orange tabby replaces sacred gold */
    --col-divine:      #f2a65a;
    --col-divine-glow: rgba(242,166,90,0.35);
    --col-accent:      #f2a65a;
    --col-active:      #ffc97e;
    /* evil: mouse grey replaces crimson */
    --col-crimson:     #8a8a94;
    --col-blood:       rgba(122,122,134,0.45);
    --col-evil-bg:     #101014;
    /* board + panels: warm dusk browns */
    --col-right-bg:    #171008;
    --col-shared:      #171209;
    --col-board:       #120d08;
    --col-text:        #f0e6d4;
    --col-text-dim:    rgba(240,230,212,0.5);
    --col-sapphire:    #7a4a1e;
    --col-sapphire-glow: rgba(122,74,30,0.45);
}
/* Evil area — the mice: cool grey, not chr crimson */
body.theme-kittens .player-area.evil {
    background: linear-gradient(135deg, rgba(74,74,86,0.55) 0%, rgba(17,17,23,0.95) 100%);
    border: 1px solid rgba(150,150,165,0.55);
    border-bottom: 1px solid rgba(150,150,165,0.3);
    box-shadow: inset 0 1px 0 rgba(190,190,205,0.15), 0 4px 24px rgba(0,0,0,0.6);
}
body.theme-kittens .player-area.evil .player-name { color: #c9ced8; }
/* Righteous area — the cats: warm cream/orange, not chr sapphire */
body.theme-kittens .player-area.righteous {
    background: linear-gradient(135deg, rgba(96,56,20,0.55) 0%, rgba(26,15,6,0.97) 100%);
    border: 1px solid rgba(242,166,90,0.5);
    border-top: 1px solid rgba(242,166,90,0.35);
    box-shadow: inset 0 -1px 0 rgba(255,205,150,0.12), 0 -4px 24px rgba(0,0,0,0.5);
}
/* Shared battlefield + phase bar: warm hearth tones */
body.theme-kittens #shared-zones {
    background:
        radial-gradient(ellipse 80% 100% at 50% 50%, rgba(40,24,10,0.85) 0%, transparent 100%),
        linear-gradient(180deg, rgba(20,12,4,0.9) 0%, rgba(14,9,4,0.9) 100%);
    border: 1px solid rgba(242,166,90,0.25);
}
body.theme-kittens #phase-bar {
    background: linear-gradient(180deg, rgba(30,19,9,0.97), rgba(18,12,6,0.97));
    border-color: rgba(242,166,90,0.28);
}
/* Playmat + quads: cosy blanket underlay; evil quad leans mouse-grey */
body.theme-kittens #board.playmat-bg,
body.theme-kittens .playmat-grid {
    background-image:
        radial-gradient(ellipse at 50% 40%, rgba(242,166,90,0.30) 0%, rgba(120,62,42,0.55) 55%, rgba(40,22,12,0.95) 100%);
    background-color: #241408 !important;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
body.theme-kittens #board.playmat-bg .player-area,
body.theme-kittens #board.playmat-bg #shared-zones {
    background: rgba(26,14,6,0.55);
}
body.theme-kittens .playmat-grid { border-color: rgba(242,166,90,0.4); }
body.theme-kittens .playmat-quad.quad-good-habituals { background: rgba(242,166,90,0.14); }
body.theme-kittens .playmat-quad.quad-evil-habituals { background: rgba(120,120,134,0.28); }
body.theme-kittens .playmat-quad.quad-evil-habituals .quad-label { color: #c9ced8; border-bottom-color: rgba(170,175,188,0.35); }
body.theme-kittens .playmat-quad.quad-available { background: rgba(255,222,180,0.10); }
body.theme-kittens .playmat-quad.quad-spent     { background: rgba(90,60,30,0.30); }
/* Corner menu + build stamp pick up the tabby accent */
body.theme-kittens #game-quick-help .qh-btn {
    border-color: rgba(242,166,90,0.5);
    color: #f2a65a;
    background: rgba(60,36,14,0.85);
}

/* ─── Plant theme playmat ──────────────────────────────────────────────────
 * "Plants vs Pests": swap the baked-in CHRISTIANITY playmat watermark for the
 * plant logo on a verdant radial underlay. The logo PNG is on a black field,
 * so screen-blend it against the gradient — the black drops out and only the
 * glowing crest reads as a faded centre watermark. */
body.theme-plantlover #board.playmat-bg,
body.theme-plantlover .playmat-grid {
    background-image:
        url('/games/christianity/images/plantlover_logo.png'),
        radial-gradient(ellipse at 50% 50%, rgba(70,150,45,0.45) 0%, rgba(14,40,10,0.96) 75%);
    background-color: #0e280a !important;
    background-size: 340px auto, cover;
    background-position: center, center;
    background-repeat: no-repeat, no-repeat;
    background-blend-mode: screen, normal;
}
body.theme-plantlover #board.playmat-bg .player-area,
body.theme-plantlover #board.playmat-bg #shared-zones {
    background: rgba(6,20,4,0.55);
}
body.theme-plantlover .playmat-grid { border-color: rgba(120,200,80,0.35); }

/* ─── Block-building theme playmat ─────────────────────────────────────────
 * No logo asset for this theme → neutral slate underlay, no watermark, so the
 * CHRISTIANITY crest never bleeds through. */
body.theme-blockbuilding #board.playmat-bg,
body.theme-blockbuilding .playmat-grid {
    background-image:
        radial-gradient(ellipse at 50% 45%, rgba(90,110,130,0.30) 0%, rgba(28,36,46,0.96) 75%);
    background-color: #1b222b !important;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
body.theme-blockbuilding #board.playmat-bg .player-area,
body.theme-blockbuilding #board.playmat-bg #shared-zones {
    background: rgba(12,16,22,0.55);
}
body.theme-blockbuilding .playmat-grid { border-color: rgba(120,150,180,0.30); }

/* ─── Christianity theme playmat ───────────────────────────────────────────
 * The default board art (img/playmat-chr.png) is a photo of the physical mat
 * with the crest logo AND all five zone labels ("Good Habituals and Tokens",
 * "Evil Habituals", "Available", "Cost Zone", "Spent") baked in — five faint
 * ghost-text layers overlapping behind the live quadrants, which already carry
 * their own header labels. The kittens board drops the photo for a clean
 * gradient and reads far better; match that here: a themed sapphire underlay
 * with the crest wordmark ALONE, screen-blended and faint, as a single
 * tasteful centre watermark. (The dark PNG field drops out under `screen`, so
 * only the crest letters glow through.) */
body.theme-chr #board.playmat-bg,
body.theme-chr .playmat-grid {
    background-image:
        url('/games/christianity/images/ccg_logo668x.png'),
        radial-gradient(ellipse at 50% 42%, rgba(74,120,196,0.26) 0%, rgba(24,40,78,0.72) 52%, rgba(9,15,33,0.96) 100%);
    background-color: #0c1428 !important;
    background-size: 300px auto, cover;
    background-position: center 44%, center;
    background-repeat: no-repeat, no-repeat;
    background-blend-mode: screen, normal;
}
body.theme-chr #board.playmat-bg .player-area,
body.theme-chr #board.playmat-bg #shared-zones {
    background: rgba(4,8,20,0.55);
}
body.theme-chr .playmat-grid { border-color: rgba(201,168,76,0.30); }

/* ─── Coop: collapse the Evil entity to a thin stats strip ─────────────────
 * In co-op the AI plays Evil, so the evil area is just a Deck/Discard
 * readout. Avoid the giant empty panel by flattening it. */
.player-area.coop-evil {
    min-height: 36px !important;
    max-height: 44px !important;
    padding: 4px 12px !important;
    display: flex !important;
    align-items: center;
    overflow: hidden;
}
.player-area.coop-evil .player-stats {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: nowrap;
    width: 100%;
}
.player-area.coop-evil .player-name { font-size: 13px; }
.player-area.coop-evil #evil-announcement { display: none; }

/* Persistent build stamp during gameplay — bottom-right corner, dimmed,
   click to dismiss. Shows the same timestamp as the loading screen so
   the user can confirm which deploy they're running without reloading.
   Wrapped in #game-corner-bar so the quick-help icon strip can sit
   inline next to it. */
#game-corner-bar {
    position: fixed;
    right: 6px;
    bottom: 6px;
    z-index: 1200;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    pointer-events: auto;
}
#game-corner-bar.dismissed { display: none; }

/* ── Turn-1 start hint (end-of-Draw pause) ──────────────────────────────
   A SMALL floating toast chip OVERLAID on the board — hosted on <body>,
   position:fixed !important (defensive: broad container rules like
   `#board > *` set position:relative and must never re-capture the chip
   into layout flow — that's what made it render as a giant grid-row panel). */
.start-draw-hint {
    position: fixed !important;
    top: 48px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1500;
    display: inline-flex !important;
    align-items: center;
    gap: 8px;
    width: max-content;
    max-width: min(92vw, 460px);
    padding: 5px 10px;
    background: rgba(20, 14, 6, 0.92);
    border: 1px solid rgba(201,168,76,0.55);
    border-radius: 9px;
    color: #efe4c6;
    font-family: 'Cinzel', serif;
    font-size: 12px;
    line-height: 1.3;
    box-shadow: 0 4px 14px rgba(0,0,0,0.5);
    pointer-events: none;            /* never blocks the board… */
}
.start-draw-hint.sdh-wide { max-width: min(94vw, 760px); }   /* the longer GOAL line */
.start-draw-hint .sdh-icon { flex: 0 0 auto; }
.start-draw-hint .sdh-x {
    pointer-events: auto;            /* …except its dismiss button */
    flex: 0 0 auto;
    background: transparent;
    border: 0;
    color: #d8bd72;
    font-size: 12px;
    cursor: pointer;
    padding: 0 2px;
}
.start-draw-hint .sdh-x:hover { color: #f4e9c1; }

/* ── Corner ☰ popover menu (consolidates the old icon strip) ──────────── */
#corner-menu-pop {
    position: absolute;
    right: 0;
    bottom: calc(100% + 8px);
    min-width: 200px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 6px;
    background: rgba(20, 14, 6, 0.96);
    border: 1px solid rgba(201,168,76,0.6);
    border-radius: 10px;
    box-shadow: 0 6px 22px rgba(0,0,0,0.6);
    z-index: 1300;
}
#corner-menu-pop.hidden { display: none; }
.corner-menu-item {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 7px 10px;
    background: transparent;
    border: none;
    border-radius: 7px;
    color: #efe4c6;
    font-family: 'Cinzel', serif;
    font-size: 12.5px;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
}
.corner-menu-item:hover { background: rgba(201,168,76,0.16); color: #f4e9c1; }
.corner-menu-item .cmi-icon { width: 20px; text-align: center; flex: 0 0 auto; }
.corner-menu-item .cmi-label { flex: 1 1 auto; white-space: nowrap; }
#game-build-stamp {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: 'Nunito Sans', system-ui, sans-serif;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #f0d07a;
    background: rgba(20, 14, 6, 0.82);
    border: 1px solid rgba(201,168,76,0.6);
    border-radius: 4px;
    padding: 3px 8px;
    cursor: pointer;
    user-select: none;
    text-shadow: 0 1px 2px rgba(0,0,0,0.8);
    box-shadow: 0 0 6px rgba(201,168,76,0.18);
    transition: opacity 120ms ease-out;
}
#game-build-stamp .gbs-beta {
    font-size: 10px;
    padding: 1px 5px;
    border-radius: 3px;
    background: rgba(201,168,76,0.9);
    color: #1a1208;
    letter-spacing: 0.1em;
}
#game-build-stamp .gbs-ago {
    opacity: 0.8;
    font-weight: 500;
}
#game-build-stamp:hover { opacity: 0.85; }
#game-build-stamp.dismissed { display: none; }

/* Quick-help icon strip — flex sibling of #game-build-stamp inside
   #game-corner-bar, so it always sits flush left of the build banner. */
#game-quick-help {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
#game-quick-help .qh-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 22px;
    background: rgba(20, 14, 6, 0.82);
    border: 1px solid rgba(201,168,76,0.6);
    border-radius: 4px;
    color: #f0d07a;
    font-size: 13px;
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    box-shadow: 0 0 6px rgba(201,168,76,0.18);
    transition: background 120ms ease-out, transform 120ms ease-out, border-color 120ms ease-out;
}
#game-quick-help .qh-btn:hover {
    background: rgba(50, 32, 12, 0.95);
    border-color: #f0d07a;
    transform: translateY(-1px);
}
#game-quick-help .qh-btn:active { transform: translateY(0); }

/* Admin quick-inspect toggle — obvious highlighted "active" state when ON. */
#admin-quick-toggle.admin-quick-on {
    background: linear-gradient(180deg, #f4e9c1, #d4af37);
    border-color: #f0d07a;
    color: #1a1208;
    box-shadow: 0 0 8px rgba(201,168,76,0.6), inset 0 0 0 1px rgba(255,255,255,0.25);
}
/* Discoverability: while admin quick-inspect is ON, cards get a pointer cursor
   and a subtle gold glow + ✎ hint on hover so it's clear a click will open the
   enlarged view for editing. */
body.admin-quick-mode .card-tile { cursor: zoom-in; }
body.admin-quick-mode .card-tile:hover {
    outline: 2px solid rgba(201,168,76,0.85);
    outline-offset: -2px;
    box-shadow: 0 0 12px rgba(201,168,76,0.5);
}
body.admin-quick-mode .card-tile:hover::after {
    content: "✎";
    position: absolute;
    top: 2px;
    right: 2px;
    z-index: 30;
    font-size: 12px;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 4px;
    color: #1a1208;
    background: rgba(240,208,122,0.95);
    box-shadow: 0 1px 3px rgba(0,0,0,0.6);
    pointer-events: none;
}

/* Card-Types reference overlay (opened via the 🎴 quick-help icon).
   Compact table of every card type, when to play it, and what it does.
   Theme-aware labels are baked into the PHP markup. */
.cardtype-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
    margin: 12px 0 8px;
}
.cardtype-table th,
.cardtype-table td {
    padding: 8px 10px;
    border-bottom: 1px solid rgba(201,168,76,0.18);
    vertical-align: middle;
    text-align: left;
}
.cardtype-table th {
    color: #f0d07a;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 11px;
    font-weight: 700;
    background: rgba(201,168,76,0.06);
}
.cardtype-table td:first-child {
    white-space: nowrap;
    color: var(--col-divine, #f0d07a);
    font-family: 'Cinzel', serif;
}
.cardtype-icon {
    width: 22px;
    height: 22px;
    object-fit: contain;
    vertical-align: middle;
    margin-right: 8px;
}
.cardtype-icon-text {
    display: inline-block;
    width: 22px;
    text-align: center;
    margin-right: 8px;
    font-size: 16px;
    line-height: 22px;
}
.phase-pill {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    background: rgba(109,192,232,0.15);
    border: 1px solid rgba(109,192,232,0.5);
    color: #cbe6f5;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    white-space: nowrap;
}
.phase-pill.auto {
    background: rgba(232,96,58,0.15);
    border-color: rgba(232,96,58,0.5);
    color: #f0c4b3;
}
.cardtype-note {
    font-size: 12px;
    color: var(--col-text, #d8c89a);
    opacity: 0.85;
    margin-top: 8px;
}
.cardtype-note a {
    color: var(--col-divine, #f0d07a);
    text-decoration: underline;
}

.pile-modal-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
    padding: 6px 8px;
    background: rgba(18, 12, 4, 0.55);
    border-bottom: 1px solid rgba(201,168,76,0.22);
}
.pile-modal-filters input,
.pile-modal-filters select {
    font: inherit;
    font-size: 12px;
    padding: 3px 6px;
    background: rgba(30, 22, 10, 0.8);
    color: #f0d07a;
    border: 1px solid rgba(201,168,76,0.35);
    border-radius: 3px;
    min-width: 0;
}
.pile-modal-filters input.pmf-q { flex: 1 1 140px; }
.pile-modal-filters input.pmf-cost-val { width: 54px; }
.pile-modal-filters select { max-width: 120px; }
.pile-modal-filters .pmf-clear {
    background: rgba(140, 40, 30, 0.55);
    color: #ffd7c3;
    border: 1px solid rgba(220,120,80,0.5);
    border-radius: 3px;
    padding: 3px 7px;
    font-size: 12px;
    cursor: pointer;
}
.pile-modal-filters .pmf-clear:hover { background: rgba(180, 55, 40, 0.8); }
.pile-modal-filters .pmf-count {
    margin-left: auto;
    font-size: 11px;
    color: rgba(201,168,76,0.75);
    letter-spacing: 0.06em;
}

/* ─── Seat placement ───────────────────────────────────────────────────────
 * Lets the player choose which SIDE of the board their own seat sits on. Two
 * body classes drive it (set by GameUI._applyPlacement): `placement-local-left`
 * (default) and `placement-local-right`. GameUI adds `placement-side-split`
 * for the single-seat duel layout (your area vs a full evil area) and
 * `placement-rotated` for the multi-seat seat-ring rotation.
 *
 * Everything here is gated to ≥1000px so the narrow-screen stacked layout
 * (mobile.css / experience.css single column) is never fought — on phones the
 * board keeps its vertical order regardless of the chosen placement.
 *
 * Specificity note: game.php ships an inline `#board.has-active-temptations …`
 * block (id+class) that appears after these linked sheets in source order.
 * The `body.… #board` selectors below carry an extra element (body), giving
 * (1,1,1) > (1,1,0), so they win no matter the cascade order. */
@media (min-width: 1000px) {

    /* Solo / PvP duel: your area on one side, the (full) evil area on the
       other, with the shared battlefield + phase bar as full-width bands. */
    body.placement-side-split #board {
        grid-template-columns: var(--board-split, 1fr) var(--board-split-r, 1fr) !important;
        grid-template-rows: auto auto minmax(0, 1fr) !important;
        grid-template-areas:
            "shared shared"
            "phase  phase"
            "me     foe"    !important;
        position: relative;
    }
    /* Draggable divider to resize the two player areas (persisted). */
    #board-split-handle {
        position: absolute; top: 0; bottom: 0; width: 12px; margin-left: -6px;
        z-index: 45; cursor: col-resize; background: transparent;
        transition: background .12s ease;
    }
    #board-split-handle::before {
        content: ''; position: absolute; left: 5px; top: 12%; bottom: 12%; width: 2px;
        background: rgba(201,168,76,0.28); border-radius: 2px;
    }
    #board-split-handle:hover { background: rgba(201,168,76,0.14); }
    #board-split-handle:hover::before { background: rgba(230,195,74,0.85); box-shadow: 0 0 8px rgba(230,195,74,0.6); }
    body.placement-side-split #shared-zones            { grid-area: shared !important; }
    body.placement-side-split #phase-bar               { grid-area: phase  !important; }
    body.placement-side-split .player-area.righteous   { grid-area: me  !important; }
    body.placement-side-split .player-area.evil        { grid-area: foe !important; }

    /* Flip: your seat moves to the right column, evil to the left. */
    body.placement-side-split.placement-local-right #board {
        grid-template-areas:
            "shared shared"
            "phase  phase"
            "foe    me"     !important;
    }

    /* Multi-seat (co-op): the righteous areas already sit side-by-side in the
       bottom row. Use grid `order` to slide the LOCAL seat to the far left or
       far right without touching anyone else's order. The rotation states
       (placement-rotated) drive order via inline styles from JS instead. */
    body.multi-righteous.placement-local-left:not(.placement-rotated)
        .player-area.righteous.player-area-local  { order: -1 !important; }
    body.multi-righteous.placement-local-right:not(.placement-rotated)
        .player-area.righteous.player-area-local  { order: 99 !important; }
}

/* The placement button GameUI injects next to the view-mode toggle. Inherits
   .btn-icon styling; this just gives the glyph a hair more weight so ⇄ reads. */
.phase-bar-btns .placement-toggle { font-weight: 700; }
.phase-bar-btns .sides-toggle     { font-weight: 700; }
.phase-bar-btns .sides-toggle.sides-flipped { color: #f0a; }

/* ─── Sides orientation: flip which team sits on TOP ───────────────────────
 * Default (no class): evil-band on top, righteous-band on bottom. The bands are
 * pinned to explicit grid ROWS, so body.sides-flip is applied by JS
 * (GameUI._applySidesRowTemplate) which REVERSES both the row sizes and each
 * band's grid-row — putting the righteous band on top and the evil band on the
 * bottom (evil-player / evil-view perspective). Left/right ordering of the
 * righteous seats (⇄ placement) is untouched. */

/* ─── Auto-drive (🚗) toggle + on-board indicator + 🤖 AI seat badge ────────
   GameUI injects the 🚗 button next to the ✨/⇄/🔲 toggles. The "on" state
   lights it in the divine accent so it's obvious the AI is playing your seat,
   backed by a pulsing on-board banner. The 🤖 AI badge marks every isBot seat
   (bot allies, auto-driven seats, disconnect-takeover bots). */
.phase-bar-btns .autodrive-toggle { font-weight: 700; }
.phase-bar-btns .autodrive-toggle.autodrive-on {
    color: var(--col-divine, #c9a84c);
    border-color: rgba(201,168,76,0.55);
    background: rgba(201,168,76,0.18);
    box-shadow: 0 0 8px rgba(201,168,76,0.45);
}

#autodrive-indicator {
    position: fixed;
    left: 50%;
    bottom: 14px;
    transform: translateX(-50%);
    z-index: 9500;
    padding: 8px 16px;
    border-radius: 999px;
    border: 1px solid rgba(201,168,76,0.5);
    background: rgba(28,33,48,0.94);
    color: var(--col-divine, #c9a84c);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    cursor: pointer;
    box-shadow: 0 4px 18px rgba(0,0,0,0.45), 0 0 14px rgba(201,168,76,0.3);
    animation: autodrive-pulse 1.8s ease-in-out infinite;
}
#autodrive-indicator:hover { background: rgba(40,46,64,0.98); }
@keyframes autodrive-pulse {
    0%,100% { box-shadow: 0 4px 18px rgba(0,0,0,0.45), 0 0 10px rgba(201,168,76,0.25); }
    50%     { box-shadow: 0 4px 18px rgba(0,0,0,0.45), 0 0 20px rgba(201,168,76,0.55); }
}

.player-area .ai-seat-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 6px;
    background: rgba(120,150,190,0.16);
    color: #9fc0e8;
    border: 1px solid rgba(140,170,210,0.35);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    border-radius: 3px;
    vertical-align: 2px;
    white-space: nowrap;
}

/* Host-permissioned DROP-IN button (take over / hand back a bot seat). */
.player-area .seat-dropin-btn {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 9px;
    background: linear-gradient(180deg, rgba(63,143,79,0.28), rgba(63,143,79,0.14));
    color: #b9f0c6;
    border: 1px solid rgba(90,190,120,0.55);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.02em;
    border-radius: 5px;
    cursor: pointer;
    white-space: nowrap;
    vertical-align: 1px;
}
.player-area .seat-dropin-btn:hover { border-color: #7fe0a0; background: rgba(63,143,79,0.4); }
.player-area .seat-dropin-btn.is-handback {
    background: linear-gradient(180deg, rgba(120,150,190,0.24), rgba(120,150,190,0.12));
    color: #cfe0f2;
    border-color: rgba(140,170,210,0.5);
}

/* Spectator / all-bots banner — fixed, unobtrusive, top-centre. */
#spectator-banner {
    position: fixed;
    top: 8px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 940;
    padding: 5px 16px;
    background: rgba(20,24,34,0.94);
    color: #f0d07a;
    border: 1px solid rgba(201,168,76,0.55);
    border-radius: 999px;
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0.04em;
    pointer-events: none;
    box-shadow: 0 6px 20px -8px rgba(0,0,0,0.7);
}

/* ─── Spectate PAUSE (⏸/▶) toggle + "paused" indicator ─────────────────────
   Shown only while watching an all-bots / spectator game (GameUI injects it
   next to 🚗/✨/🐢/⇄/🔲). The paused state lights the button and drops a clear
   fixed banner so it's obvious the board is frozen for examination. */
.phase-bar-btns .spectate-pause-toggle { font-weight: 700; }
.phase-bar-btns .spectate-pause-toggle.spectate-paused-on {
    color: var(--col-divine, #c9a84c);
    border-color: rgba(201,168,76,0.55);
    background: rgba(201,168,76,0.18);
    box-shadow: 0 0 8px rgba(201,168,76,0.45);
}

#spectate-pause-indicator {
    position: fixed;
    left: 50%;
    bottom: 52px;
    transform: translateX(-50%);
    z-index: 9500;
    padding: 8px 16px;
    border-radius: 999px;
    border: 1px solid rgba(201,168,76,0.5);
    background: rgba(28,33,48,0.94);
    color: var(--col-divine, #c9a84c);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    cursor: pointer;
    box-shadow: 0 4px 18px rgba(0,0,0,0.45), 0 0 14px rgba(201,168,76,0.3);
    animation: spectate-pause-pulse 1.8s ease-in-out infinite;
}
#spectate-pause-indicator:hover { background: rgba(40,46,64,0.98); }
@keyframes spectate-pause-pulse {
    0%,100% { box-shadow: 0 4px 18px rgba(0,0,0,0.45), 0 0 10px rgba(201,168,76,0.25); }
    50%     { box-shadow: 0 4px 18px rgba(0,0,0,0.45), 0 0 20px rgba(201,168,76,0.55); }
}
@media (prefers-reduced-motion: reduce) {
    #spectate-pause-indicator { animation: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   GAME-LIKE EFFECTS (MTG-Arena-style juice) — per-user, live-toggled.
   Master switch is a <body> class: fx-off / fx-subtle / fx-full (set by
   GameUI._applyEffectsMode). Every rule below is scoped under fx-subtle/fx-full
   so "off" is a TRUE bypass — none of this touches the baseline board. The JS
   also only ADDS the trigger classes (.fx-enter/.fx-tap/…) when effects are on,
   and prefers-reduced-motion neutralises the heavy layer (see the guard at the
   end). transform/opacity only; particles live on a separate canvas overlay.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Themed accent used by the particle bursts + glows (reused theme colours). */
:root                     { --fx-accent: #f0d07a; }
body.theme-chr            { --fx-accent: #f0d07a; }
body.theme-romanwar       { --fx-accent: #d4af37; }
body.theme-kittens        { --fx-accent: #f2a65a; }
body.theme-plantlover     { --fx-accent: #7ec850; }
body.theme-blockbuilding  { --fx-accent: #f0b429; }

/* The corner-menu toggle button GameUI injects. Inherits .btn-icon; the state
   classes tint the sparkle so the current mode reads at a glance. */
.phase-bar-btns .effects-toggle { font-weight: 700; }
.phase-bar-btns .effects-toggle.fx-toggle-off    { opacity: 0.4; filter: grayscale(1); }
.phase-bar-btns .effects-toggle.fx-toggle-subtle { opacity: 0.8; }
.phase-bar-btns .effects-toggle.fx-toggle-full   { opacity: 1; text-shadow: 0 0 8px var(--fx-accent); }

/* Bot / auto-drive ACTION-SPEED toggle (🐢 Slow / ▶ Normal / ⏩ Fast). Inherits
   .btn-icon; the state class tints the glyph so the current pace reads at a
   glance — Fast (opt-in) glows, Slow dims. */
.phase-bar-btns .botspeed-toggle { font-weight: 700; }
.phase-bar-btns .botspeed-toggle.botspeed-slow   { opacity: 0.7; }
.phase-bar-btns .botspeed-toggle.botspeed-normal { opacity: 1; }
.phase-bar-btns .botspeed-toggle.botspeed-fast   { opacity: 1; color: var(--col-divine); text-shadow: 0 0 8px rgba(201,168,76,0.6); }

/* Fire-and-forget particle canvas — full-viewport, never intercepts input. */
.fx-particle-canvas {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 9998;              /* above the board, below modals/overlays */
}

/* ── Card play: arc from hand + settle with weight ─────────────────────────
   translate + scale + slight rotate → overshoot → settle. transform/opacity
   only; the tile is fully interactive the whole time (no pointer-events lock). */
body.fx-subtle .card-tile.fx-enter,
body.fx-full   .card-tile.fx-enter {
    animation: fxCardEnter 0.44s cubic-bezier(0.22, 1.2, 0.36, 1) both;
    z-index: 6;
}
@keyframes fxCardEnter {
    0%   { transform: translateY(-24px) scale(0.62) rotate(-7deg); opacity: 0; }
    55%  { transform: translateY(3px)   scale(1.06) rotate(1.5deg); opacity: 1; }
    78%  { transform: translateY(-1px)  scale(0.985) rotate(-0.5deg); }
    100% { transform: translateY(0)     scale(1)     rotate(0deg); opacity: 1; }
}

/* ── Card feel: tap / rotate spin when a card rotates ──────────────────────
   Runs on top of the .rotated end-state (rotate(90deg)); the keyframe just
   adds a little wind-up so the flip has motion. */
body.fx-subtle .card-tile.fx-tap,
body.fx-full   .card-tile.fx-tap {
    animation: fxCardTap 0.34s cubic-bezier(0.34, 1.4, 0.5, 1) both;
}
@keyframes fxCardTap {
    0%   { transform: rotate(0deg)   scale(1); }
    45%  { transform: rotate(52deg)  scale(0.95); }
    100% { transform: rotate(90deg)  scale(1); }
}

/* ── Card feel: stronger hover-LIFT on your hand cards (on top of baseline) ─ */
body.fx-full [id$="-hand"] .card-tile:hover {
    box-shadow:
        0 16px 34px rgba(0,0,0,0.75),
        0 0 0 1px var(--fx-accent),
        0 0 20px color-mix(in srgb, var(--fx-accent) 45%, transparent);
}

/* ── Big moment: Maturity level-up pip pop + badge glow ────────────────────*/
body.fx-subtle .stat-pip.fx-pip-pop,
body.fx-full   .stat-pip.fx-pip-pop {
    animation: fxPipPop 0.6s cubic-bezier(0.3, 1.5, 0.5, 1) both;
}
@keyframes fxPipPop {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.9); filter: drop-shadow(0 0 6px var(--fx-accent)); }
    100% { transform: scale(1); }
}
body.fx-subtle .stat-badge.fx-levelup,
body.fx-full   .stat-badge.fx-levelup {
    animation: fxLevelGlow 0.9s ease-out both;
}
@keyframes fxLevelGlow {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--fx-accent) 60%, transparent); }
    35%  { box-shadow: 0 0 14px 3px color-mix(in srgb, var(--fx-accent) 55%, transparent); }
    100% { box-shadow: 0 0 0 0 rgba(0,0,0,0); }
}
/* Power JOLT: the Humility/Power badge zaps green (gain) or red (loss). */
.stat-badge.fx-stat-jolt-up   { animation: fxJoltUp   .72s ease-out both; }
.stat-badge.fx-stat-jolt-down { animation: fxJoltDown .72s ease-out both; }
@keyframes fxJoltUp {
    0%   { box-shadow: 0 0 0 0 rgba(124,252,152,0);   transform: scale(1); }
    28%  { box-shadow: 0 0 20px 4px rgba(124,252,152,.9); transform: scale(1.13); }
    100% { box-shadow: 0 0 0 0 rgba(124,252,152,0);   transform: scale(1); }
}
@keyframes fxJoltDown {
    0%   { box-shadow: 0 0 0 0 rgba(255,122,107,0);   transform: scale(1); }
    28%  { box-shadow: 0 0 20px 4px rgba(255,122,107,.9); transform: scale(1.11); }
    100% { box-shadow: 0 0 0 0 rgba(255,122,107,0);   transform: scale(1); }
}

/* ── Smooth phase / turn transitions (cross-fade the active phase step) ────*/
body.fx-subtle .phase-step,
body.fx-full   .phase-step {
    transition: color 0.3s ease, background 0.3s ease, transform 0.3s cubic-bezier(0.34,1.3,0.5,1), opacity 0.3s ease;
}
body.fx-full .phase-step.active {
    transform: translateY(-1px) scale(1.04);
}

/* ── Themed accent flourishes (subtle) ─────────────────────────────────────
   chr golden shimmer / kittens warm-paw glow as a card settles into play. */
body.fx-full.theme-chr .card-tile.fx-enter::after,
body.fx-full.theme-kittens .card-tile.fx-enter::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: radial-gradient(circle at 50% 40%, color-mix(in srgb, var(--fx-accent) 55%, transparent), transparent 70%);
    animation: fxShimmer 0.5s ease-out both;
}
@keyframes fxShimmer {
    0%   { opacity: 0.75; }
    100% { opacity: 0; }
}

/* ── reduced-motion guard: neutralise the heavy layer even if a user forced
   effects ON (default already follows the system). ─────────────────────────*/
@media (prefers-reduced-motion: reduce) {
    body.fx-subtle .card-tile.fx-enter,
    body.fx-full   .card-tile.fx-enter,
    body.fx-subtle .card-tile.fx-tap,
    body.fx-full   .card-tile.fx-tap,
    body.fx-subtle .stat-pip.fx-pip-pop,
    body.fx-full   .stat-pip.fx-pip-pop,
    body.fx-subtle .stat-badge.fx-levelup,
    body.fx-full   .stat-badge.fx-levelup,
    body.fx-full   .card-tile.fx-enter::after,
    body.fx-subtle .phase-step,
    body.fx-full   .phase-step { animation: none !important; transition: none !important; }
    .fx-particle-canvas { display: none !important; }
}

/* ── Threat-target arrows: pending evil card → the player it targets ───── */
.kcc-threat-line { animation: kccThreatDash 1.2s linear infinite; }
@keyframes kccThreatDash { to { stroke-dashoffset: -24; } }
@media (prefers-reduced-motion: reduce) { .kcc-threat-line { animation: none; } }
.threat-target-glow {
    outline: 2px solid rgba(224,96,63,.75) !important;
    outline-offset: -2px;
    border-radius: 10px;
    animation: kccThreatGlow 1.6s ease-in-out infinite;
}
@keyframes kccThreatGlow {
    0%, 100% { outline-color: rgba(224,96,63,.75); }
    50%      { outline-color: rgba(224,96,63,.30); }
}
@media (prefers-reduced-motion: reduce) { .threat-target-glow { animation: none; } }

/* ── Phase chip on the active player's area (kcc.phasePos default) ─────── */
body.kcc-phase-anchored #turn-banner,
body.kcc-phase-anchored #phase-track { display: none !important; }
#kcc-phase-chip {
    position: fixed; z-index: 1300;
    pointer-events: auto; cursor: grab; touch-action: none; user-select: none;
    display: flex; align-items: center; gap: 8px;
    background: rgba(13,11,8,.95); border: 1.5px solid rgba(240,199,96,.85);
    border-radius: 999px; padding: 5px 13px;
    color: #f4e2ab; font: 600 13px/1.3 system-ui, sans-serif;
    box-shadow: 0 3px 14px rgba(0,0,0,.55);
}
#kcc-phase-chip.dragging { cursor: grabbing; opacity: .9; box-shadow: 0 6px 22px rgba(0,0,0,.7); }
/* Phase-advance button living inside the active player's docked chip. Compact
   pill; carries its own pointer-events so a click advances (not drags the chip). */
#kcc-phase-chip .pc-advance {
    pointer-events: auto; cursor: pointer;
    margin-left: 4px; padding: 5px 12px; border-radius: 999px;
    border: 1px solid rgba(240,199,96,.6);
    background: linear-gradient(180deg, rgba(240,208,122,.95), rgba(201,168,76,.95));
    color: #1a1408; font: 800 12px/1 system-ui, sans-serif; white-space: nowrap;
    box-shadow: 0 1px 5px rgba(0,0,0,.4);
}
#kcc-phase-chip .pc-advance:hover { filter: brightness(1.08); }
#kcc-phase-chip .pc-advance.btn-blocked {
    background: linear-gradient(180deg, rgba(120,60,50,.9), rgba(90,40,34,.9));
    color: #f0d0c8; border-color: rgba(200,90,70,.5);
}
.kcc-phase-menu {
    position: fixed; z-index: 13050; min-width: 176px;
    background: rgba(13,11,8,.98); border: 1.5px solid rgba(240,199,96,.75);
    border-radius: 10px; padding: 5px; box-shadow: 0 10px 34px rgba(0,0,0,.7);
    font: 600 13px/1.3 system-ui, sans-serif; color: #f4e2ab;
}
.kcc-phase-menu button {
    display: block; width: 100%; text-align: left; background: none; border: 0;
    color: inherit; font: inherit; padding: 8px 10px; border-radius: 7px; cursor: pointer;
}
.kcc-phase-menu button:hover { background: rgba(240,199,96,.16); }
.kcc-phase-menu button.on { color: #ffd977; }
.kcc-phase-menu-sep { height: 1px; margin: 5px 4px; background: rgba(240,199,96,.25); }
/* Online connection-quality widget (top-right). */
#kcc-conn {
    position: fixed; top: 8px; right: 10px; z-index: 12000;
    display: inline-flex; align-items: center; gap: 6px;
    background: rgba(13,11,8,.85); border: 1px solid rgba(255,255,255,.15);
    border-radius: 999px; padding: 4px 11px 4px 9px;
    font: 600 12px/1 system-ui, sans-serif; color: #e8e0cf;
    pointer-events: auto; user-select: none;
}
#kcc-conn .cc-dot { width: 9px; height: 9px; border-radius: 50%; box-shadow: 0 0 6px currentColor; flex: 0 0 auto; }
#kcc-conn.green  { color: #7bd88f; }
#kcc-conn.yellow { color: #f0d07a; }
#kcc-conn.red    { color: #e0685c; }
#kcc-conn .cc-users, #kcc-conn .cc-ping { color: #e8e0cf; }
/* Shared-gaze host toggle (under the connection pill). */
#kcc-gaze-toggle {
    position: fixed; top: 36px; right: 10px; z-index: 12000;
    background: rgba(13,11,8,.85); border: 1px solid rgba(127,178,255,.5);
    border-radius: 999px; padding: 3px 11px; cursor: pointer;
    font: 700 11px/1 system-ui, sans-serif; color: #a9c9ff;
}
#kcc-gaze-toggle.off { border-color: rgba(255,255,255,.2); color: #9c9488; }
/* A card a remote player is currently examining — glow ring + name badge, gentle
   pulse. Uses filter (not transform) so it never fights the card's own tilt. */
.card-tile.peer-looking {
    box-shadow: 0 0 0 2px var(--peer-color, #7fb2ff), 0 6px 22px rgba(0,0,0,.5) !important;
    z-index: 40 !important;
    animation: kccPeerGlow 1.3s ease-in-out infinite;
}
@keyframes kccPeerGlow { 0%,100% { filter: brightness(1); } 50% { filter: brightness(1.18); } }
.card-tile.peer-looking::after {
    content: '👁 ' attr(data-peer);
    position: absolute; top: -14px; left: 50%; transform: translateX(-50%);
    background: var(--peer-color, #7fb2ff); color: #10131a;
    font: 700 9px/1.5 system-ui, sans-serif; padding: 1px 6px; border-radius: 7px;
    white-space: nowrap; pointer-events: none; z-index: 41;
}
/* A whole ZONE/AREA a remote player is examining — subtle inset ring + tinted
   wash + a name badge in the corner. Lighter than the card glow so it reads as
   "looking around here" rather than "looking at this exact card". */
.peer-looking-zone {
    position: relative;
    box-shadow: inset 0 0 0 2px var(--peer-color, #7fb2ff), inset 0 0 24px -6px var(--peer-color, #7fb2ff) !important;
    border-radius: 6px;
    transition: box-shadow .15s ease;
}
.peer-looking-zone::after {
    content: '👁 ' attr(data-peer);
    position: absolute; top: 2px; right: 4px;
    background: var(--peer-color, #7fb2ff); color: #10131a;
    font: 700 9px/1.5 system-ui, sans-serif; padding: 0 6px; border-radius: 7px;
    white-space: nowrap; pointer-events: none; z-index: 41;
    opacity: .92;
}
#kcc-phase-chip b { color: #ffd977; }
#kcc-phase-chip .pc-round { opacity: .7; font-size: 11.5px; }
#kcc-phase-chip .pc-phase { border-left: 1px solid rgba(240,199,96,.4); padding-left: 8px; }

/* ── Playmat quadrant splitters ────────────────────────────────────────── */
.pg-splitter { position: absolute; z-index: 30; touch-action: none; }
.pg-splitter-v { top: 0; bottom: 0; width: 8px; cursor: col-resize; }
.pg-splitter-h { left: 0; right: 0; height: 8px; cursor: row-resize; }
.pg-splitter:hover { background: rgba(201,168,76,.28); border-radius: 4px; }

/* Phase-chip mini track */
#kcc-phase-chip .pc-steps { display: inline-flex; gap: 2px; margin-left: 4px; }
#kcc-phase-chip .pc-step { display: inline-flex; align-items: center; gap: 3px; padding: 2px 7px;
    border-radius: 999px; opacity: .45; font-size: 12px; }
#kcc-phase-chip .pc-step i { font-style: normal; font-size: 10.5px; letter-spacing: .04em; }
#kcc-phase-chip .pc-step.on { opacity: 1; background: rgba(240,199,96,.22);
    outline: 1px solid rgba(240,199,96,.7); }

/* Source-zone badge in card pickers (multi-zone searches) */
.pick-card .pick-zone-badge {
    display: inline-block; margin-left: 7px; padding: 1px 8px; border-radius: 999px;
    font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    background: rgba(201,168,76,.2); border: 1px solid rgba(201,168,76,.5); color: #f0d07a;
    vertical-align: middle;
}
