/* =========================================================
   Nosku - chalkboard sudoku
   Design tokens
   ========================================================= */
:root {
  --bg: #16221d;
  --bg-raise: #1c2b24;
  --board-bg: #1e2f27;
  --cell-bg: #1a2b23;
  --line-major: #f4f1e8;
  --line-minor: color-mix(in srgb, var(--chalk-white) 16%, transparent);
  --chalk-white: #f4f1e8;
  --chalk-blue: #8ab4d9;
  --chalk-yellow: #e8c468;
  --chalk-pink: #e88ba0;
  --chalk-green: #9ecdb1;
  --muted: color-mix(in srgb, var(--chalk-white) 52%, transparent);
  --muted-2: color-mix(in srgb, var(--chalk-white) 30%, transparent);
  --radius-lg: 20px;
  --radius-md: 14px;
  --radius-sm: 9px;
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-num: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--chalk-white);
  font-family: var(--font-ui);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none;
  touch-action: manipulation;
  position: relative;
  min-height: 100vh;
  /* dvh tracks the actual visible viewport (browser chrome included/
     excluded as it shows/hides); plain vh resolves to the largest
     possible viewport, which is taller than what's visible right after a
     reload (address bar still shown) - the exact moment that overflowed
     the page into an unwanted scrollbar. Kept as an override, not a
     replacement, so unsupported browsers still get the vh fallback. */
  min-height: 100dvh;
  /* Installed/standalone PWAs have no address bar to show or hide, so dvh
     and vh land on nearly the same value there and this bug persisted
     anyway - almost certainly the system status bar / gesture-nav inset
     (env(safe-area-inset-*)) not being fully settled at the instant the
     CSS viewport height first resolves right after a refresh. --app-vh is
     set from JS's own window.innerHeight (see boot() in app.js), which is
     authoritative regardless of engine viewport-unit quirks - the same
     JS-measured approach layoutGameSquares() already relies on for the
     board/number-pad, for the same class of reason (see DEVNOTES.md). */
  min-height: var(--app-vh, 100dvh);
}

/* Chalkboard dust texture, self-contained SVG noise, no external assets */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: screen;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  z-index: 0;
}

button { font-family: inherit; }
h1, h2, h3 { margin: 0; }

.hidden { display: none !important; }

/* =========================================================
   Screens
   ========================================================= */
.screen {
  display: none;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  min-height: var(--app-vh, 100dvh); /* see the comment on body's min-height above */
  max-width: 520px;
  margin: 0 auto;
  padding: max(20px, env(safe-area-inset-top)) 20px calc(20px + env(safe-area-inset-bottom));
  position: relative;
  z-index: 1;
}
.screen.active { display: flex; }

/* On phones, anchor the whole screen's content to the bottom so it sits
   in comfortable one-handed thumb reach instead of up near the top. */
#screen-home { justify-content: flex-end; }

/* =========================================================
   Buttons
   ========================================================= */
.btn {
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: 13px 20px;
  border-radius: 999px;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: transform 0.15s ease, opacity 0.15s ease, background 0.15s ease;
}
.btn:active { transform: scale(0.97); }
.btn-accent { background: var(--chalk-yellow); color: #1b1408; border-color: var(--chalk-yellow); }
.btn-accent:hover { opacity: 0.92; }
.btn-ghost { background: transparent; color: var(--chalk-white); border-color: color-mix(in srgb, var(--chalk-white) 30%, transparent); }
.btn-ghost:hover { border-color: var(--chalk-white); }
.btn-wide { width: 100%; }

.icon-btn {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  background: transparent;
  color: var(--chalk-white);
  border: 1.5px solid color-mix(in srgb, var(--chalk-white) 24%, transparent);
  border-radius: 50%;
  cursor: pointer;
}
.icon-btn:active { transform: scale(0.93); }

.eyebrow {
  display: block;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--chalk-yellow);
  font-weight: 700;
  margin-bottom: 4px;
}

