/* Theme: dark is the default/baseline look (toggled via a button in
   js/app.js, which sets data-theme="light"|"dark" on <html> and persists
   the choice to localStorage). Board squares, tag badges, and piece colors
   are deliberately theme-invariant below (chess-semantic, not page chrome)
   — only page/panel/button chrome changes between the two blocks. */
:root {
  --bg: #1b1b1e;
  --panel: #242428;
  --panel-border: #34343a;
  --text: #eae7e0;
  --text-muted: #9a978f;
  --accent: #c9a15a;
  --btn-bg: #313136;
  --btn-border: #414147;
  --btn-hover: #3a3a41;
  --chip-bg: #34343c;
  --chip-border: #45454e;
  --hover-overlay: rgba(255, 255, 255, 0.06);

  --square-light: #ecd9b6;
  --square-dark: #b3875a;
  --square-highlight: #f4f06a;
  --square-target: #7fd17f;

  --tag-best: #4c9a4c;
  --tag-brilliant: #17a9c9;
  --tag-excellent: #3f9c8f;
  --tag-good: #4a86c9;
  --tag-book: #8a7455;
  --tag-inaccuracy: #d3a13b;
  --tag-mistake: #dd8a3d;
  --tag-blunder: #d1483f;
  --tag-forced: #7c7c82;
}

:root[data-theme="light"] {
  --bg: #f3efe6;
  --panel: #ffffff;
  --panel-border: #ddd6c7;
  --text: #211d17;
  --text-muted: #6b6355;
  --accent: #9c7530;
  --btn-bg: #efe9db;
  --btn-border: #ddd4c0;
  --btn-hover: #e4ddcc;
  --chip-bg: #efe9db;
  --chip-border: #ddd4c0;
  --hover-overlay: rgba(0, 0, 0, 0.05);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

button {
  font-family: inherit;
  cursor: pointer;
}

#app {
  max-width: 1300px;
  margin: 0 auto;
  padding: 16px;
}

/* Mirrors .layout's grid so the title lands centered over the board
   column specifically, not the whole page (which also has the eval bar
   and info panel pulling the midpoint off-center). */
.topbar {
  display: grid;
  grid-template-columns: 56px minmax(320px, 640px) 340px;
  gap: 20px;
  margin-bottom: 16px;
}

.topbar h1 {
  grid-column: 2;
  text-align: center;
  font-size: 1.4rem;
  margin: 0;
  letter-spacing: 0.02em;
}

.layout {
  display: grid;
  grid-template-columns: 56px minmax(320px, 640px) 340px;
  gap: 20px;
  align-items: start;
}

@media (max-width: 980px) {
  .topbar {
    display: block;
    text-align: center;
  }
  .layout {
    grid-template-columns: 1fr;
  }
}

/* ---------------- Eval panel ---------------- */
.eval-panel {
  position: relative; /* anchors .theme-toggle, positioned absolutely below */
  display: flex;
  justify-content: center;
  /* Deliberately normal document flow otherwise (no position:sticky) —
     sticky made the panel reposition relative to the *viewport* on
     scroll/zoom independently of .board-panel next to it, which is exactly
     what broke the "flush with the board" alignment when scrolling/
     zooming. Plain static flow keeps both scrolling in perfect lockstep
     instead. */
}

/* Lives in the eval-bar column, pinned to the top of it — level with the
   top of the elo-panel/tray area, well clear of the eval-readout badge
   that floats just above the bar further down this same column. (A
   previous version tried to vertically match the tray row specifically,
   which put it close enough to crowd/overlap the readout badge — a plain
   fixed top avoids that without needing to fight for space down there.) */
.theme-toggle {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  line-height: 1;
  background: var(--btn-bg);
  color: var(--text);
  border: 1px solid var(--btn-border);
  border-radius: 50%;
}
.theme-toggle:hover { background: var(--btn-hover); }

/* Pure positioning box — js/app.js sets its height and top margin to
   exactly match the board element's own rendered box (see
   syncEvalBarHeight), so the bar's top/bottom stay flush with the board's
   regardless of viewport width or what's stacked above the board
   (Elo selector, tray). The visible track (background/border/fill) lives
   in .eval-bar-inner instead, so the readout/verdict labels below can
   overlay outside it without being clipped by its rounded corners. */
