/* ==========================================================================
   BestieMe Chess Duels — Stylesheet
   ========================================================================== */

.cd-wrap {
  /* Wider container on PC so the two-column game layout has real room
     for both a large board and the moves/rewards side panel. */
  max-width: 1280px;
  margin: 0 auto;
  width: 100%;
}

.cd-header {
  text-align: center;
  margin-bottom: var(--space-5);
}
.cd-title {
  margin: 0 0 var(--space-2);
  font-size: clamp(1.5rem, 4vw, 2.25rem);
}
.cd-subtitle {
  color: var(--text-secondary);
  font-size: 0.9375rem;
  margin: 0;
}

/* ───────── Menu ───────── */
.cd-menu {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: 720px;
  margin: 0 auto;
}

/* Two-column row that holds Opponent + View side by side on tablet/PC.
   On phone it collapses to a single column so each card has room. */
.cd-menu-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}
@media (min-width: 601px) {
  .cd-menu-row { grid-template-columns: 1fr 1fr; }
}

.cd-back-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  padding: 8px 14px 8px 12px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  color: var(--text-secondary, #c0c0d0);
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 500;
  line-height: 1;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.18s ease;
}
.cd-back-btn:hover {
  background: rgba(255, 210, 64, 0.10);
  border-color: rgba(255, 210, 64, 0.45);
  color: #f5ead0;
  transform: translateX(-2px);
}
.cd-back-btn:active { transform: translateX(-2px) scale(0.97); }
.cd-back-btn svg { display: block; flex-shrink: 0; }
.cd-back-btn:focus-visible {
  outline: 2px solid rgba(255, 210, 64, 0.6);
  outline-offset: 2px;
}

.cd-menu-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
}
.cd-menu-card h3 {
  margin: 0 0 var(--space-3);
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
}
.cd-menu-help {
  color: var(--text-tertiary);
  font-size: 0.8125rem;
  margin: 0 0 var(--space-3);
}

.cd-chip-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
}
.cd-chip-row-4 {
  grid-template-columns: repeat(4, 1fr);
}
@media (max-width: 600px) {
  .cd-chip-row { grid-template-columns: repeat(2, 1fr); }
  .cd-chip-row-4 { grid-template-columns: repeat(2, 1fr); }
}

.cd-chip {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  transition: all var(--transition-base);
  color: var(--text-primary);
  font-weight: 600;
  font-size: 0.9375rem;
  text-align: center;
  position: relative;
}
.cd-chip:hover {
  border-color: var(--border-light);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
}
.cd-chip.active {
  border-color: var(--accent);
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.18), rgba(139, 92, 246, 0.12));
  color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent), 0 6px 18px rgba(99, 102, 241, 0.28);
}
.cd-chip-icon { font-size: 1.6rem; line-height: 1; }
.cd-chip small { color: var(--text-tertiary); font-size: 0.75rem; font-weight: 500; }
.cd-chip.active small { color: var(--accent); opacity: 0.85; }

/* Disabled chip — Quick Match while live PvP is not yet shipped. */
.cd-chip[disabled],
.cd-chip.cd-chip-disabled {
  opacity: 0.6;
  cursor: not-allowed;
  filter: grayscale(0.35);
  pointer-events: none;
}
.cd-chip[disabled]:hover,
.cd-chip.cd-chip-disabled:hover {
  transform: none;
  box-shadow: none;
  border-color: var(--border);
}
.cd-soon-badge {
  display: inline-block;
  margin-top: 4px;
  padding: 3px 10px;
  border-radius: 999px;
  background: linear-gradient(110deg, rgba(245, 158, 11, 0.22), rgba(245, 158, 11, 0.12));
  border: 1px solid rgba(245, 158, 11, 0.55);
  color: #fbbf24;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  white-space: nowrap;
}

