/* ── Aurora Components — visual skin for reused/relocated markup ────────────
   Layout geometry lives in aurora-table.css; this file is color, type, and
   the micro-motion layer. All color reuses table-theme.css tokens — no new
   palette. The existing global `@media (prefers-reduced-motion: reduce) { *
   { animation-duration:0.01ms!important; transition-duration:0.01ms!important } }`
   rule (style.css) already blankets every rule below; nothing extra needed here.
──────────────────────────────────────────────────────────────────────────── */

/* ── Game DNA Bar ── */
.aurora-dna-bar {
  background: rgba(0,0,0,0.5);
  border-bottom: 1px solid var(--tt-gold-dim);
}
.aurora-dna-left .brand { font-size: 0.78rem; }
/* Owner ruling 2026-07-17: these four were redundant in the DNA bar —
   #streetBadge duplicated the "WAITING" state nobody needed a label for,
   #histBtn's "#N" hand counter had no use yet, #modeToggle's "Bomb Pot"
   repeated what the center dropdown already says, and #playerCount's
   "N-handed" was already fixed at game setup. Hidden here (not removed from
   the DOM) — they're still moved into this bar by reparentDnaBar() and still
   read/written by their own app.js logic (#streetBadge drives street state,
   #histBtn opens hand history, #modeToggle is a live practice-mode toggle,
   #playerCount.value is read for seat count) — only the visible badge goes
   away, restorable later with a one-line revert if any of it's wanted back. */
.aurora-dna-bar #streetBadge,
.aurora-dna-bar #histBtn,
.aurora-dna-bar #modeToggle,
.aurora-dna-bar #playerCount {
  display: none;
}
.aurora-dna-center {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--tt-gold);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  user-select: none;
  min-width: 0;
  /* Capped so it can't dominate the bar now that the redundant badges beside
     it (WAITING/#N/Bomb Pot/N-handed, above) are hidden and would otherwise
     free up enough flex:1 space for this to stretch wide — owner ruling
     2026-07-17: allocate it a fixed budget, ellipsize (.aurora-dna-label)
     past that, same as before. */
  max-width: min(280px, 100%);
}
.aurora-dna-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.aurora-dna-chevron {
  font-size: 0.6rem;
  color: var(--tt-gold-dim, var(--tt-gold));
  transition: transform var(--mo-fast, 120ms) var(--mo-ease, ease);
  flex-shrink: 0;
}
.aurora-dna-center.is-open .aurora-dna-chevron {
  transform: rotate(180deg);
}
.aurora-dna-right .btn-new { padding: 5px 14px; font-size: 0.72rem; }

/* ── Game Info Panel — collapsible popover under the DNA bar ─────────────
   Anchored as an overlay (not a grid column) so it never reshapes the
   board-stage/dock grid; toggled from the DNA center label. */