.toast {
  position: fixed;
  top: max(14px, env(safe-area-inset-top));
  left: 50%;
  background: var(--chalk-white);
  color: #16221d;
  font-size: 13.5px;
  font-weight: 600;
  padding: 10px 16px;
  border-radius: 999px;
  z-index: 500;
  opacity: 0;
  transform: translateX(-50%) translateY(-16px);
  transition: transform 0.28s cubic-bezier(.2,.8,.2,1), opacity 0.22s ease;
  pointer-events: none;
  max-width: 86vw;
  text-align: center;
  box-shadow: 0 8px 24px rgba(0,0,0,0.35);
}
.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}

/* =========================================================
   Home screen
   ========================================================= */
.home-header { padding: 18px 2px 22px; position: relative; }
.home-header-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.brand { display: flex; align-items: center; gap: 10px; color: var(--chalk-yellow); }
.brand h1 {
  font-size: 30px;
  letter-spacing: 0.02em;
  color: var(--chalk-white);
  font-weight: 800;
}
.brand-dot { color: var(--chalk-yellow); }
.tagline { color: var(--muted); font-size: 14px; margin: 8px 0 0; max-width: 30ch; }

.offline-pill {
  display: inline-flex;
  margin-top: 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 6px 11px;
  border-radius: 999px;
  border: 1.5px solid color-mix(in srgb, var(--chalk-white) 24%, transparent);
  background: transparent;
  color: var(--muted);
  cursor: default;
}
.offline-pill.is-offline { color: var(--chalk-yellow); border-color: var(--chalk-yellow); }
.offline-pill.is-online { color: var(--chalk-green); border-color: rgba(158, 205, 177, 0.5); }

.continue-section { margin-bottom: 18px; }
.continue-section .eyebrow { margin-bottom: 8px; }
.continue-list { display: flex; flex-direction: column; gap: 10px; }
.continue-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  background: var(--bg-raise);
  border: 1px solid color-mix(in srgb, var(--chalk-white) 10%, transparent);
  border-radius: var(--radius-lg);
  padding: 16px 18px;
}
.continue-info { display: flex; flex-direction: column; min-width: 0; }
.continue-label { font-size: 16px; font-weight: 700; }
.continue-meta { font-size: 12.5px; color: var(--muted); margin-top: 2px; font-family: var(--font-num); }

.difficulty-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 18px;
}
.diff-card {
  background: var(--bg-raise);
  border: 1px solid color-mix(in srgb, var(--chalk-white) 10%, transparent);
  border-radius: var(--radius-md);
  padding: 18px 16px;
  text-align: left;
  color: var(--chalk-white);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.diff-card:active { transform: scale(0.97); }
.diff-card:hover { border-color: color-mix(in srgb, var(--chalk-white) 30%, transparent); }
.diff-card[data-difficulty="easy"] { border-left: 3px solid var(--chalk-green); }
.diff-card[data-difficulty="medium"] { border-left: 3px solid var(--chalk-blue); }
.diff-card[data-difficulty="hard"] { border-left: 3px solid var(--chalk-yellow); }
.diff-card[data-difficulty="diabolical"] { border-left: 3px solid var(--chalk-pink); }
.diff-name { font-size: 17px; font-weight: 700; }
.diff-progress { font-size: 12.5px; color: var(--muted); font-family: var(--font-num); }
.diff-avg { font-size: 11px; color: var(--muted-2); font-family: var(--font-num); min-height: 14px; }

.btn-wide.btn-ghost { margin-bottom: 20px; }

.stats-strip {
  margin-top: auto;
  display: flex;
  justify-content: space-around;
  padding-top: 18px;
  border-top: 1px dashed color-mix(in srgb, var(--chalk-white) 18%, transparent);
}
.stat { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.stat-value { font-family: var(--font-num); font-size: 20px; font-weight: 700; color: var(--chalk-yellow); }
.stat-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }

/* =========================================================
   Game screen
   ========================================================= */
#screen-game {
  height: 100dvh;
  min-height: 100dvh;
  max-height: 100dvh;
  overflow: hidden;
}

/* Empty on phones only: absorbs a modest share of the leftover vertical
   space so the board + controls group sits lower on the screen, in
   comfortable one-handed thumb reach, instead of hugging the header. */
/* A small, fixed nudge - not a proportional share of leftover space.
   On a short/4:3 screen, a proportional flex-grow here would eat a large
   chunk of the little vertical room available, at the direct expense of
   the board. A capped size still gives a bit of one-handed-reach
   breathing room on tall phones without ever competing meaningfully with
   the board and number pad for space. */
