:root {
    color-scheme: light;
    /* wet ink on rice paper: the stream is ink, the islands are left as paper */
    --ground: #f1ede4;
    --card: #fbf9f3;
    --ink: #22272e;
    --ink-soft: #6c7681;
    --muted-text: #8c9199;
    --grid-line: #e0dbcd;
    --stream: #2a3038;
    --dot: #9aa3ad;
    --done: #2f6fb0;
    --illegal: #c9342c;
    --illegal-soft: rgba(201, 52, 44, 0.14);
    --clue-tint: rgba(38, 47, 56, 0.05);
    --hover: rgba(38, 47, 56, 0.05);
    --control: #ffffff;
    --control-border: #d9d3c6;
    --control-hover: #f6f3ec;
    --card-shadow: 0 1px 2px rgba(38, 47, 56, 0.06), 0 12px 32px rgba(38, 47, 56, 0.08);
    --modal-backdrop: rgba(38, 47, 56, 0.45);
    --glow: rgba(47, 111, 176, 0.35);
    --hint: #d9a22a;
}

[data-theme="dark"] {
    color-scheme: dark;
    /* the same ink on slate */
    --ground: #12161a;
    --card: #1a2026;
    --ink: #e3e8ed;
    --ink-soft: #8c98a4;
    --muted-text: #717e8a;
    --grid-line: #2e3840;
    --stream: #07090c;
    --dot: #5d6a76;
    --done: #4f93dd;
    --illegal: #ef6358;
    --illegal-soft: rgba(239, 99, 88, 0.18);
    --clue-tint: rgba(227, 232, 237, 0.06);
    --hover: rgba(227, 232, 237, 0.05);
    --control: #202830;
    --control-border: #323d47;
    --control-hover: #28323b;
    --card-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 12px 32px rgba(0, 0, 0, 0.35);
    --modal-backdrop: rgba(0, 0, 0, 0.6);
    --glow: rgba(79, 147, 221, 0.4);
    --hint: #f0c04f;
}

* {
    box-sizing: border-box;
    -webkit-tap-highlight-color: transparent;
}

html {
    height: 100%;
}

/* The board owns the centre of the viewport: the rows above and below it
   share the spare height equally, and the header and controls sit against
   its edges within them. */
body {
    margin: 0;
    min-height: 100%;
    background: var(--ground);
    color: var(--ink);
    font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    display: grid;
    grid-template-rows: 1fr auto 1fr;
    justify-items: center;
    row-gap: 20px;
    padding: 24px 16px;
    overscroll-behavior: none;
}

/* Header */

header {
    align-self: end;
    text-align: center;
}

h1 {
    margin: 0;
    font-size: 30px;
    font-weight: 800;
    letter-spacing: -0.02em;
}

.tagline {
    margin: 4px 0 0;
    font-size: 14px;
    color: var(--muted-text);
}

.caption {
    margin: 10px 0 0;
    min-height: 18px;
    font-size: 13px;
    color: var(--muted-text);
    font-variant-numeric: tabular-nums;
}

.caption.done {
    color: var(--done);
    font-weight: 600;
}

.caption.hint {
    color: var(--hint);
}

.legend {
    display: flex;
    justify-content: center;
    gap: 16px;
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    font-size: 13px;
    color: var(--ink-soft);
}

.legend li {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* The legend draws the same two marks as the board, at a fixed size. */
.legend-mark {
    --cell: 16px;
    position: relative;
    width: var(--cell);
    height: var(--cell);
    border: 1px solid var(--grid-line);
    border-radius: 3px;
}

.legend-mark.stream {
    background: var(--stream);
    border-color: var(--stream);
}

/* Toolbar and controls */

.toolbar {
    position: fixed;
    top: 12px;
    right: 12px;
    display: flex;
    gap: 6px;
}

.icon-button {
    width: 34px;
    height: 34px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid var(--control-border);
    background: var(--control);
    color: var(--ink-soft);
    font: inherit;
    font-size: 16px;
    cursor: pointer;
}

.icon-button:hover {
    background: var(--control-hover);
    color: var(--ink);
}

.controls {
    align-self: start;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    flex-wrap: wrap;
}

.generator {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: center;
    gap: 12px;
    margin-bottom: 14px;
}

.field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted-text);
}

.field input,
.field select {
    letter-spacing: normal;
    text-transform: none;
    height: 36px;
}

.stats {
    margin: 0;
    min-height: 16px;
    text-align: center;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: var(--muted-text);
}

button.busy {
    animation: pulse 1s ease-in-out infinite;
}

@keyframes pulse {
    50% {
        opacity: 0.35;
    }
}