.aurora-info-panel {
  position: fixed;
  z-index: 95;
  top: calc(var(--aur-dna-h) + var(--aur-safe-t) + 6px);
  left: calc(14px + var(--aur-safe-l));
  width: min(240px, 70vw);
  padding: 12px 14px 10px;
  border-radius: 14px;
  border: 1px solid rgba(201,160,74,.42);
  background: linear-gradient(180deg, rgba(12,19,29,.98), rgba(5,9,15,.98));
  box-shadow: 0 14px 30px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.04);
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity var(--mo-med, 160ms) var(--mo-ease, ease), transform var(--mo-med, 160ms) var(--mo-ease, ease);
}
.aurora-info-panel.is-open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.aur-info-title {
  color: #f5e8bd;
  font-weight: 800;
  font-size: 0.82rem;
  letter-spacing: 0.03em;
  margin-bottom: 6px;
}
.aur-info-row {
  font-size: 0.72rem;
  color: rgba(238,244,255,.88);
  padding: 3px 0;
}
.aur-info-positive { color: #7fe0a8; }
.aur-info-muted { color: var(--muted, #91a0ad); font-size: 0.66rem; }
.aur-info-divider { height: 1px; background: rgba(201,160,74,.24); margin: 6px 0; }

/* The existing inline .d-badge stays in the DOM as-is (app.js's own dealer
   state, untouched — updateDealerPuck() reads its `hidden` property, not
   its CSS visibility) and visually steps aside once Aurora's premium puck
   is the one dealer indicator on screen; showing both produced two markers
   overlapping each other and the hero's stack text (caught in Phase 1
   screenshot review). visibility:hidden, not display:none — the badge's
   own getBoundingClientRect() is what positions the puck, and a
   display:none element collapses to a zero-size rect at (0,0), which sent
   the puck to the viewport's top-left corner (also caught in review). */
body.aurora-gameplay-active .d-badge { visibility: hidden; }

/* app.js's updateTimer() writes the hero's countdown to two places: the
   moved #timerWrap (kept — now lives in the hero-id slot) and a legacy
   echo badge, #heroSeatTimer, "pinned to hero seat card" for the old
   portrait layout. That badge is position:absolute; top:-10px; right:-10px
   relative to .seat--hero, which Aurora's grid stretches to fill a wide
   center column — so the badge rendered far from the hero row, at the now
   much wider box's real edge (caught as an unexplained floating green
   circle in Phase 1 screenshot review). #timerWrap already covers "timer
   near hero identity" here, so the echo is redundant, not just misplaced;
   nothing reads its state, so hiding it is safe. */
body.aurora-gameplay-active #heroSeatTimer { display: none; }

/* ── Dealer puck — premium physical chip, never a flat saturated circle ── */
.aurora-puck {
  width: var(--aur-puck-size);
  height: var(--aur-puck-size);
  border-radius: 50%;
  background: var(--tt-dealer-bg);
  color: var(--tt-dealer-text);
  border: 1.5px solid var(--tt-dealer-border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  box-shadow: 0 2px 5px rgba(0,0,0,0.45), 0 0 0 1px rgba(255,255,255,0.15) inset;
  transition: left var(--mo-slow) var(--mo-ease), top var(--mo-slow) var(--mo-ease);
}
.aurora-puck[hidden] { display: none; }

/* ── Per-seat "acting" timer ring — hero keeps the real #timerWrap (moved,
   unchanged, into the hero-id slot); this ring is Aurora-only, for whichever
   opponent seat is currently acting. Sits on the seat pill's corner so it
   reads as attached to that player, not a floating widget. ── */
.aurora-seat-timer {
  position: absolute;
  top: -6px;
  right: -6px;
  width: var(--aur-seat-timer-size);
  height: var(--aur-seat-timer-size);
  display: none;
  z-index: 32;
  pointer-events: none;
}
.aurora-seat-timer.show { display: block; }
.aur-tsv { width: 100%; height: 100%; transform: rotate(-90deg); display: block; }
.aur-t-bg   { fill: none; stroke: var(--tt-timer-track); stroke-width: 3; }
.aur-t-ring {
  fill: none;
  stroke: var(--tt-timer-normal);
  stroke-width: 3;
  stroke-linecap: round;
  transition: stroke-dashoffset var(--mo-fast) linear;
}
.aurora-seat-timer.warn   .aur-t-ring { stroke: var(--tt-timer-warn); }
.aurora-seat-timer.urgent .aur-t-ring { stroke: var(--tt-timer-urgent); }

/* Practice-mode AI turns have no real deadline (see app.js's Bet._onTurn) —
   an indeterminate sweep is the honest representation, not a fabricated
   countdown. A short arc travels the ring rather than filling/draining it. */
.aurora-seat-timer.thinking .aur-t-ring {
  stroke-dasharray: 20 61.68;
  animation: aurThinkingSweep 1.1s linear infinite;
}
@keyframes aurThinkingSweep { to { stroke-dashoffset: -81.68; } }


/* ── Context Dock states ──────────────────────────────────────────────────
   #actionBtns/#raiseSizing keep their own existing .hidden-class visibility
   (driven by showBtns/hideBtns, unrelated to this file) regardless of which
   DOM parent they sit in — moving them doesn't change when they show.
   Coach content (.coach-left/#coachChips) lost its old visibility source
   when it was reparented out of the now-empty #coachBar shell, so it needs
   an explicit rule here: hidden when Coach is off, or while an opponent
   is acting (context goes quiet, per the "Opponent Turn: observe, not act"
   spec) — but stays visible during the hero's own turn, since that's when
   the coach's explanatory advice matters most. */
.aurora-context-dock {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 4px;
  padding: 4px 2px;
  min-height: 1px; /* Coach OFF + waiting: no ugly empty strip, just zero content */
  /* Safety net, not the primary fit: the compacted raise-sizing/action-btns
     above fit the dock's grid row without scrolling at common landscape
     phone sizes (verified), but the narrowest/shortest real device class
     (iPhone SE landscape, 667×375) still needs more height than a ~190px
     column can give a slider + min/max row + confirm button without
     wrapping past it. Rather than keep shrinking touch targets below a
     usable size to chase every device height, let the dock scroll
     internally so controls stay fully reachable — never invisible, never
     spilling past the viewport — on whatever device actually renders it. */
  max-height: 100%;
  overflow-y: auto;
}
.aurora-context-dock .coach-left,
.aurora-context-dock #coachChips {
  transition: opacity var(--mo-med) var(--mo-ease);
}
.aurora-context-dock:not(.aurora-coach-on) .coach-left,
.aurora-context-dock:not(.aurora-coach-on) #coachChips,
.aurora-context-dock[data-state="opponent-turn"] .coach-left,
.aurora-context-dock[data-state="opponent-turn"] #coachChips {
  display: none;
}
.aurora-context-dock #actionBtns,
.aurora-context-dock #raiseSizing {
  transition: opacity var(--mo-med) var(--mo-ease);
}

/* The dock column is ~250px wide — far narrower than the old full-width
   footer bar #raiseSizing/#actionBtns were designed for, so their content
   wraps across two rows and needs compacting to actually fit the dock's
   height budget (measured via Puppeteer, not guessed: at default sizing
   this content overflowed the dock's box and spilled past the bottom of
   the viewport). Presentation only — no change to slider min/max/step,
   raise amounts, or click targets below the 44px iOS minimum. */
.aurora-context-dock #raiseSizing {
  gap: 2px;
  margin-bottom: 0;
  max-width: none;
}
.aurora-context-dock .raise-slider-row { gap: 6px; }
.aurora-context-dock #raiseSlider { height: 20px; }
.aurora-context-dock .raise-amt { font-size: 0.68rem; min-width: 34px; }
.aurora-context-dock .raise-minmax-row { font-size: 0.6rem; }
.aurora-context-dock .raise-back { flex-basis: 40px; min-height: 44px; font-size: 0.88rem; }
.aurora-context-dock .raise-confirm { padding: 8px 12px; font-size: 0.74rem; min-width: 60px; }
.aurora-context-dock #actionBtns { gap: 5px; justify-content: flex-end; }
.aurora-context-dock .btn-act {
  padding: 8px 12px;
  font-size: 0.74rem;
  min-width: 60px;
  min-height: 44px; /* iOS minimum tap target — unchanged from the base rule */
}

