:root {
  --bg: #faf7f2;
  --panel: #ffffff;
  --ink: #2b2320;
  --ink-soft: #6b5f57;
  --accent: #c1440e;
  --accent-soft: #e8b34c;
  --line: #e7ddcf;
  --good: #2f7d4f;
  --bad: #b3261e;
  --square-light: #f0d9b5;
  --square-dark: #b58863;
  --radius: 10px;
  --sq-size: 88px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  min-height: 100vh;
}

.topbar {
  background: var(--ink);
  color: #fff;
  position: sticky;
  top: 0;
  z-index: 10;
}
.topbar-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 24px;
}
.brand { font-weight: 700; font-size: 1.1rem; letter-spacing: 0.2px; }
.nav { display: flex; align-items: center; gap: 18px; flex: 1; }
.nav.hidden { display: none; }
.nav a {
  color: #f1e9df;
  text-decoration: none;
  font-size: 0.95rem;
  opacity: 0.85;
}
.nav a.active, .nav a:hover { opacity: 1; text-decoration: underline; }
.nav .spacer { flex: 1; }
.whoami { color: #cbbfae; font-size: 0.9rem; }
.link-btn {
  background: none;
  border: none;
  color: #f1e9df;
  cursor: pointer;
  font-size: 0.9rem;
  text-decoration: underline;
  padding: 0;
}

.app { max-width: 1200px; margin: 0 auto; padding: 28px 16px 80px; }

.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 22px;
  margin-bottom: 20px;
}

h1 { font-size: 1.5rem; margin: 0 0 4px; }
h2 { font-size: 1.15rem; margin: 0 0 12px; }
p.lead { color: var(--ink-soft); margin-top: 0; }

.auth-wrap {
  max-width: 380px;
  margin: 40px auto;
}
.field { margin-bottom: 14px; display: flex; flex-direction: column; gap: 6px; }
.field label { font-size: 0.85rem; color: var(--ink-soft); }
.field input {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  font-size: 1rem;
}
.btn {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  border: none;
  padding: 10px 18px;
  border-radius: 8px;
  font-size: 0.95rem;
  cursor: pointer;
  font-weight: 600;
  text-decoration: none;
  text-align: center;
}
.btn:hover { filter: brightness(1.05); }
.btn:disabled { opacity: 0.5; cursor: default; }
.btn.secondary {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--accent);
}
.btn.block { width: 100%; }
.error-msg { color: var(--bad); font-size: 0.9rem; min-height: 1.2em; }
.switch-line { text-align: center; margin-top: 14px; font-size: 0.9rem; color: var(--ink-soft); }
.switch-line button { background: none; border: none; color: var(--accent); cursor: pointer; text-decoration: underline; font-size: 0.9rem; }

.level-picker { margin-top: 4px; }
.level-picker-label { font-size: 0.9rem; color: var(--ink-soft); margin-bottom: 8px; }
.level-picker-options { display: flex; gap: 10px; flex-wrap: wrap; }
.level-btn { line-height: 1.5; padding: 8px 14px; text-align: center; }
.level-btn .level-desc { font-size: 0.75rem; color: var(--ink-soft); font-weight: 400; }

