:root {
    --bg:           #262421;
    --bg-2:         #312e2b;
    --bg-3:         #3a3735;
    --fg:           #f0f0ee;
    --muted:        #a8a4a0;
    --accent:       #81b64c;
    --accent-dark:  #5d8c34;
    --accent-darker:#446a26;
    --light-sq:     #ebecd0;
    --dark-sq:      #779556;
    --hint:         #f7d046;
    --wrong:        #d75d5d;
    --warn:         #ec9b35;
    --solved-bg:    rgba(129, 182, 76, 0.18);
    --wrong-bg:     rgba(215, 93, 93, 0.18);
    --warn-bg:      rgba(236, 155, 53, 0.18);
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--bg);
    color: var(--fg);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 15px;
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
    -webkit-tap-highlight-color: transparent;
    -webkit-text-size-adjust: 100%;
}

body { overflow-x: hidden; }

a { color: var(--accent); }

.muted { color: var(--muted); }
.small { font-size: 0.85rem; }

/* ---- Top bar ---- */

.topbar {
    background: var(--bg-2);
    border-bottom: 1px solid var(--bg-3);
    position: sticky;
    top: 0;
    z-index: 10;
}

.topbar-inner {
    max-width: 720px;
    margin: 0 auto;
    padding: 0.65rem 0.75rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: nowrap;
    min-height: 44px;
}

.brand {
    color: var(--fg);
    text-decoration: none;
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: 0.2px;
    white-space: nowrap;
}

.menu {
    flex: 1;
    display: flex;
    gap: 0.4rem;
    min-width: 0;
}

.menu a {
    color: var(--muted);
    text-decoration: none;
    padding: 0.45rem 0.7rem;
    border-radius: 6px;
    font-weight: 500;
    transition: background 0.15s, color 0.15s;
}

@media (hover: hover) {
    .menu a:hover { color: var(--fg); }
}

.menu a.active {
    color: var(--fg);
    background: var(--bg-3);
}

.who {
    color: var(--muted);
    font-size: 0.82rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 7em;
}

.badge {
    display: inline-block;
    padding: 0.18rem 0.55rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.6px;
    line-height: 1;
    vertical-align: middle;
}

.badge.admin-badge {
    background: var(--accent);
    color: #1d2614;
    box-shadow: 0 1px 0 var(--accent-darker);
}

@media (max-width: 380px) {
    .who { display: none; }
    .topbar-inner { gap: 0.5rem; }
}

/* ---- Page ---- */

.page {
    max-width: 720px;
    margin: 0 auto;
    padding: 0.75rem 0.75rem calc(0.75rem + env(safe-area-inset-bottom));
}

/* ---- Puzzle page ---- */

.puzzle-page {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    align-items: stretch;
    max-width: 520px;
    margin: 0 auto;
    width: 100%;
}

/* Tablet/desktop layout. Stats keeps its 880px container; the puzzle
   page sizes itself to whatever the board can be — same min(width,
   height-minus-chrome) calc — so the status bar and controls inside
   stretch to the board's width instead of the full viewport. The
   horizontal 5% gutter comes from puzzle-page being centered (margin:
   0 auto) and capped at 90vw, not from page padding. */
@media (min-width: 768px) {
    .page {
        max-width: 880px;
    }

    .page:has(.puzzle-page) {
        max-width: none;
        padding: 5vh 0;
    }

    .puzzle-page {
        max-width: min(90vw, calc(90vh - 11rem));
    }
}

.status-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.5rem 0.25rem;
}

.status {
    flex: 1;
    padding: 0.5rem 0.85rem;
    border-radius: 8px;
    background: var(--bg-2);
    font-size: 0.95rem;
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    /* Reserve enough vertical space for either a 1-line or 2-line
       message so the board below doesn't jump when the status changes
       (e.g. "Solved!" → "Solved (with help) · Click 'Next puzzle'…"). */
    min-height: 2.6em;
}

.status::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--muted);
    flex-shrink: 0;
}