/* #coachChips's base rule (style.css) is flex-shrink:0 with no wrap — fine
   in the old full-width footer, but in the ~250px dock it forced one long
   unbroken chip row. .aurora-context-dock right-aligns its children
   (align-items:flex-end), so an over-wide row pushed its own LEFT portion
   past the dock's left edge instead of clipping predictably on the right
   (caught in screenshot review — chip text was cut off on the left, not
   the right, which is what gave away the actual cause). Wrapping keeps
   every chip fully visible. */
.aurora-context-dock #coachChips {
  flex-wrap: wrap;
  justify-content: flex-end;
  max-width: 100%;
}
.aurora-context-dock .pt-chip { font-size: 0.6rem; padding: 2px 6px; }

/* .coach-text's own ellipsis truncation (style.css) only engages once its
   flex ancestor is actually width-constrained — .aurora-context-dock's
   align-items:flex-end lets flex children size to their own content
   instead of stretching to the dock's width, so without this the advice
   line just grew as wide as the sentence needed instead of truncating. */
.aurora-context-dock .coach-left { max-width: 100%; }

/* ── Orientation gate ── */
.aurora-orientation-gate {
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  background: radial-gradient(ellipse at 50% 40%, var(--tt-felt-hi) 0%, var(--tt-felt-lo) 100%);
  text-align: center;
  color: var(--text);
  /* Portrait-only surface, so only top/bottom insets are realistically ever
     non-zero here (left/right come into play in landscape, where this
     never renders) — padded anyway since iOS reports safe-area-inset
     relative to the physical device, not a guaranteed-portrait layout. */
  padding-top: max(24px, var(--aur-safe-t));
  padding-right: max(24px, var(--aur-safe-r));
  padding-bottom: max(24px, var(--aur-safe-b));
  padding-left: max(24px, var(--aur-safe-l));
  box-sizing: border-box;
  overflow: hidden;
}
.aurora-gate-brand {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--tt-gold);
  opacity: 0.85;
}
.aurora-gate-icon {
  width: 56px;
  height: 84px;
  border: 3px solid var(--tt-gold);
  border-radius: 10px;
  position: relative;
  animation: aurGateRotate 2.4s var(--mo-ease-inout) infinite;
}
.aurora-gate-icon::after {
  content: '';
  position: absolute;
  bottom: 8px;
  left: 50%;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--tt-gold-dim);
  transform: translateX(-50%);
}
@keyframes aurGateRotate {
  0%, 15%  { transform: rotate(0deg); }
  50%, 65% { transform: rotate(90deg); }
  100%     { transform: rotate(90deg); }
}
@media (prefers-reduced-motion: reduce) {
  /* The rotate animation is a supplementary visual, not the sole way to
     understand the instruction — auroraGateTitle/Sub text carries the full
     meaning on its own — so it's safe to just freeze it here. */
  .aurora-gate-icon { animation: none; transform: rotate(90deg); }
}
.aurora-gate-title { font-size: 1.05rem; font-weight: 700; margin: 0; max-width: 280px; }
.aurora-gate-sub { font-size: 0.8rem; color: var(--muted); margin: 0; max-width: 280px; line-height: 1.5; }