.cd-start-btn {
  width: 100%;
  padding: var(--space-4);
  font-size: 1.0625rem;
  font-weight: 700;
  background: linear-gradient(120deg, #6366f1, #8b5cf6 55%, #ec4899);
  background-size: 200% 200%;
  border: none;
  color: #fff;
  box-shadow: 0 6px 22px rgba(99, 102, 241, 0.38);
  transition: transform 0.15s ease, box-shadow 0.2s ease, background-position 0.3s ease;
  letter-spacing: 0.4px;
}
.cd-start-btn:hover {
  background-position: 100% 50%;
  transform: translateY(-1px);
  box-shadow: 0 10px 28px rgba(139, 92, 246, 0.48);
}
.cd-start-btn:active { transform: translateY(0); }

/* ───── Device-tier menu layout ───── */
/* PHONE (≤ 600px) — everything fits in one viewport without scrolling.
   Aggressively compact: hide chip descriptions and help text, shrink
   paddings/fonts/icons, force horizontal chip rows even for 3/4 chips,
   and place Opponent + View side by side. */
@media (max-width: 600px) {
  .cd-menu {
    gap: 8px;
    max-width: 100%;
    /* Stretch menu to fill the viewport so the fair-play notice can sit
       glued to the bottom edge instead of leaving empty space below it.
       Subtract the app header height (~70px) to keep the layout aligned
       with the visible viewport area below the header bar. */
    min-height: calc(100dvh - 70px);
  }
  /* Push the fair-play notice to the very bottom of the menu column.
     Any leftover vertical space ends up between the Start button and
     this notice rather than below it — so the notice is always pinned
     to the bottom edge of the screen. */
  .cd-menu > .cd-fair-note {
    margin-top: auto;
  }
  .cd-back-btn {
    padding: 5px 12px 5px 10px;
    font-size: 0.8rem;
  }
  .cd-menu-row {
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }
  .cd-menu-card {
    padding: 10px 12px;
    border-radius: 12px;
  }
  .cd-menu-card h3 {
    font-size: 0.75rem;
    margin-bottom: 6px;
    letter-spacing: 0.04em;
  }
  /* Help text under section titles is too space-hungry on phone. */
  .cd-menu-help { display: none; }
  /* Default chip rows (Opponent / View — 2 chips) on phone: 2 columns. */
  .cd-chip-row {
    grid-template-columns: repeat(2, 1fr);
    gap: 5px;
  }
  /* Quality row: keep all 4 chips horizontal on phone instead of 2x2. */
  .cd-chip-row-4 {
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
  }
  /* Time Control is the only direct .cd-menu-card child that isn't quality
     (Opponent / View live inside .cd-menu-row). Force its 3 chips into a
     single horizontal row. */
  .cd-menu > .cd-menu-card:not(.cd-quality-card) .cd-chip-row {
    grid-template-columns: repeat(3, 1fr);
  }
  .cd-chip {
    padding: 7px 4px;
    font-size: 0.72rem;
    gap: 2px;
    line-height: 1.15;
    min-height: 0;
  }
  .cd-chip-icon { font-size: 1.05rem; }
  /* Hide chip descriptions on phone but keep the Coming soon badge. */
  .cd-chip small { display: none; }
  .cd-soon-badge {
    font-size: 0.55rem;
    padding: 1px 6px;
    margin-top: 2px;
    letter-spacing: 0.4px;
  }
  .cd-start-btn {
    padding: 10px 14px;
    font-size: 0.95rem;
    border-radius: 12px;
  }
  /* Fair-play notice shrunk to a compact strip. */
  .cd-fair-note {
    font-size: 0.65rem;
    padding: 6px 10px;
    line-height: 1.35;
    border-radius: 10px;
  }
}
/* TABLET (601-1024px) — keep chips horizontal/comfortable */
@media (min-width: 601px) and (max-width: 1024px) {
  .cd-menu { max-width: 760px; gap: var(--space-3); }
  .cd-menu-card { padding: var(--space-4); }
  .cd-chip { padding: var(--space-3) var(--space-4); }
}
/* PC (≥ 1025px) — wider menu, larger chips/start button */
@media (min-width: 1025px) {
  .cd-menu { max-width: 880px; gap: var(--space-4); }
  .cd-menu-card { padding: var(--space-5) var(--space-5); }
  .cd-menu-card h3 { font-size: 1.05rem; }
  .cd-chip { padding: var(--space-4); font-size: 1rem; }
  .cd-chip-icon { font-size: 1.8rem; }
  .cd-start-btn { padding: var(--space-4) var(--space-5); font-size: 1.125rem; }
}

.cd-fair-note {
  background: rgba(16, 185, 129, 0.07);
  border: 1px solid rgba(16, 185, 129, 0.25);
  border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-4);
  color: var(--text-secondary);
  font-size: 0.8125rem;
  line-height: 1.5;
}
.cd-fair-note strong { color: var(--success); }

.cd-signin-gate {
  background: rgba(245, 158, 11, 0.07);
  border: 1px solid rgba(245, 158, 11, 0.25);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  text-align: center;
}
.cd-signin-gate p { margin: 0 0 var(--space-2); color: var(--text-secondary); font-size: 0.9375rem; }
.cd-signin-note { font-size: 0.8125rem; color: var(--text-tertiary); margin-top: var(--space-2); }

/* ───────── Game ───────── */
.cd-game-toolbar {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  flex-wrap: wrap;
}
.btn-sm { padding: 6px 12px; font-size: 0.8125rem; }

.cd-game-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(240px, 22%, 300px);
  gap: var(--space-4);
}
/* Single column on phone + tablet (was 900 — bumped so tablets use the
   full-width single-column layout and get a much larger board). */
@media (max-width: 1024px) {
  .cd-game-grid { grid-template-columns: 1fr; }
}

.cd-board-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  position: relative;
}