.status[data-state="ready"]::before     { background: var(--accent); }
.status[data-state="thinking"]::before  { background: var(--warn);   animation: pulse-dot 1s infinite; }
.status[data-state="wrong"]::before     { background: var(--wrong); }
.status[data-state="solved"]::before    { background: var(--accent); }
.status[data-state="solved-help"]::before{ background: var(--warn); }
.status[data-state="failed"]::before    { background: var(--wrong); }
.status[data-state="shown"]::before     { background: var(--warn); }
.status[data-state="done"]::before      { background: var(--accent); }
.status[data-state="error"]::before     { background: var(--wrong); }

.status[data-state="wrong"]      { background: var(--wrong-bg); color: var(--wrong); cursor: pointer; }
.status[data-state="solved"]     { background: var(--solved-bg); color: var(--accent); }
.status[data-state="solved-help"]{ background: var(--warn-bg); color: var(--warn); }
.status[data-state="failed"]     { background: var(--wrong-bg); color: var(--wrong); }
.status[data-state="shown"]      { background: var(--warn-bg); color: var(--warn); }

@keyframes pulse-dot {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.4; }
}

.rating-pill {
    background: var(--bg-2);
    color: var(--fg);
    font-weight: 700;
    font-size: 0.95rem;
    padding: 0.5rem 0.85rem;
    border-radius: 8px;
    min-width: 60px;
    text-align: center;
    letter-spacing: 0.5px;
    position: relative;
}

/* Floats above the rating pill when an attempt updates the elo —
   green +N or red -N that fades up and out. */
.rating-delta {
    position: absolute;
    bottom: 100%;
    left: 0;
    right: 0;
    text-align: center;
    font-weight: 700;
    font-size: 0.95rem;
    letter-spacing: 0;
    opacity: 0;
    pointer-events: none;
}

.rating-delta[data-sign="pos"] { color: var(--accent); }
.rating-delta[data-sign="neg"] { color: var(--wrong); }

.rating-delta.flash {
    animation: ratingDeltaFlash 2.5s ease-out forwards;
}

@keyframes ratingDeltaFlash {
    0%   { opacity: 0; transform: translateY(0.5rem); }
    20%  { opacity: 1; transform: translateY(0); }
    80%  { opacity: 1; transform: translateY(-0.4rem); }
    100% { opacity: 0; transform: translateY(-1.2rem); }
}

/* ---- Board ---- */

.board {
    aspect-ratio: 1 / 1;
    width: 100%;
    background: var(--bg-2);
    border-radius: 6px;
    overflow: hidden;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
    user-select: none;
    -webkit-user-select: none;
    touch-action: manipulation;
}

/* The board sizes via base width: 100% + aspect-ratio: 1/1; on
   desktop the parent .puzzle-page is itself capped to the viewport-
   fitting size, so the board, status bar, and controls all share the
   same width. No .board override needed here. */

.board-svg {
    display: block;
    width: 100%;
    height: 100%;
}

/* Base square fills are set as SVG attributes in board.js so iOS Safari
   renders them even when CSS var() in fill is unreliable. The rules below
   only override for highlight states. */

.board-svg .sq.selected,
.board-svg .sq.last-from,
.board-svg .sq.last-to {
    fill: #f6f669 !important;
}

.board-svg .sq.last-from,
.board-svg .sq.last-to {
    fill-opacity: 1;
    fill: #cdd26a !important;
}