/* ══════════════════════════════════════════════════════════════════════════
   AURORA ITERATION 2 — premium component hierarchy
   Scoped to active landscape gameplay only (body.aurora-gameplay-active +
   @media orientation:landscape) — portrait, lobby, setup and waiting
   screens are untouched, unlike Premium V4's bare .opp-pill/.hero-zone/
   .hero-avatar selectors, which applied everywhere.
   ══════════════════════════════════════════════════════════════════════════ */
@media (orientation: landscape) {
  /* Aurora Max pod treatment (aurora-max-design-tokens.css's
     .aurora-max-player-pod, adapted): richer gradient/shadow depth via
     --tt-shadow-pod, border-radius nudged 14->16px. Width/min-height stay
     the existing Puppeteer-tuned clamp() values, NOT the design package's
     own --aur-pod-w/--aur-pod-h (clamp(108-178px) / clamp(44-74px)) — those
     were sized for the standalone concept mockup's less-crowded composition
     and would very likely reopen the 6/7/8-handed board-overlap bug LAYOUTS
     was specifically built to fix (see aurora-table.js's LAYOUTS comment).
     Re-theme, not re-geometry, per the rebuild package's own priority: card
     readability and no-overlap outrank decorative sizing. */
  body.aurora-gameplay-active .opp-pill {
    width: clamp(68px, 7.2vw, 86px);
    min-width: clamp(68px, 7.2vw, 86px);
    min-height: 46px;
    padding: 4px 6px 5px;
    border-radius: 16px;
    background: linear-gradient(180deg, rgba(20,25,24,.96), rgba(8,10,9,.98));
    border: 1px solid var(--tt-gold-dim);
    box-shadow: var(--tt-shadow-pod), inset 0 1px 0 rgba(255,255,255,.07);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }

  body.aurora-gameplay-active .opp-pill .pill-top {
    flex-direction: column;
    gap: 1px;
  }

  /* Aurora Table Geometry v2 (2026-07-23), Rule 6: avatars shrink before
     text — was clamp(32px,3.2vw,40px). Pod itself, name/stack text size,
     and layout are untouched (directive 1.3: "do not redesign them"). */
  body.aurora-gameplay-active .opp-pill .pill-avatar {
    width: clamp(22px, 2.2vw, 28px);
    height: clamp(22px, 2.2vw, 28px);
    margin-top: -18px;
    border: 2px solid var(--tt-gold);
    box-shadow: 0 0 0 3px rgba(6,11,17,.95), 0 5px 13px rgba(0,0,0,.46);
  }

  body.aurora-gameplay-active .opp-pill .pill-name {
    display: block;
    max-width: 72px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: .66rem;
    line-height: 1.1;
  }

  body.aurora-gameplay-active .opp-pill .pill-stack {
    margin-top: 1px;
    font-size: .57rem;
    color: rgba(245,232,189,.88);
  }

  body.aurora-gameplay-active .opp-pill .pill-bet {
    font-size: .54rem;
  }

  /* Dealing-beat face-down backs (style.css's .pill-cards--backs, shown only
     while body.aurora-hand-dealing) must not add to the pod's own box
     height. In normal flow they do — measured via Puppeteer: 95px pod
     during dealing vs 50px at rest, a ~45px swing — and since layoutSeats()
     (aurora-table.js) centers every seat with translate(-50%,-50%) at a
     fixed y%, that swing pushes the pod visibly deeper into the felt for
     the ~1-2s dealing plays out, before it snaps back up once the backs
     hide again. This was invisible before the seat-arc flatten (fbafee0,
     2026-07-22) — the arc row still had 54-82px of spare headroom above the
     felt for seats to grow into. Flattening shrank that headroom to
     6-14px specifically because no seat was expected to need it any
     more — nobody had checked the transient mid-deal state against the new
     zero-slack budget, only the resting one. height:0 + overflow:visible
     keeps the two card-back glyphs visually in place (they still paint,
     just outside their own box) while contributing nothing to the pod's
     auto height, so the pod's rendered size — and thus its centered
     position — stays constant through the entire dealing beat. */
  body.aurora-gameplay-active .opp-pill .pill-cards.pill-cards--backs {
    height: 0;
    margin-top: 0;
    overflow: visible;
  }

  body.aurora-gameplay-active .opp-pill.is-active {
    background: linear-gradient(180deg, rgba(29,35,43,.98), rgba(8,12,17,.97));
    border-color: rgba(232,209,143,.76);
    box-shadow: 0 0 0 1px rgba(232,209,143,.19), 0 0 20px rgba(201,160,74,.28), 0 9px 24px rgba(0,0,0,.48);
  }

  /* 2026-07-23: was width:min(100%,430px) — a flat cap with zero relationship
     to the felt's real width (measured 632-794px across real devices in the
     table-geometry validation pack). #seat-hero's grid-column already gives
     100% the correct value (aurora-table.css), so the cap was only ever
     throwing away real rail-to-rail width the hero-card fan could use — see
     MEMORY hero-fan-should-use-rail-width-not-fixed-cap. app.js's
     heroFanAvailWidth()/heroCardWidth()/fanMetrics() now size the fan from
     this box's real measured width instead of a viewport-width guess, so
     this rule just needs to stop re-capping what they measure. */
  body.aurora-gameplay-active .app .hero-zone,
  body.aurora-gameplay-active .app .seat-card.cd-hero {
    width: 100%;
    margin-inline: auto;
    padding: 0 8px 3px;
    gap: 4px;
    border: 0;
    background: transparent;
    box-shadow: none;
  }

  /* ESG cards sit beside the hand fan, in their own horizontal strip, rather
     than stacked underneath — matches the premium-table prototype's
     dedicated ESG region. .hero-id keeps its own full-width row on top by
     wrapping onto flex-basis:100%; .hand-fan--hero/.esg-row then share the
     row below it. Pure layout — buildHeroZone()'s markup/order is untouched. */
  body.aurora-gameplay-active .app .hero-zone {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: center;
  }
  body.aurora-gameplay-active .app .hero-zone .hero-id {
    flex-basis: 100%;
    justify-content: center;
  }
  body.aurora-gameplay-active .app .hero-zone .esg-row {
    margin-top: 0;
    margin-left: 6px;
    padding-left: 8px;
    border-left: 1px solid rgba(201,160,74,.28);
    flex-wrap: nowrap;
  }

  body.aurora-gameplay-active .app .hero-id,
  body.aurora-gameplay-active .app .cd-hero-head {
    border-radius: 999px;
    background: linear-gradient(180deg, rgba(20,25,24,.97), rgba(8,10,9,.97));
    border: 1px solid var(--tt-gold-dim);
    box-shadow: var(--tt-shadow-pod), inset 0 1px 0 rgba(255,255,255,.035);
  }
  /* Split from the shared rule above (2026-07-23): .cd-hero-head (Countdown,
     never had an avatar to begin with) keeps its established 40px/4px-14px —
     untouched, out of this directive's scope. .hero-id's min-height/padding
     WAS sized to fit the 34px avatar; directive 3.2 ("reduce before shrinking
     hero cards: hero avatar [removed]... only then reduce hero cards") means
     that reclaimed space needs to actually reach heroFanAvailHeight(), not
     just get backfilled by an equally-tall replacement — see the shrunk
     .hero-id-timer-slot below, which is what makes this floor meaningful. */
  body.aurora-gameplay-active .app .cd-hero-head {
    min-height: 40px;
    padding: 4px 14px 4px 5px;
  }
  body.aurora-gameplay-active .app .hero-id {
    min-height: 28px;
    padding: 3px 12px 3px 4px;
  }

  /* Shrunk from 34px (avatar-matched) to 24px — genuinely reclaims row
     height for the hero cards rather than just relocating the same
     footprint (directive 3.2's actual point, not just 3.1's avatar removal
     on its own). #timerWrap's scale() below is retuned to match.
     2026-07-25: .hero-id-timer-slot is now a permanent wrapper (not a
     fleeting placeholder) — app.js/countdown-ui.js append the real
     #timerWrap *inside* it once, instead of replacing it. flex:none sizes
     the row's real flex footprint; overflow:hidden crops #timerWrap's own
     unscaled 42px box down to this element's real size, since scale()
     shrinks paint, not layout (applying scale() directly to an element
     that's ALSO been resized double-shrinks it — confirmed the hard way,
     first attempt rendered the timer at ~8px instead of 24px). */
  body.aurora-gameplay-active .app .hero-id-timer-slot {
    width: 24px;
    height: 24px;
    flex: none;
    overflow: hidden;
  }
  /* transform-origin: top left (not the default center) — with the parent
     above cropping via overflow:hidden, top-left keeps the *visible*
     (post-scale) portion anchored to the wrapper's own top-left corner,
     landing exactly inside its bounds instead of shrinking toward a center
     point that isn't the wrapper's center once cropped. */
  #timerWrap.aurora-hero-timer {
    transform: scale(0.571);
    transform-origin: top left;
  }

  /* .d-badge is visibility:hidden everywhere in Aurora (the puck replaces
     it, aurora-components.css above) — its size only matters as reserved
     flex-row footprint, invisible either way. At 20px it was actually the
     TALLEST child in .hero-id (taller than the just-shrunk timer-slot),
     silently capping the row's real height regardless of the avatar/timer
     work above — found via direct measurement, not assumed. Shrunk to
     match; still non-zero (never display:none — updateDealerPuck() centers
     the puck on this element's own rect, and a zero-size rect sends it to
     the viewport's top-left corner, a previously-fixed bug). Scoped to
     .hero-id only, not the shared base .d-badge rule opponent pods use too. */
  body.aurora-gameplay-active .app .hero-id .d-badge {
    width: 14px;
    height: 14px;
  }

  body.aurora-gameplay-active .app .hero-id strong,
  body.aurora-gameplay-active .app .cd-hero-head strong {
    font-size: .8rem;
  }

  body.aurora-gameplay-active .app .hero-chips,
  body.aurora-gameplay-active .app .cd-hero-stack {
    color: #f5e8bd;
    font-size: .72rem;
  }

  body.aurora-gameplay-active .app .hand-fan--hero {
    margin-top: -3px;
    filter: drop-shadow(0 10px 13px rgba(0,0,0,.32));
  }

  /* Card shadow only — width/height/border-radius/aspect ratio stay owned
     by each variant's own --cd-card-w/--f2-card-w/etc-driven rules (style.css,
     f2-ui.js et al), consistent with this file's "paint only" scope. */
  body.aurora-gameplay-active .app .board-card {
    box-shadow: var(--tt-shadow-card), inset 0 1px 0 rgba(255,255,255,.9);
  }

  body.aurora-gameplay-active .app .board-card.placeholder {
    opacity: .18;
    background: rgba(0,25,17,.18);
    border: 1px solid rgba(232,209,143,.16);
    box-shadow: inset 0 0 0 1px rgba(0,0,0,.08);
  }

  body.aurora-gameplay-active .app .felt-pot {
    padding: 3px 12px;
    font-size: .72rem;
    background: rgba(2,12,8,.6);
    border: 1px solid var(--tt-gold-dim);
    box-shadow: 0 4px 14px rgba(0,0,0,.34), inset 0 1px 0 rgba(255,255,255,.05);
  }

  /* Dealer Zone — a permanent felt station (aurora-table.css positions the
     outer .dealer-zone; this file is visual skinning only, per this file's
     own layout/skinning split). Understated on purpose (spec: "should not
     look like a ninth player avatar" / "remain visually subordinate to the
     board and players") — a faint felt-indentation tray, not a pod/badge.
     .dealer-zone__deck is a static 3-card stack reusing the existing
     card-back pattern (.mini-card.card-back, style.css) scaled up, per
     owner's 2026-07-16 direction: reuse the existing back design rather
     than a new asset. */
  body.aurora-gameplay-active .dealer-zone {
    border-radius: 40%;
    background: radial-gradient(circle, rgba(0,0,0,.30), transparent 72%);
    box-shadow: inset 0 1px 2px rgba(0,0,0,.35);
  }
  body.aurora-gameplay-active .dealer-zone__deck {
    position: relative;
    width: clamp(20px, 2.3vw, 30px);
    height: clamp(28px, 3.3vw, 43px);
  }
  body.aurora-gameplay-active .dealer-zone__deck .mini-card.card-back {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    box-shadow: var(--tt-shadow-card);
  }
  body.aurora-gameplay-active .dealer-zone__deck .mini-card.card-back:nth-child(1) { transform: translate(-2px, 1px) rotate(-3deg); }
  body.aurora-gameplay-active .dealer-zone__deck .mini-card.card-back:nth-child(2) { transform: translate(1px, 0) rotate(2deg); }
  body.aurora-gameplay-active .dealer-zone__deck .mini-card.card-back:nth-child(3) { transform: none; }

  /* Canonical F2: two four-card boards with one shared river at each side. */
  body.aurora-gameplay-active .community-cards.f2-board-v2 {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto auto;
    align-items: center;
    justify-items: center;
    column-gap: clamp(8px, 1.2vw, 16px);
    row-gap: clamp(8px, 1.6dvh, 14px);
    width: 100%;
  }

  body.aurora-gameplay-active .f2-board-v2 .f2-shared-river {
    grid-row: 1 / 3;
    align-self: center;
  }
  body.aurora-gameplay-active .f2-board-v2 .f2-shared-river--left { grid-column: 1; }
  body.aurora-gameplay-active .f2-board-v2 .f2-shared-river--right { grid-column: 3; }
  body.aurora-gameplay-active .f2-board-v2 .f2-live-row {
    grid-column: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(5px, .7vw, 9px);
  }
  body.aurora-gameplay-active .f2-board-v2 .f2-live-row--top { grid-row: 1; }
  body.aurora-gameplay-active .f2-board-v2 .f2-live-row--bottom { grid-row: 2; }

  body.aurora-gameplay-active .f2-board-v2 .board-card {
    width: var(--f2-card-w, 46px);
    height: calc(var(--f2-card-w, 46px) * 1.43);
    border-radius: calc(var(--f2-card-w, 46px) * .14);
  }
  body.aurora-gameplay-active .f2-board-v2 .board-card .c-rank { font-size: calc(var(--f2-card-w, 46px) * .42); }
  body.aurora-gameplay-active .f2-board-v2 .board-card .c-suit { font-size: calc(var(--f2-card-w, 46px) * .34); }
  body.aurora-gameplay-active .f2-board-v2 .f2-slot-name {
    color: rgba(245,232,189,.78);
    font-size: calc(var(--f2-card-w, 46px) * .25);
  }
}