.series-card { margin-bottom: 18px; }
.round-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
  margin-top: 10px;
}
.round-tile {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px;
  text-align: center;
  background: #fdfbf7;
}
.round-tile .num { font-size: 0.75rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.5px; }
.round-tile .label { font-weight: 600; margin: 2px 0 6px; }
.round-tile .status-badge {
  display: inline-block;
  font-size: 0.72rem;
  padding: 2px 8px;
  border-radius: 999px;
  margin-bottom: 6px;
}
.status-completed { background: #e2f3e7; color: var(--good); }
.status-active { background: #fdf1de; color: #92600f; }
.status-not_started { background: #f0ede8; color: var(--ink-soft); }
.round-tile .timer { font-variant-numeric: tabular-nums; font-size: 0.85rem; color: var(--ink); }
.round-tile .cooldown { font-size: 0.78rem; color: var(--ink-soft); margin-top: 4px; }
.round-tile button { margin-top: 8px; }

.puzzle-nav { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px; }
.puzzle-pip {
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.8rem;
  cursor: pointer;
  background: #fff;
  flex-shrink: 0;
}
.puzzle-pip.current { border-color: var(--accent); color: var(--accent); font-weight: 700; }
.puzzle-pip.solved { background: var(--good); border-color: var(--good); color: #fff; }
.puzzle-pip.pending { opacity: 0.45; cursor: default; }

.back-link { display: inline-block; margin-bottom: 14px; font-size: 0.9rem; }

.round-shell { display: flex; align-items: flex-start; gap: 20px; }

.round-sidebar {
  flex: 0 0 156px;
  width: 156px;
  position: sticky;
  top: 70px;
  padding: 18px 12px;
  text-align: center;
}
.round-sidebar-title { font-size: 1.1rem; font-weight: 700; }
.round-sidebar-label { color: var(--ink-soft); font-size: 0.82rem; margin-bottom: 10px; }
.round-sidebar-score { font-size: 1.25rem; font-weight: 700; color: var(--accent); margin-bottom: 14px; }
.round-sidebar-done { margin-top: 14px; font-size: 0.82rem; color: var(--good); font-weight: 600; }

.round-progress-readout { width: 100%; margin-top: 4px; }
.round-progress-count { font-size: 0.95rem; font-weight: 600; margin-bottom: 8px; }
.round-progress-readout .progress-track { margin-bottom: 6px; }
.round-progress-solved { font-size: 0.8rem; color: var(--ink-soft); margin-bottom: 10px; }
.round-progress-nav { display: flex; gap: 8px; justify-content: center; }
.round-progress-nav .btn { flex: 1 1 auto; padding: 6px 8px; font-size: 0.82rem; }

.opponent-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-size: 0.8rem;
  color: var(--ink-soft);
  cursor: pointer;
  text-align: left;
}
.opponent-toggle input { margin: 0; flex-shrink: 0; }

.round-main { flex: 1 1 auto; min-width: 0; }

.solve-layout { display: flex; gap: 32px; flex-wrap: wrap; align-items: flex-start; }
.board-wrap { flex: 0 0 auto; position: sticky; top: 70px; }
/* Fixed-width slots flank the board -- one always to its left, one always
   to its right -- and the turn panel (indicator + hint/analyze button) is
   moved between them in JS as the side to move changes, rather than the
   whole layout being reordered. Because both slots always reserve their
   width whether or not they currently hold the panel, the board's own
   position never shifts: White to move puts the panel in the left slot and
   leaves the right one empty (but still reserved-width); Black to move is
   the mirror image.

   72px is deliberate, and sized to ALWAYS fit rather than just at one
   tested window width: the page itself never renders wider than .app's
   1200px max-width, so however wide the browser window actually is, the
   horizontal budget available to this row tops out at a fixed number once
   the window is at least 1200px wide. Measured at that cap: 1200 - .app's
   32px padding - the sidebar's 156px - its 20px gap - the surrounding
   .panel's 44px padding - the board's own 714px - the rank-labels column
   beside it (16px, see .rank-labels below -- the board-frame that holds
   the board and its coordinate labels is 16px wider than the board alone)
   - two 32px slot gaps leaves 160px for the two slots together, i.e. 80px
   each at most. 72px fits with a few px to spare. Two things silently ate
   into this budget in earlier passes and are worth remembering: the old
   150px-per-slot design didn't budget for BOTH slots being reserved at
   once (only one slot existed at a time), and adding the rank-labels
   column later shrank the remaining budget by exactly its own width --
   both wrapped the right slot onto its own line, invisible when empty but
   visibly stranded below everything else the moment real content (Black
   to move, or the coordinate labels) landed in the squeezed side. Below
   the 1200px cap the budget only gets tighter, which is what the
   max-width: 1200px breakpoint below is for. */
.turn-slot {
  flex: 0 0 72px;
  /* Overrides the flex default of min-width: auto, which otherwise lets a
     slot's unbreakable content (the hint button's text, mainly) grow it
     past its 72px flex-basis while an EMPTY slot sits at exactly 72px -- a
     several-px mismatch between the two states that would itself shift
     the board by that amount the moment the panel moves from one slot to
     the other. Pinning both states to the identical, literal 72px is what
     makes the board's position exact, not just close. */
  min-width: 0;
  overflow: hidden;
  /* Sticky, and pinned to the same top offset as .board-wrap, so the slot
     (and whichever side currently holds the turn panel) scrolls together
     with the board instead of the board freezing in place on scroll while
     the panel -- previously a plain static-positioned element -- drifted
     away underneath it. */
  position: sticky;
  top: 70px;
}

@media (max-width: 1200px) {
  .round-shell { flex-direction: column; }
  .round-sidebar {
    width: 100%;
    flex: 1 1 auto;
    position: static;
    text-align: left;
    padding: 14px 16px;
  }
  .board-wrap { position: static; }
  /* Stacked layout has no horizontal "shift" to avoid, so the fixed-width,
     sticky slot is dropped in favor of a normal full-width, non-sticky row
     -- an empty slot then just collapses to zero height instead of leaving
     a gap, and there's no board to visually detach from since everything
     scrolls together in one column already. This
     breakpoint (1200px, matching .app's own max-width exactly) is
     intentionally much wider than a typical "mobile" breakpoint: below
     .app's own max-width there's strictly less horizontal budget than the
     168px the two reserved slots need (see the .turn-slot comment above),
     so anything at or under that width falls back to this safe
     single-column layout rather than risking the same wrap. */
  .turn-slot { flex: 1 1 100%; position: static; top: auto; }
  .turn-panel {
    flex: 1 1 100%;
    flex-direction: row;
    align-items: center;
    padding-top: 0;
  }
  .turn-indicator { flex: 1 1 auto; }
  .hint-btn { width: auto; flex: 0 0 auto; }
}
/* Coordinate frame around the board -- a rank-labels column to its left and
   a file-labels row underneath, both OUTSIDE the board itself rather than
   overlaid on its corner squares. Padding on both label strips matches the
   board's own 5px border so a label lines up with the square it names
   instead of the border; the file-labels row is additionally pushed right
   by the rank-labels column's width so it starts under the board, not
   under the rank labels. */
.board-frame { display: inline-flex; flex-direction: column; }
.board-row { display: flex; }
.rank-labels {
  display: flex;
  flex-direction: column;
  width: 16px;
  padding: 5px 0;
  box-sizing: border-box;
}
.rank-labels span {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink-soft);
}
.file-labels {
  display: flex;
  margin-left: 16px;
  padding: 0 5px;
  box-sizing: border-box;
}
.file-labels span {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-top: 4px;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink-soft);
}

.board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(8, var(--sq-size));
  grid-template-rows: repeat(8, var(--sq-size));
  border: 5px solid #4a3728;
  border-radius: 6px;
  overflow: hidden;
  user-select: none;
}
@media (max-width: 1100px) {
  :root { --sq-size: 72px; }
}
@media (max-width: 600px) {
  .board { grid-template-columns: repeat(8, 9.8vw); grid-template-rows: repeat(8, 9.8vw); }
}
.sq {
  display: flex; align-items: center; justify-content: center;
  position: relative;
  cursor: pointer;
  touch-action: none;
}
.sq.light { background: var(--square-light); }
.sq.dark { background: var(--square-dark); }
.sq.selected { outline: 4px solid var(--accent-soft); outline-offset: -4px; }
.sq.drag-hover { outline: 4px solid var(--accent); outline-offset: -4px; }
.sq.last-move::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(255, 214, 0, 0.38);
  pointer-events: none;
}
.sq.legal::after {
  content: "";
  position: absolute;
  width: 28%; height: 28%;
  border-radius: 50%;
  background: rgba(0,0,0,0.25);
  pointer-events: none;
}
.sq.legal.has-piece::after {
  width: 100%; height: 100%; border-radius: 0;
  background: rgba(193,68,14,0.35);
}
.piece-svg {
  width: 84%;
  height: 84%;
  display: block;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  filter: drop-shadow(0 3px 2px rgba(0,0,0,0.35));
}
.piece-svg.piece-hidden { visibility: hidden; }
.arrow-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.drag-ghost {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 1000;
  filter: drop-shadow(0 8px 12px rgba(0,0,0,0.45));
  opacity: 0.95;
}