.board-svg .sq.dark.last-from,
.board-svg .sq.dark.last-to { fill: #aaa23a !important; }

.board-svg .sq.dark.selected { fill: #bbcb44 !important; }
.board-svg .sq.light.selected { fill: #f5f682 !important; }

.board-svg .sq.hint {
    fill: var(--hint) !important;
    animation: pulse 1.2s ease-in-out infinite;
}

.board-svg .sq.wrong { fill: var(--wrong) !important; }

@keyframes pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.55; }
}

.board-svg .sq { cursor: pointer; }

.board-svg .sq.drag-over {
    fill: rgba(255, 255, 255, 0.18) !important;
}

/* Shaded dots / capture rings drawn on legal target squares while a piece
   is selected (or being dragged). Pointer-events are off on the group so
   they never intercept clicks/drags meant for the underlying square. */
.board-svg .move-target {
    fill: rgba(0, 0, 0, 0.28);
}

.board-svg .move-target.capture {
    fill: none;
    stroke: rgba(0, 0, 0, 0.32);
}

.board-svg .drag-ghost {
    cursor: grabbing;
    opacity: 0.92;
}

/* While dragging we want the SVG to swallow touch instead of letting the
   browser pan the page — single-finger drags need to follow the cursor. */
.board-svg {
    touch-action: none;
}

.board-svg .coord {
    fill: rgba(0, 0, 0, 0.45);
    font-family: -apple-system, sans-serif;
    font-weight: 600;
    pointer-events: none;
    user-select: none;
    -webkit-user-select: none;
}

.board-svg .piece {
    pointer-events: none;
    user-select: none;
    -webkit-user-select: none;
}

/* ---- Controls ---- */

.controls {
    display: flex;
    gap: 0.4rem;
    margin-top: 0.25rem;
}

.controls button {
    flex: 1;
    background: var(--bg-2);
    color: var(--fg);
    border: none;
    border-radius: 8px;
    padding: 0.7rem 0.4rem;
    min-height: 48px;
    font-size: 1.15rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, transform 0.05s;
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.25);
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    -webkit-appearance: none;
    appearance: none;
    font-family: inherit;
    white-space: nowrap;
}

@media (hover: hover) {
    .controls button:hover:not(:disabled) {
        background: var(--bg-3);
    }

    .controls button.primary:hover:not(:disabled) {
        background: #94c95b;
    }
}

.controls button:active:not(:disabled) {
    transform: translateY(1px);
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}

.controls button:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}

.controls button.arrow {
    font-size: 1.9rem;
    line-height: 1;
}

.controls button.primary {
    background: var(--accent);
    color: #1d2614;
    box-shadow: 0 2px 0 var(--accent-darker);
    font-size: 0.95rem;
    flex: 1.4;
}

.controls button.primary:disabled {
    background: var(--bg-2);
    color: var(--muted);
    box-shadow: 0 2px 0 rgba(0, 0, 0, 0.25);
}

/* ---- Stats page ---- */

.summary-row {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

@media (max-width: 520px) {
    .summary-row {
        grid-template-columns: repeat(2, 1fr);
    }
}

.card {
    background: var(--bg-2);
    border-radius: 8px;
    padding: 0.85rem 1rem;
    margin-bottom: 0.75rem;
}

.card-header {
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 1.5px;
    font-size: 0.7rem;
    margin-bottom: 0.6rem;
    font-weight: 600;
}

.card.stat {
    text-align: center;
    padding: 0.85rem 0.5rem;
    margin-bottom: 0;
}

.stat-num {
    font-size: 1.7rem;
    color: var(--accent);
    font-weight: 700;
    line-height: 1;
}

.stat-lbl {
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 1px;
    font-size: 0.65rem;
    margin-top: 0.4rem;
    font-weight: 600;
}

.two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

@media (max-width: 600px) {
    .two-col {
        grid-template-columns: 1fr;
    }
}

.activity {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 50px;
}

.activity .bar {
    flex: 1;
    background: var(--accent-darker);
    border-radius: 2px 2px 0 0;
    min-height: 4px;
    transition: background 0.15s;
}

@media (hover: hover) {
    .activity .bar:hover { background: var(--accent); }
}

.activity .bar[data-n="0"] { background: var(--bg-3); }

table.themes {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
}

table.themes th,
table.themes td {
    text-align: left;
    padding: 0.45rem 0.5rem;
    border-bottom: 1px solid var(--bg-3);
}

table.themes th {
    color: var(--muted);
    font-weight: 600;
    text-transform: uppercase;
    font-size: 0.68rem;
    letter-spacing: 1px;
}

table.themes tr:last-child td {
    border-bottom: none;
}

table.themes td:nth-child(2),
table.themes td:nth-child(3),
table.themes td:nth-child(4),
table.themes td:nth-child(5) {
    font-variant-numeric: tabular-nums;
    color: var(--accent);
}

/* Admin "All users" table reuses .themes for layout but its column
   meanings differ — undo the nth-child accent on cols 2–5 (FP / IP /
   dates) and apply tabular nums to the numeric trailing columns. */
.card.admin {
    overflow-x: auto;
}

.card.admin table.themes {
    min-width: 720px;
}

.card.admin table.themes td.mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.78rem;
}

