:root {
    /* Denim-blue palette — quiet background, indigo accent, white tiles. */
    --bg: #eef2f7;          /* pale blue-gray page background */
    --fg: #1f2a3a;          /* dark navy ink */
    --accent: #3d5a80;      /* denim blue — links, headings, buttons */
    --accent-dark: #2c4262; /* hover state */
    --tile: #ffffff;        /* clean white tiles */
    --tile-edge: #b9c4d4;   /* soft blue-gray border */
    --tile-selected: #cfe0f4;  /* light denim wash for actively selected */
    --tile-path: #a9c4ec;      /* slightly stronger denim for missed-word path */
    --ok: #2f7d4f;          /* keep green for success, tuned a touch cooler */
    --bad: #b3261e;
    --muted: #6b7689;       /* blue-gray text */
    --card: #ffffff;        /* card backgrounds match tiles */
}

* { box-sizing: border-box; }
body {
    margin: 0;
    font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif;
    background: var(--bg);
    color: var(--fg);
}
.page { max-width: none; margin: 0; padding: 1.5rem 2rem 4rem; }
.page.narrow { max-width: 420px; margin: 0 auto; }

.top {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center; gap: 1rem;
    margin-bottom: 1.5rem; border-bottom: 1px solid var(--tile-edge);
    padding-bottom: .75rem;
}
.top h1 { margin: 0; font-size: 1.4rem; color: var(--accent); }
/* Brand mark (left) — logo + "Clean Dirt Games", links home. */
.top .brand {
    justify-self: start; display: inline-flex; align-items: center; gap: .5rem;
    font-size: 1.3rem; font-weight: 800; color: var(--accent);
    text-decoration: none; letter-spacing: .01em; white-space: nowrap;
}
.top .brand:hover { text-decoration: none; opacity: .9; }
.cdg-logo { width: 1.75em; height: 1.75em; flex: none; display: block; }
/* The specific game's name, centered. */
.top .game-title {
    justify-self: center; margin: 0; text-align: center;
    font-size: 1.7rem; font-weight: 800; color: var(--accent-dark, var(--accent));
    letter-spacing: .02em;
}
.top nav {
    justify-self: end; display: flex; gap: 1rem; align-items: center;
    flex-wrap: wrap; justify-content: flex-end;
}
.top nav a { color: var(--accent); text-decoration: none; }
.top nav a:hover { text-decoration: underline; }
.who { color: var(--muted); font-size: .9rem; margin-right: .5rem; }

@media (max-width: 820px) {
    .top { grid-template-columns: 1fr; justify-items: center; text-align: center; }
    .top .brand, .top .game-title, .top nav { justify-self: center; }
}

/* Board flash: green when every cell is used, denim-blue on a 50%+ finish. */
#board { position: relative; }
#board.flash-green::after,
#board.flash-blue::after {
    content: ''; position: absolute; inset: -10px; border-radius: 16px;
    pointer-events: none; animation: board-flash 1s ease-out;
}
#board.flash-green::after { --fc: 52, 199, 89; }
#board.flash-blue::after  { --fc: 28, 96, 189; }    /* denim blue */
@keyframes board-flash {
    0%   { box-shadow: 0 0 0 0 rgba(var(--fc), 0);   background: rgba(var(--fc), 0); }
    22%  { box-shadow: 0 0 0 18px rgba(var(--fc), .55), 0 0 60px rgba(var(--fc), .75);
           background: rgba(var(--fc), .20); }
    100% { box-shadow: 0 0 0 0 rgba(var(--fc), 0);   background: rgba(var(--fc), 0); }
}

.card {
    background: var(--card);
    border: 1px solid var(--tile-edge);
    border-radius: 8px;
    padding: 1.25rem 1.5rem;
    margin-bottom: 1rem;
}
.card label { display: block; margin: .75rem 0; }
.card input {
    display: block; width: 100%; padding: .5rem;
    font-size: 1rem; margin-top: .25rem;
    border: 1px solid var(--tile-edge); border-radius: 4px;
    background: white;
}
.card button, .btn {
    display: inline-block; padding: .6rem 1.2rem;
    font-size: 1rem; font-weight: 600; cursor: pointer;
    background: var(--accent); color: white;
    border: 0; border-radius: 4px; text-decoration: none;
}
.card button:hover, .btn:hover { background: var(--accent-dark); }