/* Board stage hosts the board itself and the fullscreen button overlay. */
.cd-board-stage {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Fullscreen toggle button — small icon overlay top-right of the board.
   Tinted background so it's visible on both light and dark squares. */
.cd-fs-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 30;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(10, 14, 26, 0.55);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  cursor: pointer;
  transition: background 150ms ease, transform 150ms ease, border-color 150ms ease;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  padding: 0;
}
.cd-fs-btn:hover {
  background: rgba(10, 14, 26, 0.8);
  border-color: rgba(255, 255, 255, 0.25);
  transform: scale(1.05);
}
.cd-fs-btn:active { transform: scale(0.95); }
.cd-fs-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.cd-fs-icon { display: block; }
.cd-fs-icon-exit { display: none; }

/* Fullscreen state — CSS-only approach that works on every browser (incl.
   iOS Safari, where the real Fullscreen API is restricted to <video>). */
.cd-board-col.cd-fs-active {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--bg-primary, #0a0e1a);
  padding: 12px;
  gap: 10px;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Use the small viewport units so mobile address bar doesn't clip us. */
  width: 100vw;
  height: 100svh;
  height: 100dvh;
}
.cd-board-col.cd-fs-active .cd-board-stage {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cd-board-col.cd-fs-active .cd-board-host {
  /* Largest possible square that fits inside the stage area */
  width: min(100%, calc(100dvh - 140px));
  height: auto;
  aspect-ratio: 1 / 1;
  max-width: 100%;
  max-height: 100%;
  margin: 0 auto;
}
.cd-board-col.cd-fs-active .cd-clock-row {
  flex: 0 0 auto;
  width: 100%;
  max-width: 600px;
}
.cd-board-col.cd-fs-active .cd-clock {
  font-size: 1.5rem;
}
.cd-board-col.cd-fs-active .cd-clock-box {
  padding: 10px 18px;
}

/* PC-only fullscreen tuning: clocks rotated on right edge, board fills viewport,
   smoke/cloud sky background, no surrounding container — the 3D board appears
   to float in the air. */
@media (min-width: 1025px) {
  .cd-board-col.cd-fs-active {
    padding: 0;
    gap: 0;
    overflow: hidden;
    /* Dark night-sky atmosphere — the cloud puffs ride on top of this. */
    background: linear-gradient(180deg, #0c1729 0%, #050913 60%, #02040a 100%);
  }
  /* Animated cloud layer — multiple soft puffs drifting slowly so the board
     feels suspended in moving fog. ::before sits behind everything else
     because all clock/board children have z-index > 0 via stacking context. */
  .cd-board-col.cd-fs-active::before {
    content: "";
    position: absolute;
    inset: -8%;
    background:
      radial-gradient(ellipse 900px 420px at 18% 28%, rgba(200,220,245,0.34), transparent 55%),
      radial-gradient(ellipse 760px 380px at 82% 72%, rgba(190,210,240,0.30), transparent 55%),
      radial-gradient(ellipse 1300px 600px at 50% 95%, rgba(130,170,220,0.42), transparent 65%),
      radial-gradient(ellipse 620px 320px at 72% 18%, rgba(230,240,250,0.22), transparent 55%),
      radial-gradient(ellipse 540px 280px at 28% 78%, rgba(170,200,235,0.26), transparent 60%);
    filter: blur(8px);
    animation: cd-smoke-drift 38s ease-in-out infinite alternate;
    pointer-events: none;
    z-index: 0;
  }
  /* Second cloud layer drifting in the opposite direction at a different
     pace — overlap of the two layers creates the "moving fog" sensation. */
  .cd-board-col.cd-fs-active::after {
    content: "";
    position: absolute;
    inset: -8%;
    background:
      radial-gradient(ellipse 700px 360px at 65% 45%, rgba(180,205,240,0.22), transparent 55%),
      radial-gradient(ellipse 820px 400px at 35% 60%, rgba(160,195,235,0.20), transparent 58%),
      radial-gradient(ellipse 580px 300px at 90% 30%, rgba(210,225,245,0.18), transparent 55%);
    filter: blur(14px);
    animation: cd-smoke-drift-2 52s ease-in-out infinite alternate;
    pointer-events: none;
    z-index: 0;
    mix-blend-mode: screen;
  }
  /* Make sure interactive children sit above the smoke layers */
  .cd-board-col.cd-fs-active .cd-board-stage,
  .cd-board-col.cd-fs-active .cd-clock-row,
  .cd-board-col.cd-fs-active .cd-status,
  .cd-board-col.cd-fs-active .cd-fs-btn {
    position: relative;
    z-index: 2;
  }
  /* Strip the rounded container — board floats directly on the smoke */
  .cd-board-col.cd-fs-active .cd-board-host {
    background: transparent;
    border-radius: 0;
    overflow: visible;
    box-shadow: none;
  }
  /* Lift clocks out of the flex column and pin them to the right edge */
  .cd-board-col.cd-fs-active .cd-clock-row {
    position: absolute;
    right: 18px;
    width: auto;
    max-width: none;
    padding: 0;
    background: transparent;
    border: none;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    z-index: 10;
    pointer-events: none;
  }
  /* HTML clocks pinned to viewport corners on the right edge. We use a
     sibling selector for the Black clock because the status pill is now
     the actual first child of .cd-board-col — `:first-child` would no
     longer match the Black clock-row. */
  .cd-board-col.cd-fs-active .cd-status + .cd-clock-row {
    top: 4%;
    right: 24px;
  }
  .cd-board-col.cd-fs-active > .cd-clock-row:last-child {
    bottom: 4%;
    right: 24px;
  }
  /* Rotate clock box so the digits read vertically (top→bottom) */
  .cd-board-col.cd-fs-active .cd-clock-box {
    writing-mode: vertical-rl;
    text-orientation: mixed;
    transform: rotate(180deg);
    padding: 14px 10px;
    gap: 8px;
    pointer-events: auto;
  }
  .cd-board-col.cd-fs-active .cd-clock {
    font-size: 1.6rem;
    letter-spacing: 1px;
  }
  .cd-board-col.cd-fs-active .cd-clock-label {
    letter-spacing: 2px;
  }
  /* PC fullscreen: pin the status pill to the very top of the viewport,
     centered horizontally — sits just under the browser address bar. */
  .cd-board-col.cd-fs-active .cd-status {
    position: fixed;
    top: 12px;
    left: 50%;
    right: auto;
    bottom: auto;
    transform: translateX(-50%);
    z-index: 10;
  }
  /* Stage now spans the full viewport */
  .cd-board-col.cd-fs-active .cd-board-stage {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
  }
  /* 3D canvas spans the FULL viewport — no square cropping. The Three.js
     scene draws the board centered, and OrbitControls lets the user zoom
     in/out and orbit freely; pieces can grow toward the screen edges
     without ever being clipped by a container. */
  .cd-board-col.cd-fs-active .cd-board-host {
    width: 100dvw;
    height: 100dvh;
    aspect-ratio: auto;
    max-width: none;
    max-height: none;
  }
  .cd-board-col.cd-fs-active .cd-board-host > canvas {
    width: 100% !important;
    height: 100% !important;
    display: block;
  }
  /* 2D fullscreen on PC: independent width / height tuning. Width is the
     dominant axis (squares wider than they are tall) so the board is
     visually impactful without flooding the viewport. (3D mode unaffected.) */
  .cd-board-col.cd-fs-active .cd-board-host.c2d-root {
    width: min(94dvw, 94dvh);
    height: min(66dvw, 66dvh);
    max-width: 94dvh;
    max-height: 66dvh;
    aspect-ratio: auto;
  }
}
/* Swap icons when in fullscreen */
.cd-board-col.cd-fs-active .cd-fs-icon-enter { display: none; }
.cd-board-col.cd-fs-active .cd-fs-icon-exit { display: block; }
/* In fullscreen we keep the FS button visible (top-right of viewport now). */
.cd-board-col.cd-fs-active .cd-fs-btn {
  top: 14px;
  right: 14px;
}
/* Prevent body scroll while in fullscreen */
body.cd-fs-lock { overflow: hidden; }

.cd-clock-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
}
.cd-clock-box {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 8px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
}
.cd-clock-label {
  color: var(--text-tertiary);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.cd-clock {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text-primary);
}
.cd-clock-box.active {
  background: rgba(99, 102, 241, 0.12);
  border-color: var(--accent);
}
.cd-clock-box.active .cd-clock { color: var(--accent); }

/* Status pill — "Your move" / "Thinking…". Eye-catching gradient pill that
   shimmers gently so the player always knows whose turn it is. Position is
   tier-specific: above the clocks on phone/tablet, sticky to the top of the
   viewport on PC so it remains visible while the player thinks. */
.cd-status {
  align-self: center;
  display: inline-block;
  padding: 7px 22px;
  border-radius: 999px;
  background: linear-gradient(120deg, #6366f1 0%, #8b5cf6 45%, #ec4899 100%);
  background-size: 220% 220%;
  color: #fff;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  box-shadow:
    0 4px 18px rgba(99, 102, 241, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
  animation: cd-status-shimmer 3.4s ease-in-out infinite;
  margin: 0 auto var(--space-2);
  position: relative;
  z-index: 5;
}
@keyframes cd-status-shimmer {
  0%   { background-position:   0% 50%; box-shadow: 0 4px 18px rgba(99, 102, 241, 0.4),  inset 0 1px 0 rgba(255, 255, 255, 0.2); }
  50%  { background-position: 100% 50%; box-shadow: 0 4px 26px rgba(236,  72, 153, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.28); }
  100% { background-position:   0% 50%; box-shadow: 0 4px 18px rgba(99, 102, 241, 0.4),  inset 0 1px 0 rgba(255, 255, 255, 0.2); }
}
/* PC: stick the status pill to the top of the viewport so it's always
   visible just below the browser address bar while the player thinks. */
@media (min-width: 1025px) {
  .cd-status {
    position: sticky;
    top: 10px;
    margin-bottom: var(--space-3);
  }
}

/* Board host — responsive square that fits the column.
   The width is `min(column-width, dvh-budget)` so the board never grows
   past either its column OR the visible vertical space. The reservation
   value (the number we subtract from 100dvh) accounts for the toolbar,
   two clock rows, status text and page padding above/below the board.
   `100dvh` is used instead of `100vh` so mobile browsers don't size the
   board against the largest possible viewport — the address bar would
   then cover the bottom clock row.

   Defaults here are the medium-screen baseline; phones and PCs get
   tuned overrides via the breakpoints below.                          */
.cd-board-host {
  width: min(100%, calc(100dvh - 240px));
  max-width: 100%;
  aspect-ratio: 1 / 1;
  margin: 0 auto;
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--bg-secondary);
}

/* ───────── Device-tier board sizing ─────────
   Three explicit tiers, each with its own vertical reservation. The
   `min(...)` clamp guarantees the board never overflows in either
   axis no matter which constraint binds first.                       */

/* PHONE (≤ 600px) — single column, compact chrome, edge-to-edge board */
@media (max-width: 600px) {
  /* Compact the header so more vertical space is available for the board */
  .cd-header { margin-bottom: var(--space-3); }
  .cd-title  { font-size: clamp(1.1rem, 4vw, 1.4rem); }
  .cd-subtitle { display: none; }
  /* Tighter toolbar */
  .cd-game-toolbar { gap: 6px; margin-bottom: 8px; }
  .cd-game-toolbar .btn-sm { padding: 5px 10px; font-size: 0.78rem; }
  /* Tighter clock rows */
  .cd-clock-row { padding: 6px 8px; gap: 8px; }
  .cd-clock { font-size: 1.1rem; }
  /* Board fills nearly the entire viewport width — drop the rounded
     corners so the squares run to the device edge naturally. */
  .cd-board-host {
    width: min(calc((100vw - 8px) * 0.8), calc((100dvh - 175px) * 0.8));
    max-width: calc(100vw - 8px);
    border-radius: 6px;
  }
}

/* TABLET (601px – 1024px) — single column, normal chrome */
@media (min-width: 601px) and (max-width: 1024px) {
  .cd-board-host {
    width: min(calc(100% * 0.8), calc((100dvh - 215px) * 0.8));
  }
}

/* PC (≥ 1025px) — square board sized so the entire chrome (page header,
   title, toolbar, status pill, both clocks) plus the board fits inside
   the viewport without overflow. Both axes use 65dvh as the natural
   upper bound, with a tight calc clamp for short screens. */
@media (min-width: 1025px) {
  .cd-board-host {
    width: auto;
    height: min(65dvh, calc(100dvh - 360px));
    max-height: calc(100dvh - 320px);
    max-width: 100%;
    aspect-ratio: 1 / 1;
  }
}

/* ───────── Side panel ───────── */
.cd-side-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.cd-side-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}
.cd-side-card h4 {
  margin: 0 0 var(--space-3);
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
}
.cd-moves {
  max-height: 360px;
  overflow-y: auto;
  font-family: var(--font-mono);
  font-size: 0.875rem;
  line-height: 1.6;
}
.cd-move-row {
  display: grid;
  grid-template-columns: 32px 1fr 1fr;
  gap: 8px;
  padding: 2px 0;
}
.cd-move-num { color: var(--text-tertiary); }
.cd-rewards-text { color: var(--text-secondary); margin: 0 0 var(--space-2); font-size: 0.875rem; }
.cd-rewards-text strong { color: var(--gold-glow, #f5b800); }
.cd-rewards-text-small { color: var(--text-tertiary); font-size: 0.75rem; margin: 0; }

/* ───────── Game over overlay ───────── */
.cd-over-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
}
.cd-over-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  max-width: 420px;
  width: 100%;
  text-align: center;
  animation: cd-over-pop 240ms cubic-bezier(0.34, 1.56, 0.64, 1);
  position: relative;
}
.cd-over-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--text-secondary, #c0c0d0);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  transition: background 0.18s ease, color 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
.cd-over-close:hover {
  background: rgba(255, 59, 59, 0.18);
  border-color: rgba(255, 59, 59, 0.55);
  color: #fff;
  transform: scale(1.08);
}
.cd-over-close:active { transform: scale(0.94); }
.cd-over-close:focus-visible {
  outline: 2px solid rgba(255, 210, 64, 0.6);
  outline-offset: 2px;
}
@keyframes cd-over-pop {
  from { opacity: 0; transform: scale(0.92); }
  to { opacity: 1; transform: scale(1); }
}
.cd-over-card h2 {
  margin: 0 0 var(--space-2);
  font-size: 1.75rem;
}
.cd-over-sub {
  color: var(--text-secondary);
  margin: 0 0 var(--space-4);
}
.cd-over-reward {
  background: rgba(245, 158, 11, 0.1);
  border: 1px solid rgba(245, 158, 11, 0.3);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  color: var(--gold-glow, #f5b800);
  font-weight: 700;
  margin: 0 0 var(--space-4);
}
.cd-over-actions {
  display: flex;
  gap: var(--space-2);
}
.cd-over-actions .btn { flex: 1; }

/* ==========================================================================
   2D BOARD (chess-2d.js)
   ========================================================================== */
.c2d-root {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.c2d-root.locked {
  pointer-events: none;
  opacity: 0.85;
}
.c2d-board {
  display: grid;
  /* `minmax(0, 1fr)` is critical — without the 0 min, large piece glyphs
     force each cell to grow beyond 1/8 of the host, pushing the rightmost
     files past the container edge where `overflow: hidden` clips them. */
  grid-template-columns: repeat(8, minmax(0, 1fr));
  grid-template-rows: repeat(8, minmax(0, 1fr));
  width: 100%;
  height: 100%;
  background: #6f4d2c;
  border-radius: var(--radius-md);
  overflow: hidden;
  position: relative;
}
.c2d-board.flip { transform: rotate(180deg); }
.c2d-board.flip .c2d-piece { transform: rotate(180deg); }

.c2d-cell {
  border: 0;
  padding: 0;
  /* min-* 0 + overflow-hidden defends against grid blow-out when piece
     glyphs are large — see comment on .c2d-board. */
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  cursor: pointer;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  transition: background-color 100ms ease;
  box-sizing: border-box;
}
.c2d-cell.light { background: #e6d3b3; }
.c2d-cell.dark { background: #6f4d2c; }
.c2d-cell.last::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(255, 224, 102, 0.35);
  pointer-events: none;
}
.c2d-cell.sel::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(79, 163, 255, 0.35);
  pointer-events: none;
}
/* Destination markers — colour shows whether the move is "safe" (the
   landing square is NOT attacked by an opponent piece after the move)
   or "unsafe" (the landing square would be under attack, so the piece
   could be captured). Captures get a ring instead of a dot so the user
   still sees the destination contains an enemy piece. */
.c2d-cell.safe::after {
  content: "";
  position: absolute;
  width: 32%;
  height: 32%;
  border-radius: 50%;
  background: rgba(74, 222, 128, 0.7);
  pointer-events: none;
  box-shadow: 0 0 8px rgba(74, 222, 128, 0.35);
}
.c2d-cell.safe-capture::after {
  content: "";
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  border: 4px solid rgba(74, 222, 128, 0.85);
  pointer-events: none;
  box-shadow: 0 0 10px rgba(74, 222, 128, 0.4);
}
.c2d-cell.unsafe::after {
  content: "";
  position: absolute;
  width: 32%;
  height: 32%;
  border-radius: 50%;
  background: rgba(239, 68, 68, 0.75);
  pointer-events: none;
  box-shadow: 0 0 8px rgba(239, 68, 68, 0.4);
}
.c2d-cell.unsafe-capture::after {
  content: "";
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  border: 4px solid rgba(239, 68, 68, 0.9);
  pointer-events: none;
  box-shadow: 0 0 10px rgba(239, 68, 68, 0.45);
}
.c2d-cell.check::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle, rgba(255, 48, 48, 0.6) 30%, transparent 70%);
  pointer-events: none;
}
.c2d-piece {
  /* vmin fallback for any browser without container query support;
     overridden by the cqi version below on modern browsers. */
  font-size: clamp(20px, 5vmin, 50px);
  font-size: clamp(20px, 70cqmin, 60px);
  line-height: 1;
  user-select: none;
  pointer-events: none;
  max-width: 100%;
  max-height: 100%;
  transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1);
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.35));
}
/* Establish a size container so the piece glyph scales to the cell box. */
.c2d-cell { container-type: size; }
.c2d-piece.w { color: #ffffff; }
.c2d-piece.b { color: #1a1a1a; }

/* Promotion overlay (shared by 2D and 3D) */
.c2d-promotion-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
}
.c2d-promotion-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  max-width: 380px;
  width: 100%;
}
.c2d-promotion-card h3 {
  margin: 0 0 var(--space-4);
  text-align: center;
  font-size: 1.0625rem;
}
.c2d-promotion-options {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.c2d-promotion-options button {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  cursor: pointer;
  font-size: 1.5rem;
  color: var(--text-primary);
  transition: all 120ms ease;
}
.c2d-promotion-options button:hover {
  border-color: var(--accent);
  background: rgba(99, 102, 241, 0.1);
}
.c2d-promotion-cancel {
  width: 100%;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-2);
  color: var(--text-secondary);
  cursor: pointer;
}