.card.admin table.themes td:nth-child(2),
.card.admin table.themes td:nth-child(3),
.card.admin table.themes td:nth-child(4),
.card.admin table.themes td:nth-child(5) {
    color: inherit;
    font-variant-numeric: normal;
}

.card.admin table.themes td:nth-child(6),
.card.admin table.themes td:nth-child(7),
.card.admin table.themes td:nth-child(8),
.card.admin table.themes td:nth-child(9),
.card.admin table.themes td:nth-child(10) {
    font-variant-numeric: tabular-nums;
    color: var(--accent);
}

.card.admin tr.self td {
    background: rgba(255, 215, 0, 0.08);
}

.card.admin .geo-link,
.card.admin .geo-text {
    font-family: -apple-system, system-ui, sans-serif;
    font-size: 0.74rem;
    font-weight: 400;
}

.card.admin .geo-link {
    color: var(--accent);
    text-decoration: none;
}

.card.admin .geo-link:hover {
    text-decoration: underline;
}

/* ---- Error panel ---- */

.err {
    background: var(--wrong-bg);
    color: var(--wrong);
    border-radius: 8px;
    padding: 1rem 1.25rem;
}

.err h2 { margin-top: 0; }

.err code {
    background: rgba(0, 0, 0, 0.3);
    padding: 1px 6px;
    border-radius: 3px;
}

/* ---- Analysis page ---- */

.analysis-page {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.analysis-upload {
    background: var(--bg-2);
    border-radius: 8px;
    padding: 0.85rem 1rem;
}

.upload-btn {
    display: inline-block;
    background: var(--accent);
    color: #1d2614;
    padding: 0.55rem 1rem;
    border-radius: 6px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s;
}

.upload-btn:has(input:disabled),
button.upload-btn:disabled {
    background: var(--bg-3);
    color: var(--muted);
    cursor: not-allowed;
}

.upload-btn input[type="file"] {
    display: none;
}

.upload-btn-secondary {
    background: var(--bg-3);
    color: var(--fg);
    border: none;
    font-family: inherit;
    font-size: inherit;
    margin-left: 0.5rem;
}

.upload-btn-secondary:not(:disabled):hover {
    background: #4a4744;
}

.analysis-diagnostics {
    background: var(--bg-2);
    border-radius: 8px;
    padding: 0.5rem 0.75rem;
}

.analysis-diagnostics > summary {
    cursor: pointer;
    color: var(--muted);
    font-size: 0.85rem;
    font-weight: 600;
    padding: 0.25rem 0;
    user-select: none;
}

.analysis-diagnostics[open] > summary {
    margin-bottom: 0.6rem;
}

.analysis-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0.75rem;
}

.analysis-col {
    background: var(--bg-2);
    border-radius: 8px;
    padding: 0.6rem 0.75rem 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 0;
}

.analysis-col h3 {
    margin: 0;
    font-size: 0.9rem;
    color: var(--muted);
    font-weight: 600;
}

.analysis-canvas {
    width: 100%;
    height: auto;
    background: var(--bg-3);
    border-radius: 4px;
    display: block;
}

.analysis-canvas-256 {
    image-rendering: pixelated;
}