.error {
    background: #fcebea; color: var(--bad);
    padding: .75rem 1rem; border-radius: 4px; margin-bottom: 1rem;
    border: 1px solid #f3c3c0;
}

.install-log { padding-left: 1.2rem; }
.install-log li { margin: .3rem 0; }
.install-log li.ok { color: var(--ok); }
.install-log li.fail { color: var(--bad); }

/* HUD ---------------------------------------------------------------- */
.hud {
    display: flex; gap: 1.5rem; justify-content: center;
    margin-bottom: 1rem; font-variant-numeric: tabular-nums;
}
.hud-cell {
    background: var(--card); border: 1px solid var(--tile-edge);
    border-radius: 6px; padding: .5rem 1rem; min-width: 90px;
    text-align: center;
}
.hud-cell .label {
    display: block; font-size: .75rem; color: var(--muted);
    text-transform: uppercase; letter-spacing: .05em;
}
.hud-cell #timer, .hud-cell #score, .hud-cell #found-count {
    font-size: 1.5rem; font-weight: 700;
}
#timer.warn { color: var(--bad); }

/* Board -------------------------------------------------------------- */
.board-wrap { display: flex; justify-content: center; margin: 1rem 0; }
#board {
    display: grid;
    grid-template-columns: repeat(4, 9rem);
    grid-template-rows:    repeat(4, 9rem);
    gap: .75rem;
    user-select: none;
    position: relative;            /* anchor the SVG overlay below */
}
/* SVG line overlay — drawn on top of all tiles. pointer-events: none so
   mouse drags still reach the cells beneath. */
#board-lines {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;
    overflow: visible;
    z-index: 10;
}
.path-line {
    stroke: var(--ok);
    stroke-width: 8;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: .85;
    filter: drop-shadow(0 0 4px rgba(46, 125, 50, .55));
}