/* ==========================================================================
   3D BOARD (chess-3d.js)
   ========================================================================== */
.c3d-root {
  width: 100%;
  height: 100%;
  position: relative;
}
.c3d-root canvas {
  display: block;
  width: 100% !important;
  height: 100% !important;
}

/* ==========================================================================
   END-OF-GAME ANIMATIONS (2D board)
   --------------------------------------------------------------------------
   These visually communicate *why* the game ended before the result overlay
   appears: the losing king's square pulses, the checkmating attacker's
   square pulses gold, and the king glyph tips over.
   ========================================================================== */

@keyframes c2d-mate-king-pulse {
  0%, 100% { box-shadow: inset 0 0 0 4px rgba(255,32,48,0.0), 0 0 0 0 rgba(255,32,48,0); background-color: rgba(255,32,48,0.18); }
  50%      { box-shadow: inset 0 0 0 4px rgba(255,32,48,0.95), 0 0 28px 6px rgba(255,32,48,0.6); background-color: rgba(255,32,48,0.42); }
}
@keyframes c2d-stale-king-pulse {
  0%, 100% { box-shadow: inset 0 0 0 4px rgba(255,210,64,0.0); background-color: rgba(255,210,64,0.18); }
  50%      { box-shadow: inset 0 0 0 4px rgba(255,210,64,0.95), 0 0 22px 4px rgba(255,210,64,0.45); background-color: rgba(255,210,64,0.38); }
}
@keyframes c2d-end-king-pulse {
  0%, 100% { box-shadow: inset 0 0 0 4px rgba(170,180,200,0.0); background-color: rgba(170,180,200,0.18); }
  50%      { box-shadow: inset 0 0 0 4px rgba(170,180,200,0.9); background-color: rgba(170,180,200,0.36); }
}
@keyframes c2d-mate-attacker-pulse {
  0%, 100% { box-shadow: inset 0 0 0 4px rgba(255,210,64,0.0); background-color: rgba(255,210,64,0.18); }
  50%      { box-shadow: inset 0 0 0 4px rgba(255,210,64,0.95), 0 0 22px 4px rgba(255,210,64,0.45); background-color: rgba(255,210,64,0.38); }
}
@keyframes c2d-tip-over {
  0%   { transform: rotate(0deg)   translateY(0); }
  60%  { transform: rotate(70deg)  translateY(-10%); }
  100% { transform: rotate(90deg)  translateY(0); }
}
@keyframes c2d-draw-pulse-anim {
  0%, 100% { filter: brightness(1)   saturate(1); }
  50%      { filter: brightness(1.2) saturate(1.4); }
}