.game-top-spacer { flex: 0 1 44px; min-height: 0; }

.game-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0 16px;
  flex: 0 0 auto;
}
.game-title { flex: 1; display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.game-difficulty { font-weight: 700; font-size: 14.5px; text-transform: capitalize; }
.game-puzzle-id { font-size: 11.5px; color: var(--muted); font-family: var(--font-num); }
.game-metrics { display: flex; align-items: center; gap: 12px; margin-right: 4px; }
.metric { font-family: var(--font-num); font-size: 14px; color: var(--muted); }
.metric #mistake-count { color: var(--chalk-pink); font-weight: 700; }
.metric-timer { color: var(--chalk-white); font-weight: 700; font-size: 15px; letter-spacing: 0.02em; }

/* The board takes whatever vertical space is left after the header,
   number pad and toolbar claim theirs, and sizes itself as the largest
   square that fits — so it shrinks automatically at any number pad size
   or screen height, and the page can never need to scroll. */
.board-wrap {
  position: relative;
  /* Sized by its own width (a square), not stretched to fill leftover
     height - the number pad row below is what claims whatever space the
     board doesn't need. Can still shrink if the two together don't fit. */
  flex: 0 1 auto;
  min-height: 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  transition: max-width 0.2s ease;
}

/* On phones this is a real (bottom-weighted) flex column holding the
   board and the pad row, sitting below .game-top-spacer. Wide screens
   override this to a side-by-side row (see the min-width: 860px block). */
.game-layout {
  display: flex;
  flex-direction: column;
  flex: 3 1 0;
  min-height: 0;
  gap: 10px;
}
.game-controls { display: contents; }

/* Row-layout number pad: the toolbar goes back to a single row below the
   pad instead of flanking it. board-wrap keeps its base (non-growing)
   behavior here too, so - same as the base .pad-row comment already says -
   pad-row is what absorbs whatever vertical space the board doesn't need,
   not board-wrap centering the board within its own inflated box (which
   is what used to leave the board with equal empty padding above *and*
   below it on a tall/narrow phone, while the pad+toolbar sat cramped
   together at the very bottom). A grid, not the flex-wrap used elsewhere,
   lets the number pad's row grow to fill that leftover space and center
   the pad within it specifically, while the toolbar row stays pinned to
   the bottom instead of being pushed down along with it. Scoped to
   phones only - on wide screens the two-column layout below handles
   sizing on its own. */
@media (max-width: 859px) {
  #screen-game.row-toolbar .pad-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr auto;
  }
  #screen-game.row-toolbar .numpad-wrap { grid-column: 1 / -1; grid-row: 1; }
  #screen-game.row-toolbar .side-tools { grid-row: 2; flex-direction: row; min-width: 0; }
  /* .pad-row's children are exactly [side-tools, numpad-wrap, side-tools],
     all <div>s - :first-of-type/:last-of-type reliably tell the two
     side-tools apart without needing an extra wrapper element. */
  #screen-game.row-toolbar .side-tools:first-of-type { grid-column: 1; }
  #screen-game.row-toolbar .side-tools:last-of-type { grid-column: 2; }
  #screen-game.row-toolbar .tool-btn { width: auto; flex: 1 1 0; }
}