/* Short landscape heights (390px and below) — the hero-id pod above the fan
   (body.aurora-gameplay-active .app .hero-id, ~40px min-height + a 34px
   avatar) still won every specificity fight against style.css's own
   max-height:420px shrink for those same properties, since this file's
   selectors here are all scoped under body.aurora-gameplay-active .app.
   Root cause of the hero-fan-runs-off-the-bottom bug (owner report
   2026-07-20): between this pod and the fan's own height, .hero-zone's
   actual content never fit inside its allotted box at the shortest
   supported viewports, confirmed via direct getBoundingClientRect()
   measurement at 844x390. Card size itself is still owned by style.css's
   .hand-fan--hero rules (this file only ever painted margin/filter on it,
   per this file's own "paint only" scope note above) — this block only
   trims the pod that sits above it. */
@media (orientation: landscape) and (max-height: 420px) {
  body.aurora-gameplay-active .app .hero-zone { gap: 2px; }
  /* .cd-hero-head kept at its established 20px/1px-7px — out of scope, same
     reasoning as the base rule above. .hero-id trimmed further (2026-07-23)
     so the shrunk timer-slot's reclaimed height actually reaches
     heroFanAvailHeight() at this already-tight breakpoint too. */
  body.aurora-gameplay-active .app .cd-hero-head {
    min-height: 20px;
    padding: 1px 7px 1px 2px;
  }
  body.aurora-gameplay-active .app .hero-id {
    min-height: 18px;
    padding: 1px 6px 1px 2px;
  }
  /* 12px (first attempt) made the "30"/"15" countdown number illegible —
     unlike .d-badge below, this one is visible and functional, so it has a
     real legibility floor the invisible badge doesn't. 18px keeps 2-digit
     text readable while still beating the original 16px avatar. Same
     wrapper-crops-scaled-child technique as the base breakpoint above, at
     this breakpoint's own target (18/42 = 0.4286). */
  body.aurora-gameplay-active .app .hero-id-timer-slot {
    width: 18px;
    height: 18px;
    flex: none;
    overflow: hidden;
  }
  #timerWrap.aurora-hero-timer {
    transform: scale(0.4286);
    transform-origin: top left;
  }
  body.aurora-gameplay-active .app .hero-id .d-badge {
    width: 10px;
    height: 10px;
  }
  body.aurora-gameplay-active .app .hero-id strong,
  body.aurora-gameplay-active .app .cd-hero-head strong {
    font-size: .68rem;
  }
  body.aurora-gameplay-active .app .hero-chips,
  body.aurora-gameplay-active .app .cd-hero-stack {
    font-size: .62rem;
  }
  body.aurora-gameplay-active .app .hand-fan--hero {
    margin-top: -1px;
  }
}