.info-panel { flex: 1 1 260px; min-width: 240px; }
.game-title { font-weight: 700; margin-bottom: 2px; }
.game-meta { color: var(--ink-soft); font-size: 0.88rem; margin-bottom: 14px; }
.score-line { font-size: 1.05rem; margin-bottom: 10px; }
.feedback { min-height: 1.4em; font-size: 0.92rem; margin-bottom: 10px; }
.feedback.good { color: var(--good); }
.feedback.bad { color: var(--bad); }
.feedback.hint { color: #1e6fd9; }

.hint-btn { width: 100%; }
.progress-track { height: 6px; background: var(--line); border-radius: 4px; overflow: hidden; margin-bottom: 16px; }
.progress-fill { height: 100%; background: var(--accent); }

.turn-panel {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 14px;
  padding-top: 6px;
}
.turn-indicator {
  display: inline-block;
  text-align: center;
  font-size: 1.3rem;
  font-weight: 700;
  padding: 10px 14px;
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
}

.history-section {
  margin-top: 24px;
  border-top: 1px solid var(--line);
  padding-top: 14px;
}
.history-section summary {
  cursor: pointer;
  font-size: 0.95rem;
  padding: 4px 0;
  user-select: none;
}
.history-section summary strong { color: var(--accent); }
.history-section summary:hover { color: var(--accent); }
.history-body { margin-top: 14px; max-height: 360px; overflow-y: auto; overflow-x: auto; }
.history-empty { color: var(--ink-soft); font-size: 0.9rem; }
table.history-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; white-space: nowrap; }
table.history-table th, table.history-table td { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--line); }
table.history-table th { color: var(--ink-soft); font-weight: 600; font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.4px; }
.history-dash { color: var(--ink-soft); opacity: 0.6; font-size: 0.82rem; }
.history-inprogress { color: var(--accent); font-style: italic; }

/* A per-round band breakdown can add up to 7 extra columns (one per rating
   group a level draws from -- see LEVEL_GROUPS), which is more than a
   narrow screen can show at once; this scrolls horizontally instead of
   squeezing every column or wrapping the table's own layout. */
.table-scroll { overflow-x: auto; }
table.scores-table { width: 100%; border-collapse: collapse; font-size: 0.92rem; white-space: nowrap; }
table.scores-table th, table.scores-table td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line); }
table.scores-table th { color: var(--ink-soft); font-weight: 600; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.4px; }
.score-pct { color: var(--ink-soft); font-size: 0.85em; }

.empty-state { text-align: center; padding: 40px 20px; color: var(--ink-soft); }
.loading { text-align: center; padding: 60px 0; color: var(--ink-soft); }