.eval-bar-track {
  position: relative;
  width: 28px;
}

.eval-bar-inner {
  position: absolute;
  inset: 0;
  background: #2b2b2b;
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  overflow: hidden;
}

.eval-readout {
  position: absolute;
  left: 50%;
  bottom: 100%;
  transform: translateX(-50%);
  margin-bottom: 6px;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 0.85rem;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  padding: 2px 6px;
  min-width: 40px;
  text-align: center;
  white-space: nowrap;
}

.eval-bar-fill {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  background: #f2efe8;
  height: 50%;
  /* No transition: the app streams live score updates rapidly during each
     ~500ms analysis, retargeting this height many times in quick
     succession — an animated height fighting that stream of updates can
     end up visibly lagging behind (or outright stuck short of) the actual
     current score, which is exactly what made the 50/50 midline look
     wrong relative to where the fill boundary actually was. Snapping
     instantly avoids that; the app's whole pitch is instant feedback
     anyway, so an animated lag here was working against that. */
}

/* The 50/50 marker. Previously a 1px rgba(0,0,0,0.25) line — nearly
   invisible against the bar's own dark upper half (dark-on-dark), which is
   exactly why it only seemed to show up as a faint line near Even: that's
   the one spot where it sits right at the boundary with the light fill
   instead of entirely within the dark area. A mid-gray, mostly-opaque line
   contrasts against both halves so it reads the same everywhere. */
.eval-bar-mid {
  position: absolute;
  left: 0; right: 0; top: 50%;
  transform: translateY(-50%);
  height: 3px;
  background: rgba(150, 150, 150, 0.9);
  pointer-events: none;
}

/* Below the desktop breakpoint the bar goes horizontal and js/app.js stops
   sizing it to the board (see the matchMedia check in syncEvalBarHeight)
   — inline height/margin-top from that get cleared, and this flex-row
   layout takes over instead. Deliberately placed *after* the base rules
   above: at equal specificity, source order decides the winner once the
   media query's condition is true, so this has to come later to win. */
@media (max-width: 980px) {
  .eval-panel { width: 100%; gap: 8px; }
  /* The toggle's absolute desktop positioning (matched to the tray row in
     that narrow side column) doesn't apply once the bar goes horizontal —
     put it back in normal flow, first in the row, left of the bar. */
  .theme-toggle { position: static; transform: none; flex-shrink: 0; }
  .eval-bar-track {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    height: auto !important;
    margin-top: 0 !important;
  }
  .eval-bar-inner {
    position: relative;
    inset: auto;
    flex: 1;
    height: 22px;
  }
  .eval-bar-fill { left: auto; right: auto; bottom: 0; top: 0; width: 50%; height: auto; }
  .eval-bar-mid { top: 0; bottom: 0; left: 50%; right: auto; width: 3px; height: auto; transform: translateX(-50%); }
  .eval-readout { position: static; transform: none; margin: 0; }
}

/* ---------------- Board panel ---------------- */
.board-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.elo-panel {
  width: 100%;
  max-width: 560px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.elo-label {
  font-size: 0.75rem;
  color: var(--text-muted);
}
.elo-label strong { color: var(--accent); font-weight: 700; }

.elo-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
}
.elo-btn {
  background: var(--btn-bg);
  color: var(--text);
  border: 1px solid var(--btn-border);
  border-radius: 999px;
  padding: 5px 11px;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}