.c2d-cell.c2d-mate-king {
  animation: c2d-mate-king-pulse 0.55s ease-in-out 3 forwards;
  position: relative; z-index: 2;
}
.c2d-cell.c2d-stale-king {
  animation: c2d-stale-king-pulse 0.6s ease-in-out 3 forwards;
  position: relative; z-index: 2;
}
.c2d-cell.c2d-end-king {
  animation: c2d-end-king-pulse 0.6s ease-in-out 3 forwards;
  position: relative; z-index: 2;
}
.c2d-cell.c2d-mate-attacker {
  animation: c2d-mate-attacker-pulse 0.5s ease-in-out 3 forwards;
  animation-delay: 0.15s;
  position: relative; z-index: 2;
}
.c2d-piece.c2d-tip-over {
  animation: c2d-tip-over 0.9s cubic-bezier(0.34, 1.2, 0.64, 1) 1 forwards;
  animation-delay: 1.0s;
  transform-origin: 50% 90%;
  display: inline-block;
}
.c2d-root.c2d-draw-pulse {
  animation: c2d-draw-pulse-anim 0.9s ease-in-out 2;
}

/* Jet contrail SVG overlay drawn during replay moves.
   - Starts at full opacity with a strong drop-shadow glow
   - Fades over 1 second via CSS transition
   - pointer-events: none so it never blocks clicks */