/* Click-a-word definition popup. Positioned by JS near the clicked item. */
.def-popup {
    position: absolute;
    background: var(--card);
    border: 1px solid var(--tile-edge);
    border-radius: 8px;
    padding: .65rem .85rem;
    max-width: 22rem;
    min-width: 12rem;
    box-shadow: 0 6px 18px rgba(0,0,0,.18);
    z-index: 2000;
    font-size: .95rem;
    line-height: 1.35;
}
.def-popup .def-word {
    font-weight: 700;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: .04em;
    margin-bottom: .3rem;
}
.def-popup .def-text { color: var(--fg); }
.def-popup .def-text.def-none { color: var(--muted); font-style: italic; }
#found-list li[data-word], #missed-list li[data-word] { cursor: pointer; }
#found-list li[data-word]:hover, #missed-list li[data-word]:hover {
    background: rgba(61, 90, 128, .14);
}
.cell {
    background: linear-gradient(180deg, #ffffff 0%, #d9e1ec 100%);
    border: 1px solid var(--tile-edge);
    border-radius: 12px;
    display: flex; align-items: center; justify-content: center;
    font-size: 3rem; font-weight: 700; cursor: pointer;
    transition: transform .08s, box-shadow .08s, background .08s;
    position: relative;
    /* 3D bevel: inner top highlight + inner bottom shadow + outer drop. */
    box-shadow:
        inset 0 2px 0 rgba(255, 255, 255, .85),
        inset 0 -3px 0 rgba(0, 0, 0, .08),
        inset 0 0 0 1px rgba(255, 255, 255, .4),
        0 4px 6px rgba(31, 42, 58, .15),
        0 2px 3px rgba(31, 42, 58, .10);
}
.cell:hover {
    background: linear-gradient(180deg, #ffffff 0%, #c8d5e6 100%);
    transform: translateY(-1px);
    box-shadow:
        inset 0 2px 0 rgba(255, 255, 255, .9),
        inset 0 -3px 0 rgba(0, 0, 0, .08),
        inset 0 0 0 1px rgba(255, 255, 255, .5),
        0 6px 10px rgba(31, 42, 58, .18),
        0 2px 4px rgba(31, 42, 58, .12);
}
.cell.selected {
    background: linear-gradient(180deg, #cfe0f4 0%, #a9c4ec 100%);
    transform: translateY(2px);
    box-shadow:
        inset 0 3px 6px rgba(31, 42, 58, .15),
        inset 0 -1px 0 rgba(255, 255, 255, .35),
        0 0 0 4px var(--ok),
        0 0 14px rgba(46, 125, 50, .55);
}
/* Persistent green outline on any cell that's been part of an accepted
   word this round. Cleared when a new game starts. Uses outline (not
   box-shadow) so it composes cleanly with the .selected ring above. */
.cell.used {
    outline: 3px solid var(--ok);
    outline-offset: -3px;
}
.cell.path     { background: var(--tile-path); }
.cell .seq {
    position: absolute; top: 2px; left: 4px;
    font-size: .65rem; font-weight: 500; color: var(--muted);
}
/* Traditional Scrabble letter value, lower-right corner. Reference only —
   does not affect Boggle's length-based scoring. */
.cell .letter-value {
    position: absolute; bottom: 4px; right: 7px;
    font-size: .85rem; font-weight: 600; color: var(--muted);
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

/* Entry / buttons ---------------------------------------------------- */
.entry { text-align: center; margin-top: 1rem; }
.current-word {
    font-size: 1.5rem; font-weight: 700; letter-spacing: .1em;
    min-height: 2.2rem; padding: .4rem; color: var(--accent);
}
.actions { display: flex; justify-content: center; gap: .5rem; flex-wrap: wrap; }
.actions button {
    padding: .5rem 1rem; font-size: .95rem; cursor: pointer;
    background: var(--accent); color: white; border: 0; border-radius: 4px;
}
.actions button:disabled { background: #bbb; cursor: default; }
.actions button:hover:not(:disabled) { background: var(--accent-dark); }

.toast {
    margin-top: .75rem; min-height: 1.2rem;
    font-weight: 600; color: var(--muted);
}
.toast.ok  { color: var(--ok); }
.toast.bad { color: var(--bad); }

/* Success flash --------------------------------------------------------
   On accepted submit, briefly pulses ONLY the cells in the accepted
   word's path — green ring expands, light tint, then fades back. */
@keyframes cell-success-flash {
    0%, 100% {
        box-shadow:
            inset 0 2px 0 rgba(255, 255, 255, .85),
            inset 0 -3px 0 rgba(0, 0, 0, .08),
            inset 0 0 0 1px rgba(255, 255, 255, .4),
            0 4px 6px rgba(31, 42, 58, .15),
            0 2px 3px rgba(31, 42, 58, .10),
            0 0 0 0 rgba(46, 125, 50, 0);
    }
    25% {
        box-shadow:
            inset 0 2px 0 rgba(255, 255, 255, .85),
            inset 0 -3px 0 rgba(0, 0, 0, .08),
            inset 0 0 0 1px rgba(255, 255, 255, .4),
            0 4px 6px rgba(31, 42, 58, .15),
            0 2px 3px rgba(31, 42, 58, .10),
            0 0 0 6px var(--ok),
            0 0 22px rgba(46, 125, 50, .7);
    }
}
.cell.success-flash {
    animation: cell-success-flash .55s ease-out;
}

/* Easter egg: NITZ — each cell flashes a rainbow ring then sparkles. */
@keyframes nitz-rainbow {
    0% {
        box-shadow:
            inset 0 2px 0 rgba(255, 255, 255, .85),
            inset 0 -3px 0 rgba(0, 0, 0, .08),
            0 4px 6px rgba(31, 42, 58, .15),
            0 0 0 0 rgba(0, 0, 0, 0);
    }
    25% {
        box-shadow:
            inset 0 2px 0 rgba(255, 255, 255, .85),
            inset 0 -3px 0 rgba(0, 0, 0, .08),
            0 4px 6px rgba(31, 42, 58, .15),
            0 0 0 7px var(--nitz-color, gold),
            0 0 28px var(--nitz-color, gold);
    }
    100% {
        box-shadow:
            inset 0 2px 0 rgba(255, 255, 255, .85),
            inset 0 -3px 0 rgba(0, 0, 0, .08),
            0 4px 6px rgba(31, 42, 58, .15),
            0 0 0 0 rgba(0, 0, 0, 0);
    }
}
.cell.nitz-flash {
    animation: nitz-rainbow 1.3s ease-out;
}
@keyframes sparkle-fly {
    0% {
        transform: translate(-50%, -50%) scale(.4) rotate(0deg);
        opacity: 0;
    }
    20% {
        transform: translate(-50%, -50%) scale(1.1) rotate(45deg);
        opacity: 1;
    }
    100% {
        transform: translate(calc(-50% + var(--dx, 0px)),
                             calc(-50% + var(--dy, 0px)))
                   scale(.9) rotate(540deg);
        opacity: 0;
    }
}
.sparkle {
    position: fixed;
    font-size: 1.75rem;
    pointer-events: none;
    z-index: 9999;
    animation: sparkle-fly 1.4s ease-out forwards;
    will-change: transform, opacity;
}

/* Easter egg: TOVE — a big heart blooms and floats up. */
@keyframes tove-heart-bloom {
    0%   { transform: translate(-50%, -50%) scale(.2); opacity: 0; }
    25%  { transform: translate(-50%, -50%) scale(1.4); opacity: 1; }
    65%  { transform: translate(-50%, -80%)  scale(1.1); opacity: 1; }
    100% { transform: translate(-50%, -140%) scale(.95); opacity: 0; }
}
.tove-heart {
    position: fixed;
    top: 50%; left: 50%;
    font-size: 10rem;
    color: #e0245e;
    text-shadow: 0 6px 18px rgba(224, 36, 94, .35);
    pointer-events: none;
    z-index: 9999;
    animation: tove-heart-bloom 2s ease-out forwards;
}

/* Layout: words found (left, grows) | board (center) | stats+missed (right, grows) */
.play-layout {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 2rem;
    align-items: start;
}
.play-layout .left-col    { grid-column: 1; display: flex; flex-direction: column; gap: 1.25rem; min-width: 0; }
.play-layout .board-area  { grid-column: 2; }
.play-layout .stats-bar   { grid-column: 3; }

/* Top-10 scoreboard under the Words-found list (left column). */
.hud-scores h3 { margin: 0 0 .5rem; font-size: 1rem; color: var(--accent); }
.top-scores {
    list-style: none; margin: 0; padding: 0;
    counter-reset: rank; font-variant-numeric: tabular-nums; font-size: .95rem;
}
.top-scores li {
    display: flex; align-items: baseline; gap: .5rem;
    padding: .3rem .4rem; border-bottom: 1px solid var(--tile-edge);
}
.top-scores li:last-child { border-bottom: 0; }
.top-scores li::before {
    counter-increment: rank; content: counter(rank) '.';
    color: var(--muted); width: 1.5rem; flex: none; text-align: right;
}
.top-scores li b { color: var(--fg); min-width: 3rem; font-size: 1.02rem; }
.top-scores li span { color: var(--muted); margin-left: auto; white-space: nowrap; }
.top-scores li.empty { color: var(--muted); justify-content: center; }
.top-scores li.empty::before { content: none; }
.top-scores li:first-child b { color: #c47a17; font-weight: 800; }   /* best run pops */

.play-layout .board-area {
    display: flex; flex-direction: column; align-items: center;
}
.play-layout .board-area .entry { width: 100%; }

/* Right column: Time / Score / Words + a History button, then missed-words. */
/* Right column is one unified card panel, like Word Mojo's .hud-panel:
   stacked HUD cells + a history button + the missed-words section. */
.stats-bar {
    display: flex; flex-direction: column; gap: 1rem; min-width: 0;
    background: var(--card); border: 1px solid var(--tile-edge);
    border-radius: 10px; padding: 1rem .9rem;
}
.stats-bar .hud { margin: 0; gap: .75rem; }
.stats-bar .hud-cell { flex: 1; }
/* missed-words reads as a section inside the panel, not a nested card */
.stats-bar .list-block { border: 0; background: none; padding: 0; }
/* Missed-words list packed as tight as possible. */
.stats-bar .list-block li { padding: 0 .25rem; line-height: 1.18; }
.side-btn {
    display: block; text-align: center; text-decoration: none;
    background: var(--card); border: 1px solid var(--tile-edge);
    border-radius: 6px; padding: .55rem .8rem; color: var(--accent); font-weight: 600;
}
.side-btn:hover { background: var(--tile-selected); }

/* Lists -------------------------------------------------------------- */
.list-block {
    background: var(--card); border: 1px solid var(--tile-edge);
    border-radius: 10px; padding: 1rem 1.25rem;
}
/* Missed-list: multi-column adaptive flow, same as the found list. Grows
   with the page rather than scrolling internally — multi-column would
   clip awkwardly inside a fixed-height scroll box. */
#missed-block ul {
    column-width: 8rem;
    column-gap: 1.25rem;
    overflow: visible;
    max-height: none;
}
#missed-block li {
    break-inside: avoid;
}
.list-block h3 { margin: 0 0 .5rem; color: var(--accent); }
.list-block ul {
    list-style: none; padding: 0; margin: 0;
    overflow-y: auto;
    flex: 1 1 auto;
}
#missed-block.side-list ul { max-height: none; }
.list-block li {
    padding: .15rem .25rem;
    display: flex; justify-content: space-between;
    font-variant-numeric: tabular-nums;
}

/* Found-list: compact, default font, flows into as many columns as the
   left-of-board space affords. The page is full-viewport wide and the
   board sits fixed-width in the middle, so on a wide screen this column
   has hundreds of pixels to spread the word list into. */
#found-block ul {
    overflow: visible;
    max-height: none;
    column-width: 8rem;
    column-gap: 1.25rem;
}
#found-block li {
    padding: .15rem .25rem;
    break-inside: avoid;
    display: flex; justify-content: space-between;
}
#found-block li .w   { font-weight: 700; }
#found-block li .pts { color: var(--muted); }
.list-block li .pts { color: var(--muted); }
.list-block li:hover { background: rgba(61, 90, 128, 0.10); cursor: default; }
#missed-list li[data-path]:hover { background: var(--tile-selected); }
.hint { color: var(--muted); font-size: .85rem; margin: 0 0 .75rem; }
.mono { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }

/* History table ------------------------------------------------------ */
.history {
    width: 100%; border-collapse: collapse;
}
.history th, .history td {
    padding: .4rem .6rem; text-align: left;
    border-bottom: 1px solid #d4dbe6;
}
.history th { color: var(--muted); font-weight: 600; font-size: .85rem; }

@media (max-width: 900px) {
    .play-layout {
        grid-template-columns: 1fr;
    }
    .play-layout .board-area,
    .play-layout .left-col,
    .play-layout .stats-bar { grid-column: 1; }
    .play-layout .board-area { order: 1; }
    .play-layout .stats-bar  { order: 2; }
    .play-layout .left-col { order: 3; }
    .list-block.side-list { position: static; max-height: none; }
    .stats-bar { max-width: none; }   /* full-width panel when stacked */
}
@media (max-width: 640px) {
    #board {
        grid-template-columns: repeat(4, 5rem);
        grid-template-rows:    repeat(4, 5rem);
    }
    .cell { font-size: 2rem; }
}