select, button, input {
    font: inherit;
    font-size: 16px;
    color: var(--ink);
    background: var(--control);
    border: 1px solid var(--control-border);
    border-radius: 999px;
    padding: 7px 14px;
    cursor: pointer;
}

button:hover, select:hover {
    background: var(--control-hover);
}

input[type="number"] {
    width: 72px;
    padding-right: 6px;
}

/* Board */

.board {
    --cell: clamp(28px, calc((100vw - 64px) / var(--size)), 50px);
    display: grid;
    grid-template-columns: repeat(var(--size), var(--cell));
    grid-template-rows: repeat(var(--size), var(--cell));
    padding: 12px;
    background: var(--card);
    border-radius: 18px;
    box-shadow: var(--card-shadow);
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}

.board.solved {
    animation: glow 1.4s ease;
}

@keyframes glow {
    50% {
        box-shadow: var(--card-shadow), 0 0 0 4px var(--glow);
    }
}

.cell {
    width: var(--cell);
    height: var(--cell);
    position: relative;
    display: grid;
    place-items: center;
    border-right: 1px solid var(--grid-line);
    border-bottom: 1px solid var(--grid-line);
    cursor: pointer;
}

.cell[data-column="0"] {
    border-left: 1px solid var(--grid-line);
}

.cell[data-row="0"] {
    border-top: 1px solid var(--grid-line);
}

.cell.clue {
    background: var(--clue-tint);
    cursor: default;
}

.board.placeholder .cell {
    opacity: 0.6;
}

/* Ink is opaque, so a stream cell takes no hover tint */
@media (hover: hover) {
    .cell:not(.clue):not(.stream):hover {
        background: var(--hover);
    }
}

/* Marks: a stream cell fills with ink and its borders melt into its
   neighbours; a dot is a small bead of soft ink; a clue is its number. */

.cell.stream {
    background: var(--stream);
    border-color: var(--stream);
}

.glyph {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    transition: transform 0.08s ease;
}

.cell.press .glyph {
    transform: scale(0.86);
}

.cell.dot .glyph::before,
.legend-mark.dot::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: calc(var(--cell) * 0.22);
    height: calc(var(--cell) * 0.22);
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: var(--dot);
}

.number {
    font-size: calc(var(--cell) * 0.46);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    color: var(--ink);
}

/* A hint rings the cell the solver points at. The ring is laid over the
   grid lines around the tile (its own on the right and bottom, its
   neighbours' on the top and left) and reaches no further. */

.cell.hint::after {
    content: "";
    position: absolute;
    inset: -1px;
    border: 3px solid var(--hint);
    pointer-events: none;
}

/* Broken rules turn red: a 2 × 2 of stream, or an island with two
   numbers or more cells than its number */

.cell.illegal {
    background: var(--illegal-soft);
}

.cell.illegal.stream {
    background: var(--illegal);
    border-color: var(--illegal);
}

.cell.illegal.dot .glyph::before {
    background: var(--illegal);
}

.cell.illegal .number {
    color: var(--illegal);
}

/* Solved: the ink settles into water, the dots sink away and the grid fades */

.board.solved .cell.stream {
    background: var(--done);
    border-color: var(--done);
    transition: background 600ms ease, border-color 600ms ease;
}

.board.solved .cell.dot .glyph::before {
    opacity: 0;
    transition: opacity 300ms ease;
}

.board.solved .cell.clue {
    background: transparent;
}

/* Modals */

.modal {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: var(--modal-backdrop);
    z-index: 10;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease, visibility 0s linear 0.2s;
}

.modal.open {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.2s ease;
}

.modal-card {
    max-width: 380px;
    width: 100%;
    max-height: 100%;
    overflow-y: auto;
    padding: 24px 26px 22px;
    border-radius: 18px;
    background: var(--card);
    box-shadow: var(--card-shadow);
    font-size: 14px;
    line-height: 1.5;
    transform: scale(0.97);
    transition: transform 0.2s ease;
}

.modal.open .modal-card {
    transform: scale(1);
}

@media (prefers-reduced-motion: reduce) {
    .modal,
    .modal-card,
    .board.solved,
    .board.solved .cell.stream,
    .board.solved .cell.dot .glyph::before {
        transition: none;
        animation: none;
    }
}

.modal-card h2 {
    margin: 0 0 10px;
    font-size: 20px;
}

.modal-card p {
    margin: 0 0 10px;
}

.modal-card ul {
    margin: 0 0 12px;
    padding-left: 20px;
}

.modal-subhead {
    font-weight: 600;
    margin-top: 14px;
}

.modal-close {
    margin-top: 6px;
    width: 100%;
}

@media (max-width: 420px) {
    body {
        padding-top: 60px;
        padding-bottom: 60px;
    }

    .legend {
        gap: 12px;
    }
}