.c2d-trail {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
  opacity: 1;
  filter: drop-shadow(0 0 6px rgba(255, 210, 64, 0.7))
          drop-shadow(0 0 14px rgba(255, 245, 208, 0.45));
  transition: opacity 1s ease-out, filter 1s ease-out;
  z-index: 3;
}
.c2d-trail.fading {
  opacity: 0;
  filter: drop-shadow(0 0 0 rgba(255, 210, 64, 0));
}

/* ==========================================================================
   LOCKED PIECE FEEDBACK
   --------------------------------------------------------------------------
   When the user touches a piece that has no legal moves, briefly shake
   the glyph in place. That's the only cue — no overlay, no orbit, no
   lock icon.
   ========================================================================== */

@keyframes piece-shake {
  0%, 100% { transform: translateX(0) translateY(0); }
  15%      { transform: translateX(-4px) translateY(-1px); }
  30%      { transform: translateX(4px)  translateY(1px); }
  45%      { transform: translateX(-3px) translateY(-1px); }
  60%      { transform: translateX(3px)  translateY(1px); }
  75%      { transform: translateX(-2px) translateY(0); }
  90%      { transform: translateX(2px)  translateY(0); }
}
.c2d-piece.c2d-piece-shake {
  animation: piece-shake 0.45s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
  color: #c41515 !important;
  text-shadow: 0 0 8px rgba(196, 21, 21, 0.7);
}