.board {
  display: grid;
  /* minmax(0, 1fr), not plain 1fr: same fix as the number pad already
     got. Plain 1fr lets a track grow to fit its largest digit, so empty
     columns/rows collapse and columns with digits stay oversized -
     exactly the "collapsed cells" look. minmax(0, 1fr) forces all 9
     equal, regardless of content, at any board size. */
  grid-template-columns: repeat(9, minmax(0, 1fr));
  grid-template-rows: repeat(9, minmax(0, 1fr));
  width: auto;
  max-width: 100%;
  max-height: 100%;
  /* Deliberately no meaningful min-width/min-height floor: the board is
     the one thing allowed to shrink as far as it needs to. The number
     pad and toolbar are sized from user settings first, and the board
     becomes the largest square that fits whatever's left - on an unusual
     aspect ratio that might mean a small board, but the controls must
     never be pushed off-screen to keep it bigger than that. */
  min-width: 0;
  min-height: 0;
  aspect-ratio: 1 / 1;
  background: var(--board-bg);
  border: 2.5px solid var(--line-major);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.board { container-type: inline-size; }
.cell {
  position: relative;
  display: grid;
  place-items: center;
  background: var(--cell-bg);
  border-right: 1px solid var(--line-minor);
  border-bottom: 1px solid var(--line-minor);
  font-family: var(--font-num);
  /* Sized from the board's own rendered width (container query units),
     not the viewport - vw units don't shrink when the board itself has
     to shrink (e.g. a big number pad claims most of the screen), so the
     digits end up oversized for a small board. 5.4cqw ~= half a cell's
     width (board width / 9), a good single-digit fit at any board size. */
  font-size: clamp(9px, 5.4cqw, 24px);
  font-weight: 500;
  color: var(--chalk-white);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}
.cell:nth-child(9n) { border-right: none; }
.cell:nth-child(n+73) { border-bottom: none; }
.cell.col-edge-3 { border-right: 2px solid var(--line-major); }
.cell.row-edge-3 { border-bottom: 2px solid var(--line-major); }

.cell.given { color: var(--chalk-blue); font-weight: 700; }
.cell.user-value { color: var(--chalk-white); font-weight: 600; }
.cell.error { color: var(--chalk-pink); }
.cell.selected { background: color-mix(in srgb, var(--chalk-yellow) 22%, transparent); }
.cell.peer { background: color-mix(in srgb, var(--chalk-white) 5.5%, transparent); }
.cell.same-value:not(.selected) { background: color-mix(in srgb, var(--chalk-blue) 16%, transparent); }
/* Duplicate value sharing a row/col/box with this cell - distinct from
   .error (wrong vs. the solution): a conflict explains *why*, an inset
   outline layered on top rather than replacing the existing state. */
.cell.conflict { box-shadow: inset 0 0 0 2px var(--chalk-pink); }
.cell.num-highlight:not(.selected) { background: color-mix(in srgb, var(--chalk-green) 20%, transparent); }
.cell.hint-flash { animation: hintFlash 0.9s ease; }
@keyframes hintFlash {
  0% { background: color-mix(in srgb, var(--chalk-yellow) 55%, transparent); }
  100% { background: transparent; }
}

.cell .notes-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  width: 88%;
  height: 88%;
}
.cell .notes-grid span {
  display: grid;
  place-items: center;
  font-size: clamp(5px, 1.8cqw, 10px);
  color: var(--muted);
  font-family: var(--font-num);
}
.cell .notes-grid span.on { color: var(--chalk-yellow); font-weight: 700; }

.pause-overlay {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter: blur(3px);
  border-radius: var(--radius-sm);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  font-size: 18px;
  font-weight: 700;
}

.numpad {
  display: grid;
  /* minmax(0, 1fr), not plain 1fr: without the 0 minimum, a track will
     grow to fit oversized button text and push later columns (i.e. the
     "9" button) outside the viewport instead of shrinking to fit. */
  grid-template-columns: repeat(9, minmax(0, 1fr));
  gap: 6px;
  width: 100%;
  max-height: 100%;
  min-width: 0;
  min-height: 0;
  flex: 0 0 auto;
  transition: max-width 0.2s ease, gap 0.2s ease;
}
.numpad.layout-grid {
  /* Same width:auto fix as .board - the base .numpad rule sets width:100%
     for row layout, which would force this into a rectangle instead of
     a square (see the comment on .board for why). */
  width: auto;
  container-type: inline-size;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: repeat(3, minmax(0, 1fr));
  gap: 0;
  aspect-ratio: 1 / 1;
  border: 2.5px solid var(--line-major);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--board-bg);
}
.num-btn {
  aspect-ratio: 1 / 1;
  border-radius: 10px;
  background: var(--bg-raise);
  border: 1px solid color-mix(in srgb, var(--chalk-white) 12%, transparent);
  color: var(--chalk-white);
  font-family: var(--font-num);
  /* Row layout only has 1/9th of the width per button, so its font can't
     grow as far as grid layout's (1/3rd per button) without the digit
     overflowing its own button - cap it lower here. */
  font-size: clamp(15px, 3.6vw, 19px);
  font-weight: 600;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: font-size 0.2s ease;
}
.numpad.layout-grid .num-btn {
  aspect-ratio: auto;
  border-radius: 0;
  border: none;
  border-right: 1px solid var(--line-minor);
  border-bottom: 1px solid var(--line-minor);
  background: transparent;
  /* Proportional to the number pad's own rendered width (which already
     reflects the size slider via its max-width), not the viewport - so
     the digit always matches however big or small the pad actually is,
     with no separate --num-scale multiplier needed here. */
  font-size: clamp(14px, 15cqw, 42px);
}
.numpad.layout-grid .num-btn:nth-child(3n) { border-right: none; }
.numpad.layout-grid .num-btn:nth-child(n+7) { border-bottom: none; }
.numpad.layout-grid .num-btn:active { background: color-mix(in srgb, var(--chalk-white) 8%, transparent); }
.num-btn .remain { font-size: 8px; color: var(--muted-2); font-weight: 600; }
.num-btn:active { transform: scale(0.93); }
.num-btn.depleted { opacity: 0.28; pointer-events: none; }
.num-btn.highlighted { border-color: var(--chalk-green); color: var(--chalk-green); }