.elo-btn:hover { background: var(--btn-hover); }
.elo-btn.active { background: var(--accent); color: #201a0c; border-color: var(--accent); }
.elo-btn.god-mode { border-style: dashed; }
.elo-btn.god-mode.active { border-style: solid; }

.tray {
  display: flex;
  gap: 6px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  padding: 6px 10px;
  justify-content: center;
  width: 100%;
  max-width: 560px;
}

.tray-piece {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.tray-piece .piece-icon { width: 82%; height: 82%; }

.tray-piece:hover { background: var(--hover-overlay); }

.board-wrap {
  width: 100%;
  max-width: 560px;
  aspect-ratio: 1 / 1;
}

.board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(8, 1fr);
  width: 100%;
  height: 100%;
  border: 2px solid #14140f;
  border-radius: 4px;
  overflow: hidden;
}

.square {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.square.light { background: var(--square-light); }
.square.dark { background: var(--square-dark); }
.square.sq-highlight::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--square-highlight);
  opacity: 0.45;
}
.square.sq-lastmove::after {
  content: "";
  position: absolute;
  inset: 0;
  background: #f4f06a;
  opacity: 0.3;
}
.square.sq-drop-target::after {
  content: "";
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  background: var(--square-target);
  opacity: 0.55;
}

/* Click-to-move: the square holding the currently-selected piece. */
.square.sq-selected::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--square-highlight);
  opacity: 0.45;
}
/* Click-to-move legal destinations. A small centered dot for a quiet move; */
.square.sq-move-target::after {
  content: "";
  position: absolute;
  inset: 38%;
  border-radius: 50%;
  background: var(--square-target);
  opacity: 0.6;
  pointer-events: none;
}
/* ...a ring around the edge instead when the target square is a capture, so
   the piece being captured stays visible under it. */
.square.sq-move-target.sq-move-capture::after {
  inset: 5%;
  background: transparent;
  border: 4px solid var(--square-target);
  opacity: 0.75;
}
.square.sq-suggest-from::after,
.square.sq-suggest-to::after {
  content: "";
  position: absolute;
  inset: 3px;
  border: 3px solid #4aa3e0;
  border-radius: 4px;
  opacity: 0.85;
  pointer-events: none;
}

.coord-file, .coord-rank {
  position: absolute;
  font-size: 10px;
  font-weight: 700;
  opacity: 0.55;
  pointer-events: none;
  user-select: none;
}
.coord-file { bottom: 2px; right: 3px; }
.coord-rank { top: 2px; left: 3px; }
.square.light .coord-file, .square.light .coord-rank { color: var(--square-dark); }
.square.dark .coord-file, .square.dark .coord-rank { color: var(--square-light); }