/* ==========================================================================
   REPLAY BANNER — cricket-style "how it happened" overlay shown while the
   last few moves are stepped through on the board.
   ========================================================================== */
.chess-replay-banner {
  position: fixed;
  top: max(env(safe-area-inset-top, 0px), 14px);
  left: 50%;
  transform: translate(-50%, -20px);
  z-index: 99999;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  border-radius: 999px;
  background: linear-gradient(135deg, rgba(20,24,36,0.92), rgba(40,30,60,0.92));
  border: 1px solid rgba(255,210,64,0.45);
  box-shadow: 0 8px 28px rgba(0,0,0,0.4), 0 0 18px rgba(255,210,64,0.18);
  color: #f5ead0;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.chess-replay-banner.visible {
  opacity: 1;
  transform: translate(-50%, 0);
}
.chess-replay-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #ff3b3b;
  box-shadow: 0 0 10px rgba(255, 59, 59, 0.85);
  animation: chess-replay-dot-blink 0.9s ease-in-out infinite;
  flex-shrink: 0;
}
@keyframes chess-replay-dot-blink {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: 0.4; transform: scale(0.75); }
}

/* PC-fullscreen smoke clouds — slow drift + scale so two layers overlapping
   give a sense of moving fog. The clouds never fully repeat (alternate
   direction), keeping the motion organic instead of looping visibly. */