/* The middle row: a toolbar column on each side, the number pad centered
   between them. Grid, not flex, so the two side columns can be
   auto-width while the number pad's column takes exactly what's left. */
.pad-row {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  justify-content: center;
  gap: 10px;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
}
.numpad-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
}
.side-tools {
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 0 0 auto;
  min-height: 0;
  gap: 10px;
}
.tool-btn {
  background: var(--bg-raise);
  border: 1px solid color-mix(in srgb, var(--chalk-white) 12%, transparent);
  border-radius: var(--radius-sm);
  color: var(--muted);
  width: 68px;
  min-width: 0;
  min-height: 0;
  padding: 12px 4px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  font-size: 10.5px;
  font-weight: 600;
  cursor: pointer;
}
.tool-btn:active { transform: scale(0.95); }
.tool-btn[aria-pressed="true"] { color: var(--chalk-yellow); border-color: color-mix(in srgb, var(--chalk-yellow) 50%, transparent); }
.tool-btn.tool-disabled { opacity: 0.35; pointer-events: none; }

/* =========================================================
   Library screen
   ========================================================= */
.lib-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 0 16px;
}
.lib-bar h2 { font-size: 18px; font-weight: 800; }
.lib-spacer { width: 38px; }

.lib-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 16px;
  overflow-x: auto;
}
.lib-tab {
  flex: 1;
  background: var(--bg-raise);
  border: 1px solid color-mix(in srgb, var(--chalk-white) 12%, transparent);
  color: var(--muted);
  padding: 9px 10px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}
.lib-tab.active { color: #1b1408; background: var(--chalk-yellow); border-color: var(--chalk-yellow); }

.lib-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  overflow-y: auto;
  padding-bottom: 12px;
}
.lib-item {
  aspect-ratio: 1 / 1;
  border-radius: 10px;
  background: var(--bg-raise);
  border: 1px solid color-mix(in srgb, var(--chalk-white) 10%, transparent);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-family: var(--font-num);
  gap: 3px;
  position: relative;
}
.lib-item .n { font-size: 13px; font-weight: 700; color: var(--muted); }
.lib-item.solved { border-color: rgba(158, 205, 177, 0.5); }
.lib-item.solved .n { color: var(--chalk-green); }
.lib-item.in-progress { border-color: color-mix(in srgb, var(--chalk-yellow) 50%, transparent); }
.lib-item.in-progress .n { color: var(--chalk-yellow); }
.lib-item .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--muted-2); }
.lib-item.solved .dot { background: var(--chalk-green); }
.lib-item.in-progress .dot { background: var(--chalk-yellow); }

.lib-download { margin-top: 14px; text-align: center; }
.download-status { font-size: 12px; color: var(--muted); margin-top: 8px; min-height: 16px; font-family: var(--font-num); }

/* =========================================================
   Settings screen
   ========================================================= */