.piece {
  position: relative;
  width: 88%;
  height: 88%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.piece.dragging { opacity: 0.25; }

/* Piece artwork: traced directly from the user's reference sheets — verified
   against a red test background to confirm both colors render fully opaque
   (see js/piece-icons.js). Both colors are two stacked paths:

     `.piece-icon-backing`  an opaque solid silhouette, always filled white,
                             sitting *underneath* the main shape so nothing
                             ever shows the board square color through a
                             piece.
     `.piece-icon-main`     the visible black ink on top:
                              - white pieces: the traced outline + detail ink
                                (eye, cross, bands) — the outline *is* this
                                path, not a stroke trick.
                              - black pieces: the full compound silhouette
                                with fill-rule evenodd, whose cut-outs (eye,
                                mitre notch, crown gaps) reveal the white
                                backing layer beneath.

   White pieces give `.piece-icon-main` a thin self-colored stroke (same
   color as the fill) purely for crisp anti-aliased edges — not a visible
   border. Black pieces skip the stroke entirely; fill alone is crisp enough
   at their scale and a stroke there read as an unwanted outline.

   The traced paths use a ~550-unit-tall coordinate space (the source scan's
   native resolution), so stroke widths are scaled to match. */
.piece-icon {
  width: 84%;
  height: 84%;
  overflow: visible;
}
.piece-icon-backing { fill: #fbfaf6; }

.piece-icon-white .piece-icon-main {
  fill: #171410;
  stroke: #171410;
  stroke-width: 4;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.piece-icon-black .piece-icon-main {
  fill: #171410;
  stroke: none;
}
.piece-icon-black { filter: drop-shadow(0 1px 1px rgba(0,0,0,0.4)); }
.drag-ghost {
  position: fixed;
  pointer-events: none;
  z-index: 500;
  width: 52px;
  height: 52px;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 4px 6px rgba(0,0,0,0.5));
}
.drag-ghost .piece-icon { width: 100%; height: 100%; }

/* ---------------- Controls ---------------- */
.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  width: 100%;
  max-width: 560px;
}
.control-group {
  display: flex;
  gap: 6px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  padding: 6px;
}
.control-group button {
  background: var(--btn-bg);
  color: var(--text);
  border: 1px solid var(--btn-border);
  border-radius: 6px;
  padding: 7px 10px;
  font-size: 0.8rem;
  white-space: nowrap;
}
.control-group button:hover { background: var(--btn-hover); }
.control-group button:active { transform: translateY(1px); }
.control-group button.active { background: var(--accent); color: #201a0c; border-color: var(--accent); }
.control-group button:disabled { opacity: 0.4; cursor: default; }

#btnTurnWhite { background: #f2efe8; color: #17140f; border-color: #d8d3c6; }
#btnTurnWhite:hover { background: #ffffff; }
#btnTurnBlack { background: #17140f; color: #f2efe8; border-color: #000; }
#btnTurnBlack:hover { background: #262220; }

.hint {
  font-size: 0.75rem;
  color: var(--text-muted);
  text-align: center;
  max-width: 560px;
  margin: 0;
}

/* ---------------- Info panel ---------------- */
.info-panel {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.card {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  padding: 12px 14px;
}
.card h2 {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  margin: 0 0 8px 0;
}

.muted { color: var(--text-muted); }

.suggestion-body { font-size: 0.92rem; }
.suggestion-move {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--accent);
}
.suggestion-meta { font-size: 0.78rem; color: var(--text-muted); margin-top: 2px; }
.suggestion-mode { font-size: 0.72rem; color: var(--accent); margin-top: 4px; font-weight: 600; }
.suggestion-play-btn {
  margin-top: 8px;
  background: var(--accent);
  color: #201a0c;
  border: none;
  border-radius: 6px;
  padding: 6px 10px;
  font-weight: 600;
  font-size: 0.8rem;
}
.suggestion-play-btn:disabled { opacity: 0.5; cursor: default; }

.opening-name { font-weight: 700; font-size: 1rem; }
.opening-meta { font-size: 0.8rem; color: var(--text-muted); margin-top: 3px; line-height: 1.4; }

.move-feed {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 480px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.move-feed-item {
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  padding: 7px 9px;
  cursor: pointer;
  transition: background 120ms;
}
.move-feed-item:hover { background: rgba(255,255,255,0.04); }
.move-feed-item.active { border-color: var(--accent); background: rgba(201,161,90,0.08); }

.move-feed-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.move-feed-ply { font-size: 0.72rem; color: var(--text-muted); min-width: 30px; }
.move-feed-san { font-weight: 700; }
.move-tag {
  font-size: 0.68rem;
  font-weight: 700;
  padding: 2px 6px;
  border-radius: 999px;
  color: #fff;
  white-space: nowrap;
}
.tag-best { background: var(--tag-best); }
.tag-brilliant { background: var(--tag-brilliant); }
.tag-excellent { background: var(--tag-excellent); }
.tag-good { background: var(--tag-good); }
.tag-book { background: var(--tag-book); }
.tag-inaccuracy { background: var(--tag-inaccuracy); color: #241a02; }
.tag-mistake { background: var(--tag-mistake); }
.tag-blunder { background: var(--tag-blunder); }
.tag-forced { background: var(--tag-forced); }

.concept-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.concept-chip {
  font-size: 0.65rem;
  background: var(--chip-bg);
  border: 1px solid var(--chip-border);
  color: var(--text-muted);
  padding: 1px 6px;
  border-radius: 999px;
}

/* ---------------- Promotion picker ---------------- */
.promotion-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 600;
}
.promotion-overlay.hidden { display: none; }
.promotion-box {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  padding: 16px;
  display: flex;
  gap: 10px;
}
.promotion-choice {
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--btn-bg);
  border: 1px solid var(--btn-border);
  border-radius: 8px;
  cursor: pointer;
}
.promotion-choice .piece-icon { width: 80%; height: 80%; }
.promotion-choice:hover { background: var(--accent); }