@keyframes cd-smoke-drift {
  0%   { transform: translate(0%, 0%) scale(1); }
  100% { transform: translate(-4%, 3%) scale(1.10); }
}
@keyframes cd-smoke-drift-2 {
  0%   { transform: translate(0%, 0%) scale(1.05); }
  100% { transform: translate(5%, -3%) scale(1.15); }
}
.chess-replay-text { white-space: nowrap; }

.chess-replay-skip {
  margin-left: 4px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(255, 210, 64, 0.16);
  border: 1px solid rgba(255, 210, 64, 0.45);
  color: #ffd040;
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  cursor: pointer;
  pointer-events: auto;
  transition: background 0.18s ease, transform 0.15s ease, color 0.18s ease;
}
.chess-replay-skip:hover {
  background: rgba(255, 210, 64, 0.32);
  color: #fff5d0;
  transform: scale(1.05);
}
.chess-replay-skip:active { transform: scale(0.95); }
.chess-replay-skip:focus-visible {
  outline: 2px solid rgba(255, 210, 64, 0.7);
  outline-offset: 2px;
}
.chess-replay-banner.visible { pointer-events: auto; }

/* ==========================================================================
   REPLAY FRAME DOWNLOAD — small secondary action on the result overlay
   ========================================================================== */
.cd-over-download {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding: 8px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px dashed rgba(255, 210, 64, 0.4);
  color: var(--text-secondary, #c0c0d0);
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.cd-over-download:hover {
  background: rgba(255, 210, 64, 0.12);
  border-color: rgba(255, 210, 64, 0.7);
  color: #f5ead0;
  transform: translateY(-1px);
}
.cd-over-download:active { transform: translateY(0) scale(0.98); }
.cd-over-download:focus-visible {
  outline: 2px solid rgba(255, 210, 64, 0.6);
  outline-offset: 2px;
}
.cd-over-download svg { display: block; flex-shrink: 0; }

/* Capture progress / status pill (top-right corner) */
.chess-capture-status {
  position: fixed;
  top: max(env(safe-area-inset-top, 0px), 14px);
  right: 14px;
  z-index: 100001;
  padding: 10px 16px;
  border-radius: 999px;
  background: rgba(20, 24, 36, 0.94);
  border: 1px solid rgba(255, 210, 64, 0.45);
  color: #f5ead0;
  font-size: 0.88rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  opacity: 0;
  transform: translateY(-10px);
  pointer-events: none;
  transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.34, 1.4, 0.64, 1);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}
.chess-capture-status.visible {
  opacity: 1;
  transform: translateY(0);
}