.analysis-board-wrap {
    background: var(--bg-2);
    border-radius: 8px;
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    max-width: 520px;
    width: 100%;
    margin: 0 auto;
}

.analysis-board-wrap h3 {
    margin: 0;
    font-size: 0.9rem;
    color: var(--muted);
    font-weight: 600;
}

.fen-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.fen-label {
    color: var(--muted);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.5px;
}

.fen-input {
    flex: 1;
    min-width: 0;
    background: var(--bg-3);
    color: var(--fg);
    border: 1px solid transparent;
    border-radius: 4px;
    padding: 0.45rem 0.6rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.85rem;
}

.fen-input:focus {
    outline: none;
    border-color: var(--accent);
}

.position-editor {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    background: var(--bg-2);
    border-radius: 8px;
    padding: 0.5rem 0.75rem;
}

.position-editor > summary {
    cursor: pointer;
    color: var(--muted);
    font-size: 0.85rem;
    font-weight: 600;
    padding: 0.25rem 0;
    user-select: none;
}

.position-editor[open] > summary {
    color: var(--accent);
}

.palette {
    display: grid;
    grid-template-columns: repeat(13, 1fr);
    gap: 0.25rem;
    padding: 0.4rem;
    background: var(--bg-3);
    border-radius: 6px;
}

.palette-tile {
    aspect-ratio: 1 / 1;
    border: 2px solid transparent;
    border-radius: 4px;
    background-color: var(--bg-2);
    cursor: pointer;
    padding: 0;
    min-width: 0;
    appearance: none;
    -webkit-appearance: none;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.palette-tile > svg {
    display: block;
    width: 100%;
    height: 100%;
}

.palette-tile.active {
    border-color: var(--accent);
    background-color: rgba(129, 182, 76, 0.2);
}

.palette-eraser {
    color: var(--muted);
    font-size: 1.2rem;
    line-height: 1;
    font-weight: 700;
}

.palette-eraser.active {
    color: var(--accent);
}

.editor-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.stm-toggle {
    border: none;
    padding: 0;
    margin: 0;
    display: flex;
    gap: 0.75rem;
    font-size: 0.85rem;
    color: var(--muted);
}

.stm-toggle label {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    cursor: pointer;
}

.stm-toggle input[type="radio"] {
    accent-color: var(--accent);
}

.editor-actions {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
}

/* Override the upload-btn margin-left for action rows where they're
   spaced via flex gap instead. */
.editor-actions .upload-btn-secondary,
.fen-row .upload-btn-secondary {
    margin-left: 0;
    padding: 0.4rem 0.7rem;
    font-size: 0.85rem;
}

.board-with-eval {
    display: flex;
    gap: 0.5rem;
    align-items: stretch;
}

/* Match the analysis-page play-controls row to the board's horizontal
   span — offset by the eval-bar column width (36px) + its 0.5rem gap. */
.play-controls {
    margin-left: calc(36px + 0.5rem);
}

.board-with-eval .board {
    flex: 1;
    min-width: 0;
}

.eval-bar {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 36px;
    flex-shrink: 0;
    gap: 0.3rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75rem;
    color: var(--muted);
}

.eval-readout {
    font-weight: 700;
    color: var(--fg);
    font-size: 0.85rem;
    text-align: center;
    min-height: 1.1em;
}

.eval-track {
    flex: 1;
    width: 16px;
    background: #1d1c1a;       /* black side */
    border-radius: 4px;
    overflow: hidden;
    position: relative;
    box-shadow: inset 0 0 0 1px var(--bg-3);
}

.eval-white {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: #f0f0ee;       /* white side, fills from bottom */
    transition: height 0.18s ease-out;
}

/* Mate-for-white: fully white bar; mate-for-black: fully black. */
.eval-bar[data-mate="w"] .eval-white { height: 100% !important; }
.eval-bar[data-mate="b"] .eval-white { height: 0%   !important; }

.eval-depth {
    min-height: 1em;
    text-align: center;
}