.settings-list {
  display: flex;
  flex-direction: column;
  margin-bottom: 8px;
}
.setting-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 15px 2px;
  border-bottom: 1px dashed color-mix(in srgb, var(--chalk-white) 14%, transparent);
}
.setting-info { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.setting-title { font-size: 14.5px; font-weight: 700; }
.setting-desc { font-size: 12px; color: var(--muted); line-height: 1.45; }

.switch { position: relative; display: inline-block; width: 44px; height: 26px; flex-shrink: 0; }
.switch input { opacity: 0; width: 0; height: 0; position: absolute; }
.switch-track {
  position: absolute; inset: 0;
  background: color-mix(in srgb, var(--chalk-white) 16%, transparent);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s ease;
}
.switch-track::before {
  content: "";
  position: absolute;
  width: 20px; height: 20px;
  left: 3px; top: 3px;
  background: var(--chalk-white);
  border-radius: 50%;
  transition: transform 0.15s ease, background 0.15s ease;
}
.switch input:checked + .switch-track { background: color-mix(in srgb, var(--chalk-yellow) 85%, transparent); }
.switch input:checked + .switch-track::before { transform: translateX(18px); background: #1b1408; }
.switch input:focus-visible + .switch-track { outline: 2px solid var(--chalk-yellow); outline-offset: 2px; }

.stepper { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.stepper-btn {
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--chalk-white) 24%, transparent);
  background: var(--bg-raise);
  color: var(--chalk-white);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}
.stepper-btn:active { transform: scale(0.92); }
#max-mistakes-value { font-family: var(--font-num); font-weight: 700; min-width: 16px; text-align: center; font-size: 15px; }
#max-mistakes-row.tool-disabled { opacity: 0.35; pointer-events: none; }
.setting-row.tool-disabled { opacity: 0.35; pointer-events: none; }

.settings-app { margin-top: 10px; padding-top: 18px; border-top: 1px dashed color-mix(in srgb, var(--chalk-white) 18%, transparent); }
.settings-backup { margin-top: 10px; padding-top: 18px; border-top: 1px dashed color-mix(in srgb, var(--chalk-white) 18%, transparent); }
.settings-custom { margin-top: 10px; padding-top: 18px; border-top: 1px dashed color-mix(in srgb, var(--chalk-white) 18%, transparent); }
.backup-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.text-input {
  font-family: var(--font-num);
  font-size: 13px;
  background: var(--bg-raise);
  color: var(--chalk-white);
  border: 1.5px solid color-mix(in srgb, var(--chalk-white) 24%, transparent);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  width: 100%;
}
.text-input:focus { outline: none; border-color: var(--chalk-yellow); }
.app-version {
  text-align: center;
  font-size: 11px;
  font-family: var(--font-num);
  color: var(--muted-2);
  margin: 22px 0 4px;
}

/* =========================================================
   Themes
   ========================================================= */
body[data-theme="light"] {
  --bg: #ffffff;
  --bg-raise: #f2f1ed;
  --board-bg: #ffffff;
  --cell-bg: #ffffff;
  --line-major: #1c1b1a;
  --line-minor: rgba(28, 27, 26, 0.16);
  --chalk-white: #1c1b1a;
  --chalk-blue: #2f6fa8;
  --chalk-yellow: #c9902c;
  --chalk-pink: #c6425e;
  --chalk-green: #2e8b57;
  --muted: rgba(28, 27, 26, 0.55);
  --muted-2: rgba(28, 27, 26, 0.32);
}
body[data-theme="light"]::before { opacity: 0.025; mix-blend-mode: multiply; }

body[data-theme="amoled"] {
  --bg: #000000;
  --bg-raise: #0a0a0a;
  --board-bg: #000000;
  --cell-bg: #000000;
  --line-major: #6e6e69;
  --line-minor: rgba(110, 110, 105, 0.32);
  --chalk-white: #c4c4be;
  --chalk-blue: #6f96ad;
  --chalk-yellow: #f0cd72;
  --chalk-pink: #f2a0b4;
  --chalk-green: #a9e0bd;
  --muted: rgba(196, 196, 190, 0.55);
  --muted-2: rgba(196, 196, 190, 0.3);
}
body[data-theme="amoled"]::before { opacity: 0.035; }
body[data-theme="amoled"] .cell.user-value { color: var(--line-major); }
body[data-theme="amoled"] .num-btn { color: var(--line-major); }

/* Warm - a low blue-light, sepia-leaning theme that's easy on the eyes.
   No blue hues anywhere; accents lean amber/olive/terracotta instead. */
body[data-theme="warm"] {
  --bg: #e8dbab;
  --bg-raise: #ddcd92;
  --board-bg: #e8dbab;
  --cell-bg: #e8dbab;
  --line-major: #4a3b22;
  --line-minor: rgba(74, 59, 34, 0.16);
  --chalk-white: #3b2c18;
  --chalk-blue: #8a6a35;
  --chalk-yellow: #c9902c;
  --chalk-pink: #b5573e;
  --chalk-green: #74812f;
  --muted: rgba(59, 44, 24, 0.55);
  --muted-2: rgba(59, 44, 24, 0.3);
}
body[data-theme="warm"]::before { opacity: 0.025; mix-blend-mode: multiply; }

/* =========================================================
   Segmented control (theme / numpad layout pickers)
   ========================================================= */
.setting-row-col { flex-direction: column; align-items: stretch; }
.segmented {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}
.segmented-btn {
  flex: 1 1 30%;
  min-width: 76px;
  background: var(--bg-raise);
  border: 1px solid color-mix(in srgb, var(--chalk-white) 14%, transparent);
  color: var(--muted);
  padding: 9px 8px;
  border-radius: 10px;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}
.segmented-btn.active { color: #1b1408; background: var(--chalk-yellow); border-color: var(--chalk-yellow); }
.setting-hint {
  display: block;
  font-size: 11px;
  color: var(--muted-2);
  margin-top: 8px;
  font-family: var(--font-num);
}

.slider-row { display: flex; align-items: center; gap: 12px; margin-top: 6px; }
.slider-row input[type="range"] {
  flex: 1;
  accent-color: var(--chalk-yellow);
  height: 4px;
}
.slider-row .slider-value {
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 13.5px;
  min-width: 20px;
  text-align: center;
}

/* =========================================================
   Modals
   ========================================================= */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(10, 15, 12, 0.72);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 300;
}
.modal {
  background: var(--bg-raise);
  border: 1px solid color-mix(in srgb, var(--chalk-white) 14%, transparent);
  border-radius: var(--radius-lg);
  padding: 28px 24px 24px;
  max-width: 360px;
  width: 100%;
  text-align: center;
  position: relative;
  overflow: hidden;
}
.modal h2 { font-size: 22px; font-weight: 800; margin-bottom: 6px; }
.modal-copy { color: var(--muted); font-size: 13.5px; line-height: 1.5; margin: 10px 0 6px; }
.complete-stats {
  display: flex;
  justify-content: center;
  gap: 34px;
  margin: 18px 0 22px;
}
.complete-value { display: block; font-family: var(--font-num); font-size: 24px; font-weight: 700; color: var(--chalk-yellow); }
.complete-label { display: block; font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin-top: 2px; }
.modal-actions { display: flex; gap: 10px; justify-content: center; }
.modal-actions .btn { flex: 1; }

#burst-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* =========================================================
   Responsive
   ========================================================= */
@media (min-width: 460px) {
  .lib-grid { grid-template-columns: repeat(6, 1fr); }
}
@media (max-width: 340px) {
  .lib-grid { grid-template-columns: repeat(4, 1fr); }
}

/* Wide screens (tablets, unfolded foldables, desktop windows): stop just
   centering a phone-width column in a sea of empty space. Widen the shell
   and, for the game screen specifically, put the board and controls
   side by side instead of stacked. */
@media (min-width: 860px) {
  .screen { max-width: 1180px; }

  .game-top-spacer { display: none; }

  #screen-home, #screen-library, #screen-settings {
    max-width: 760px;
  }
  #screen-home { justify-content: flex-start; }

  .difficulty-grid { grid-template-columns: repeat(4, 1fr); }
  .lib-grid { grid-template-columns: repeat(10, 1fr); }

  .game-layout {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    justify-content: center;
    gap: 56px;
    flex: 1;
    min-height: 0;
  }

  .board-wrap {
    flex: 0 1 560px;
    max-width: 560px;
    margin: 0;
  }

  .game-controls {
    display: flex;
    flex-direction: column;
    flex: 0 1 420px;
    max-width: 420px;
    min-height: 0;
    gap: 24px;
  }

  .num-btn { font-size: clamp(15px, 2.2vw, 22px); }
  .tool-btn { padding: 16px 4px; font-size: 12.5px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}
