/* =========================================================================
   Sudoku Variant Studio — design system
   Warm paper surfaces, one terracotta accent, and colour reserved for the
   things that mean something: the puzzle, the difficulty, the verdict.
   ========================================================================= */

:root {
  --font-ui: "Segoe UI Variable Text", "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-grid: "Segoe UI Variable Display", "Inter", "Segoe UI", system-ui, sans-serif;
  --font-mono: "Cascadia Code", ui-monospace, "SF Mono", Consolas, monospace;

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px;
  --r1: 6px; --r2: 10px; --r3: 14px; --r4: 20px;

  /* light palette */
  --bg:          #f4f1ec;
  --surface:     #fdfcfa;
  --surface-2:   #f0ece5;
  --surface-3:   #e4dfd6;
  --ink:         #221f1b;
  --ink-2:       #4c4740;
  --muted:       #857e73;
  --line:        #ddd7cc;
  --line-strong: #b7afa1;
  --grid-thin:   #cec7ba;
  --grid-bold:   #4e4a43;

  --accent:      #bc5b33;
  --accent-ink:  #ffffff;
  --accent-soft: #f7e6dc;
  --accent-line: #dfa183;

  --good:        #2e7d52;
  --good-soft:   #ddefe3;
  --warn:        #96690f;
  --warn-soft:   #f7edd4;
  --bad:         #b23129;
  --bad-soft:    #f9dcd8;

  /* difficulty scale, gentle → search */
  --dc1: #2e7d52;
  --dc2: #33739c;
  --dc3: #b08526;
  --dc4: #bc5b33;
  --dc5: #b23129;

  --given:       #221f1b;
  --solved:      #2d5fa6;
  --pencil:      #837c70;
  --sel:         #f3d9a4;
  --sel-line:    #c1913a;
  --step-focus:  #ffe9ae;
  --step-elim:   #f8cdc7;

  /* constraint palette — legible on both themes */
  --line-renban:     #9a6bd8;
  --line-nabner:     #6f6f7a;
  --line-german:     #4f9d69;
  --line-dutch:      #d78b2e;
  --line-custom:     #4d8fb5;
  --line-palindrome: #a9a29a;
  --line-entropy:    #c0508f;
  --line-modular:    #4aa39b;
  --line-parity:     #7b86d6;
  --line-odd:        #b2708f;
  --line-even:       #6f92b8;
  --line-thermo:     #8d867c;
  --line-slowthermo: #a79e8d;
  --line-arrow:      #6b6660;
  --line-regionsum:  #3f8ad6;
  --line-zipper:     #c77b3f;
  --line-between:    #7a7a7a;
  --line-lockout:    #8a5fbd;
  --cage:            #55504a;
  --clone:           #dfe7f2;
  --extra-region:    #e9e0f2;

  --shade-yin:   #3a3733;
  --shade-yang:  #ffffff;
  --fog:         #b9b3a8;
  --fog-edge:    #8d8679;

  /* The nine cell colours, and the nine pen inks that pair with them. These
     are defined once and read by three places - the grid fills, the swatches
     on the digit pad, and the pen - because a palette kept in two files is a
     palette that quietly stops matching the first time one is edited.
     They stay identical in dark mode: they are backgrounds for dark digits,
     and the renderer already haloes digits to keep them legible over any of
     them, so flipping these would break that rather than help it. */
  --cell-c1: #f2b3ae;  --cell-c2: #f6d59a;  --cell-c3: #f4efa4;
  --cell-c4: #b9e3ad;  --cell-c5: #a9dbe0;  --cell-c6: #b4c4ef;
  --cell-c7: #d5b6ec;  --cell-c8: #e9c3d8;  --cell-c9: #cfcabf;

  /* Pen ink is the same hue carried to full strength - a line drawn in the
     pastel used for fills would disappear against a cell filled with it. */
  --ink-c1: #c8483f;  --ink-c2: #c98a12;  --ink-c3: #9a9412;
  --ink-c4: #3f8f42;  --ink-c5: #2b8f9c;  --ink-c6: #3f63c4;
  --ink-c7: #7b45b8;  --ink-c8: #b8407e;  --ink-c9: #55504a;

  --shadow-1: 0 1px 2px rgba(35, 30, 22, .05), 0 1px 1px rgba(35, 30, 22, .04);
  --shadow-2: 0 2px 6px rgba(35, 30, 22, .07), 0 12px 32px rgba(35, 30, 22, .09);
  --shadow-3: 0 18px 48px rgba(35, 30, 22, .2);
}

:root[data-theme="dark"] {
  --bg:          #141519;
  --surface:     #1c1e23;
  --surface-2:   #24262c;
  --surface-3:   #2f323a;
  --ink:         #edebe7;
  --ink-2:       #c6c2bb;
  --muted:       #928d84;
  --line:        #32353c;
  --line-strong: #565a63;
  --grid-thin:   #3b3f47;
  --grid-bold:   #a3aab4;

  --accent:      #e08055;
  --accent-ink:  #241108;
  --accent-soft: #3a251b;
  --accent-line: #8a4f33;

  --good:        #5cc48b;
  --good-soft:   #1d3628;
  --warn:        #e0b055;
  --warn-soft:   #3a2f16;
  --bad:         #f0776c;
  --bad-soft:    #3d1f1c;

  --dc1: #5cc48b;
  --dc2: #6aa8d8;
  --dc3: #d8ac4e;
  --dc4: #e08055;
  --dc5: #f0776c;

  --given:       #f3f1ed;
  --solved:      #82b4f2;
  --pencil:      #8f8a82;
  --sel:         #4a3f26;
  --sel-line:    #c59a45;
  --step-focus:  #4a3f1c;
  --step-elim:   #4a2622;

  --line-nabner:     #9a9aa6;
  --line-palindrome: #8e8880;
  --line-thermo:     #6a655e;
  --line-slowthermo: #575249;
  --line-arrow:      #a8a29a;
  --cage:            #b6afa6;
  --clone:           #26313f;
  --extra-region:    #2e2740;

  --shade-yin:   #0e0f11;
  --shade-yang:  #e8e5e0;
  --fog:         #363a41;
  --fog-edge:    #565c66;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-2: 0 6px 24px rgba(0, 0, 0, .5);
  --shadow-3: 0 20px 56px rgba(0, 0, 0, .6);
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }

body {
  font-family: var(--font-ui);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

button, input, select, textarea { font: inherit; color: inherit; }
::selection { background: var(--accent-soft); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r1); }

/* ------------------------------------------------------------- app shell */
.app { display: grid; grid-template-rows: auto 1fr; height: 100vh; }

.topbar {
  display: flex; align-items: center; gap: var(--s4);
  padding: 0 var(--s4);
  height: 54px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  z-index: 20;
}

.brand {
  display: flex; align-items: baseline; gap: 9px;
  font-weight: 680; font-size: 14.5px; letter-spacing: -.015em;
  white-space: nowrap;
}
.brand .dot {
  width: 10px; height: 10px; border-radius: 3px;
  background: var(--accent);
  align-self: center;
  transform: rotate(45deg);
}
.brand small { color: var(--muted); font-weight: 450; font-size: 12px; letter-spacing: 0; }

.spacer { flex: 1; }

/* segmented control */
.segmented {
  display: inline-flex;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
.segmented button {
  border: 0; background: transparent; cursor: pointer;
  padding: 4px 16px; border-radius: 999px;
  color: var(--muted); font-weight: 600; font-size: 13px;
  transition: background .15s, color .15s, box-shadow .15s;
}
.segmented button:hover { color: var(--ink-2); }
.segmented button[aria-pressed="true"] {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-1);
}
.segmented.glyphs button { padding: 4px 10px; }
.segmented.glyphs svg { width: 20px; height: 20px; display: block; }

/* buttons */
.btn {
  display: inline-flex; align-items: center; gap: var(--s2);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  padding: 6px 13px;
  border-radius: var(--r2);
  cursor: pointer;
  font-weight: 600; font-size: 13px;
  transition: background .15s, border-color .15s, transform .06s, opacity .15s;
  white-space: nowrap;
}
.btn:hover { background: var(--surface-2); border-color: var(--line-strong); }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: .4; pointer-events: none; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn.primary:hover { filter: brightness(1.07); background: var(--accent); }
.btn.ghost { border-color: transparent; background: transparent; color: var(--ink-2); }
.btn.ghost:hover { background: var(--surface-2); color: var(--ink); }
.btn.icon { padding: 6px 9px; }
.btn.sm { padding: 4px 10px; font-size: 12.5px; }

kbd {
  font-family: var(--font-mono); font-size: 11px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 5px; padding: 1px 5px; color: var(--muted);
}

/* ---------------------------------------------------------------- layout */
main {
  display: grid;
  grid-template-columns: 252px minmax(0, 1fr) 372px;
  min-height: 0;
}

.palette, .side {
  background: var(--surface);
  min-height: 0;
  display: flex; flex-direction: column;
}
.palette { border-right: 1px solid var(--line); }
.side { border-left: 1px solid var(--line); }

.scroll { overflow-y: auto; overscroll-behavior: contain; }
.scroll::-webkit-scrollbar { width: 10px; }
.scroll::-webkit-scrollbar-thumb {
  background: var(--surface-3); border-radius: 10px;
  border: 3px solid var(--surface);
}
.scroll::-webkit-scrollbar-thumb:hover { background: var(--line-strong); }

/* ------------------------------------------------------------- palette */
.palette-head {
  padding: var(--s3);
  border-bottom: 1px solid var(--line);
}
.search {
  width: 100%;
  border: 1px solid var(--line); background: var(--surface-2);
  border-radius: 999px; padding: 6px 14px; font-size: 13px;
}
.search::placeholder { color: var(--muted); }
.search:focus { border-color: var(--accent-line); outline: none; }

.group { padding: 2px var(--s2) var(--s2); }
.group > h3 {
  position: sticky; top: 0; z-index: 2;
  margin: 0; padding: 10px 8px 6px;
  font-size: 10.5px; font-weight: 750; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
  background: linear-gradient(var(--surface) 78%, transparent);
}
.tools { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; }
.tool {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px;
  min-height: 40px;
  border: 1px solid transparent; border-radius: var(--r2);
  background: transparent; cursor: pointer; text-align: left;
  color: var(--ink-2);
  transition: background .12s, border-color .12s, color .12s;
}
.tool:hover { background: var(--surface-2); color: var(--ink); }
.tool svg { width: 26px; height: 26px; display: block; flex: none; }
.tool span {
  font-size: 11.5px; line-height: 1.25; font-weight: 560;
  letter-spacing: -.01em;
}
.tool[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent-line);
  color: var(--ink);
  box-shadow: var(--shadow-1);
}
.tool.wide { grid-column: span 2; }

/* toggles */
.toggle-row {
  display: flex; align-items: center; gap: var(--s2);
  padding: 5px 8px; border-radius: var(--r1); cursor: pointer;
  transition: background .12s;
}
.toggle-row:hover { background: var(--surface-2); }
.toggle-row input { accent-color: var(--accent); width: 15px; height: 15px; margin: 0; flex: none; }
.toggle-row span { font-size: 12.5px; }

/* ---------------------------------------------------------------- board */
.board {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center;
  gap: var(--s3);
  padding: var(--s4);
  min-width: 0; min-height: 0;
  background: var(--bg);
}
.board-wrap {
  position: relative;
  width: min(100%, calc(100vh - 172px));
  aspect-ratio: 1;
  max-width: 840px;
}
#grid {
  width: 100%; height: 100%;
  display: block;
  border-radius: var(--r3);
  background: var(--surface);
  box-shadow: var(--shadow-2);
  border: 1px solid var(--line);
  touch-action: none;
  user-select: none;
}

.boardbar {
  display: flex; align-items: center; gap: var(--s2);
  flex-wrap: wrap; justify-content: center;
}
/* Colour mode turns the pad into swatches. The colours come from the same
   custom properties the grid fills use, addressed by position, so there is no
   second copy of the palette to keep in step. */
.pad.colours button {
  color: #221f1b; font-size: 12px; font-weight: 700;
  /* No cross-fade when the mode switches: nine buttons dissolving from grey
     into nine different colours is a mess to look at, and it leaves the pad
     showing the wrong colours for the length of the fade. */
  transition: none;
}
/* Hover must not repaint over the swatch — the colour is the whole point of
   the button, so lift it rather than replace it. */
.pad.colours button:hover { filter: brightness(1.07); }
.pad.colours button:nth-child(1) { background: var(--cell-c1); }
.pad.colours button:nth-child(2) { background: var(--cell-c2); }
.pad.colours button:nth-child(3) { background: var(--cell-c3); }
.pad.colours button:nth-child(4) { background: var(--cell-c4); }
.pad.colours button:nth-child(5) { background: var(--cell-c5); }
.pad.colours button:nth-child(6) { background: var(--cell-c6); }
.pad.colours button:nth-child(7) { background: var(--cell-c7); }
.pad.colours button:nth-child(8) { background: var(--cell-c8); }
.pad.colours button:nth-child(9) { background: var(--cell-c9); }
.pad.colours button[aria-pressed="true"] {
  outline: 2px solid var(--ink);
  outline-offset: 1px;
}

/* The pen's ink picker. Same idea, full-strength inks. */
/* Five across, so nine swatches wrap 5+4 and read as a block rather than as a
   full row with one straggler underneath. */
.swatches { display: grid; grid-template-columns: repeat(5, 20px); gap: 4px; }
.swatches button {
  width: 20px; height: 20px; padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--r1); cursor: pointer;
}
.swatches button[aria-pressed="true"] { outline: 2px solid var(--ink); outline-offset: 1px; }
.swatches.inks button:nth-child(1) { background: var(--ink-c1); }
.swatches.inks button:nth-child(2) { background: var(--ink-c2); }
.swatches.inks button:nth-child(3) { background: var(--ink-c3); }
.swatches.inks button:nth-child(4) { background: var(--ink-c4); }
.swatches.inks button:nth-child(5) { background: var(--ink-c5); }
.swatches.inks button:nth-child(6) { background: var(--ink-c6); }
.swatches.inks button:nth-child(7) { background: var(--ink-c7); }
.swatches.inks button:nth-child(8) { background: var(--ink-c8); }
.swatches.inks button:nth-child(9) { background: var(--ink-c9); }

.pad { display: flex; gap: 4px; }
.pad button {
  width: 38px; height: 38px;
  border: 1px solid var(--line); background: var(--surface);
  color: var(--ink);
  border-radius: var(--r2); cursor: pointer;
  font-weight: 650; font-size: 16px;
  box-shadow: var(--shadow-1);
  transition: background .12s, transform .06s, border-color .12s;
}
.pad button:hover { background: var(--surface-2); border-color: var(--line-strong); }
.pad button:active { transform: translateY(1px); }

.status {
  font-size: 12.5px; color: var(--muted);
  display: flex; align-items: center; gap: var(--s2);
  min-height: 22px;
}
.status .pill, .pill {
  border-radius: 999px; padding: 2px 10px; font-weight: 650; font-size: 11.5px;
  background: var(--surface-2); color: var(--ink-2);
}
.pill.ok   { background: var(--good-soft); color: var(--good); }
.pill.warn { background: var(--warn-soft); color: var(--warn); }
.pill.bad  { background: var(--bad-soft);  color: var(--bad); }
.pill.dc1 { background: color-mix(in srgb, var(--dc1) 14%, transparent); color: var(--dc1); }
.pill.dc2 { background: color-mix(in srgb, var(--dc2) 14%, transparent); color: var(--dc2); }
.pill.dc3 { background: color-mix(in srgb, var(--dc3) 16%, transparent); color: var(--dc3); }
.pill.dc4 { background: color-mix(in srgb, var(--dc4) 15%, transparent); color: var(--dc4); }
.pill.dc5 { background: color-mix(in srgb, var(--dc5) 14%, transparent); color: var(--dc5); }

.explain {
  border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: var(--r2); background: var(--surface-2);
  padding: var(--s3); margin-bottom: var(--s3);
  font-size: 12.5px; line-height: 1.6;
  animation: settle .18s ease;
}
.explain h5 { margin: 0 0 4px; font-size: 12.5px; font-weight: 680; }
.explain .rule { color: var(--ink-2); margin-bottom: 6px; }
.explain .finding { color: var(--ink); }
.explain code {
  font-family: var(--font-mono); font-size: 11.5px;
  background: var(--surface-3); border-radius: 4px; padding: 1px 5px;
}

.choice-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--s2); }
.choice {
  border: 1px solid var(--line); border-radius: var(--r2); background: var(--surface);
  padding: var(--s2); cursor: pointer; text-align: center;
  transition: border-color .12s, background .12s;
}
.choice:hover { border-color: var(--accent-line); background: var(--surface-2); }
.choice svg { width: 100%; height: auto; display: block; margin-bottom: 6px; }
.choice .n { font-size: 12px; font-weight: 650; }

.pill.spin::before {
  content: '';
  display: inline-block;
  width: 9px; height: 9px;
  margin-right: 7px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  vertical-align: -1px;
  animation: whirl .7s linear infinite;
}
@keyframes whirl { to { transform: rotate(360deg); } }

/* ------------------------------------------------------------ side panel */
.tabs {
  display: flex; gap: 2px; padding: var(--s2) var(--s3) 0;
  border-bottom: 1px solid var(--line);
}
.tabs button {
  border: 0; background: transparent; cursor: pointer;
  padding: 7px 12px 9px; font-size: 13px; font-weight: 600;
  color: var(--muted); border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color .14s, border-color .14s;
}
.tabs button:hover { color: var(--ink-2); }
.tabs button[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); }

.pane { display: none; padding: var(--s4); min-height: 0; }
.pane[data-active] { display: block; }

.pane h4 {
  margin: var(--s5) 0 var(--s2);
  font-size: 10.5px; font-weight: 750; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
}
.pane h4:first-child { margin-top: 0; }

/* progress */
.progress { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s4); }
.progress-track {
  flex: 1; height: 6px; border-radius: 999px;
  background: var(--surface-3);
  overflow: hidden;
}
.progress-fill {
  height: 100%; width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent) 70%, var(--good)));
  transition: width .25s ease;
}
.progress-label {
  font-family: var(--font-mono); font-size: 11.5px; color: var(--muted);
  min-width: 52px; text-align: right;
}

.rules { font-size: 13px; line-height: 1.65; color: var(--ink-2); }
.rules ul { margin: 0; padding-left: 18px; }
.rules li { margin-bottom: var(--s2); }
.rules li::marker { color: var(--accent); }

.card {
  border: 1px solid var(--line); border-radius: var(--r2);
  background: var(--surface-2);
  padding: var(--s3);
}
.card + .card { margin-top: var(--s2); }

/* constraint list */
.clue-list { display: flex; flex-direction: column; gap: 3px; }
.clue {
  display: flex; align-items: center; gap: var(--s2);
  padding: 6px 8px; border-radius: var(--r1);
  border: 1px solid transparent;
  cursor: pointer; font-size: 12.5px;
}
.clue:hover { background: var(--surface-2); border-color: var(--line); }
.clue .swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.clue .who { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.clue .where { color: var(--muted); font-family: var(--font-mono); font-size: 11px; }
.clue .kill {
  border: 0; background: transparent; color: var(--muted); cursor: pointer;
  padding: 2px 5px; border-radius: 4px; opacity: 0; font-size: 14px; line-height: 1;
}
.clue:hover .kill { opacity: 1; }
.clue .kill:hover { background: var(--bad-soft); color: var(--bad); }

/* the current step */
.step {
  border: 1px solid var(--line);
  border-left: 3px solid var(--muted);
  border-radius: var(--r2); background: var(--surface-2);
  padding: var(--s3); margin-bottom: var(--s2);
  animation: settle .2s ease;
}
@keyframes settle { from { opacity: 0; transform: translateY(3px); } }
.step.dc1 { border-left-color: var(--dc1); }
.step.dc2 { border-left-color: var(--dc2); }
.step.dc3 { border-left-color: var(--dc3); }
.step.dc4 { border-left-color: var(--dc4); }
.step.dc5 { border-left-color: var(--dc5); }
.step .tech {
  display: flex; align-items: center; gap: var(--s2);
  font-weight: 680; font-size: 13px; margin-bottom: 4px;
}
.step .tech .n { color: var(--muted); font-family: var(--font-mono); font-weight: 500; font-size: 11px; }
.step .body { font-size: 12.5px; line-height: 1.62; color: var(--ink-2); }

.timeline { display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s3); }
.timeline[hidden] { display: none; }
.timeline input[type=range] { flex: 1; accent-color: var(--accent); }

/* the log */
.log { display: flex; flex-direction: column; gap: 2px; }
.log-row {
  display: flex; gap: var(--s2); align-items: center;
  padding: 5px 8px; border-radius: var(--r1); cursor: pointer;
  font-size: 12px; border: 1px solid transparent;
}
.log-row:hover { background: var(--surface-2); }
.log-row[data-current] { background: var(--accent-soft); border-color: var(--accent-line); }
.log-row .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--muted); }
.dot.dc1 { background: var(--dc1); }
.dot.dc2 { background: var(--dc2); }
.dot.dc3 { background: var(--dc3); }
.dot.dc4 { background: var(--dc4); }
.dot.dc5 { background: var(--dc5); }
.log-row .n { color: var(--muted); font-family: var(--font-mono); font-size: 10.5px; min-width: 24px; }
.log-row .t { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.report { font-size: 12.5px; line-height: 1.65; }
.report p { margin: 0 0 var(--s2); }
.report .hot {
  font-family: var(--font-mono); font-size: 11.5px;
  background: var(--surface-3); border-radius: 4px; padding: 1px 5px;
}

/* fields */
.field { display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s2); }
.field label { font-size: 12.5px; color: var(--ink-2); flex: 1; }
.field input[type=text], .field input[type=number], .field select {
  border: 1px solid var(--line); background: var(--surface-2);
  border-radius: var(--r1); padding: 4px 8px; font-size: 12.5px;
  min-width: 0; width: 130px;
}
.field.stack { flex-direction: column; align-items: stretch; gap: 4px; }
.field.stack input, .field.stack select, .field.stack textarea { width: 100%; }
textarea {
  border: 1px solid var(--line); background: var(--surface-2);
  border-radius: var(--r1); padding: 6px 8px; font-size: 12.5px;
  resize: vertical; min-height: 64px; width: 100%;
}

.hint { font-size: 11.5px; color: var(--muted); line-height: 1.55; }

/* toast */
.toast-host {
  position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
  display: flex; flex-direction: column; gap: var(--s2);
  z-index: 100; pointer-events: none;
}
.toast {
  background: var(--ink); color: var(--bg);
  padding: 9px 18px; border-radius: 999px;
  font-size: 13px; font-weight: 600;
  box-shadow: var(--shadow-3);
  animation: rise .22s cubic-bezier(.2, .8, .3, 1);
}
.toast.bad { background: var(--bad); color: #fff; }
.toast.good { background: var(--good); color: #fff; }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }

/* modal */
.modal-host {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(22, 19, 15, .45);
  display: none; align-items: center; justify-content: center;
  padding: var(--s5);
  backdrop-filter: blur(2px);
}
.modal-host[data-open] { display: flex; }
.modal {
  background: var(--surface); border-radius: var(--r4);
  box-shadow: var(--shadow-3);
  width: min(580px, 100%); max-height: 84vh;
  display: flex; flex-direction: column;
  border: 1px solid var(--line);
  animation: settle .18s ease;
}
.modal header {
  padding: var(--s4) var(--s5) var(--s3);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: var(--s3);
}
.modal header h2 { margin: 0; font-size: 16px; font-weight: 680; }
.modal .content { padding: var(--s4) var(--s5); overflow-y: auto; }
.modal footer {
  padding: var(--s3) var(--s5) var(--s4);
  border-top: 1px solid var(--line);
  display: flex; gap: var(--s2); justify-content: flex-end;
}

.library { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); }
.lib-item {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); border: 1px solid var(--line);
  border-radius: var(--r2); cursor: pointer; background: var(--surface);
  text-align: left;
  transition: border-color .12s, background .12s, transform .06s;
}
.lib-item:hover { border-color: var(--accent-line); background: var(--surface-2); }
.lib-item:active { transform: translateY(1px); }
.lib-item .t { font-weight: 650; font-size: 13px; }
.lib-item .d { font-size: 11.5px; color: var(--muted); line-height: 1.4; }

/* ------------------------------------------------------------ utilities */
/* These exist so no markup needs a style attribute. That lets the deployed
   Content-Security-Policy be `style-src 'self'` with no inline exception —
   see HOSTING.md. */
.grow { flex: 1; }
.bar-start { justify-content: flex-start; gap: 6px; }
.mt-0 { margin-top: 0; }
.mt-6 { margin-top: 6px; }
.mt-8 { margin-top: 8px; }
.mt-10 { margin-top: 10px; }
.mt-12 { margin-top: 12px; }
.mb-10 { margin-bottom: 10px; }
.mb-14 { margin-bottom: 14px; }
.tight { margin: 0 0 4px; }
.row-tight { margin: -4px 0 6px; }
.field-inset { margin: 8px 4px 0; }
.bad-text { color: var(--bad); }
.warn-text { color: var(--warn); }
.count { color: var(--muted); font-weight: 600; }

.clue .swatch[data-cat="line"] { background: var(--line-renban); }
.clue .swatch[data-cat="cage"] { background: var(--cage); }
.clue .swatch[data-cat="edge"] { background: var(--ink); }
.clue .swatch[data-cat="corner"] { background: var(--ink); }
.clue .swatch[data-cat="cell"] { background: var(--line-strong); }
.clue .swatch[data-cat="outside"] { background: var(--accent); }
.clue .swatch { background: var(--muted); }

/* ------------------------------------------------------------- printing */
/* The browser's own "Save as PDF" is the export: no library, real vector
   output, and it prints properly on paper too. Everything but the grid and the
   rules is hidden, and the light palette is forced so a dark-theme screen does
   not produce a page of black ink. */
.print-sheet { display: none; }

@media print {
  :root, :root[data-theme="dark"] {
    --bg: #fff; --surface: #fff; --surface-2: #fff; --surface-3: #eee;
    --ink: #000; --ink-2: #222; --muted: #555;
    --line: #bbb; --line-strong: #666; --grid-thin: #999; --grid-bold: #000;
    --given: #000; --solved: #000; --pencil: #666;
    --accent: #000; --accent-line: #666; --cage: #000;
    --fog: #ddd; --fog-edge: #999;
  }
  html, body { height: auto; overflow: visible; background: #fff; }
  .topbar, .palette, .side, .boardbar, .status, .toast-host, .modal-host { display: none !important; }
  .app, main { display: block; height: auto; }
  .board { padding: 0; background: none; display: block; }
  .board-wrap { width: 100%; max-width: 170mm; aspect-ratio: 1; margin: 0 auto; }
  #grid { box-shadow: none; border: 0; }

  .print-sheet { display: block; margin: 0 auto; max-width: 170mm; }
  .print-sheet h1 { font-size: 15pt; margin: 0 0 2mm; font-weight: 700; }
  .print-sheet .by { font-size: 10pt; color: #444; margin: 0 0 4mm; }
  .print-sheet h2 { font-size: 10pt; margin: 6mm 0 2mm; text-transform: uppercase;
                    letter-spacing: .08em; color: #444; }
  .print-sheet ul { margin: 0; padding-left: 5mm; font-size: 10pt; line-height: 1.5; }
  .print-sheet li { margin-bottom: 1.5mm; }
  .print-sheet .foot { margin-top: 6mm; font-size: 8pt; color: #777; }
  @page { margin: 12mm; }
}

/* --------------------------------------------------------- responsive */
@media (max-width: 1220px) {
  main { grid-template-columns: 216px minmax(0, 1fr) 330px; }
  .tools { grid-template-columns: 1fr; }
}
/* ------------------------------------------------------------ handheld */
/* Below 980px the three columns stack: grid first, because that is what you
   came for, then the tools, then the panels. */
@media (max-width: 980px) {
  body { overflow: auto; -webkit-text-size-adjust: 100%; }
  .app { height: auto; min-height: 100dvh; }
  main { grid-template-columns: 1fr; grid-template-rows: auto auto auto; }
  .board { order: 1; padding: var(--s3) var(--s2); }
  .palette { order: 2; }
  .side { order: 3; }
  .palette, .side { border: 0; border-top: 1px solid var(--line); max-height: none; }
  .board-wrap { width: min(100%, 560px); }
  .library { grid-template-columns: 1fr; }

  /* the header wraps rather than squeezing everything to nothing */
  .topbar { height: auto; flex-wrap: wrap; padding: var(--s2) var(--s3); gap: var(--s2); }
  .brand { font-size: 13.5px; }
  .brand small { display: none; }
  .spacer { display: none; }

  /* the palette is a scrolling strip instead of a tall column */
  .palette .scroll { max-height: 42vh; }
}

@media (max-width: 640px) {
  /* Touch targets. A finger wants about 44px in both directions, and nine
     buttons in a row cannot give that on a phone — they come out around 36
     wide. So the pad becomes a 3x3 keypad instead: the same reading order as
     the grid, comfortably large, and easier to hit without looking. */
  .pad {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
    width: 100%;
    max-width: 264px;
    margin: 0 auto;
  }
  .pad button { width: 100%; height: 46px; font-size: 18px; }
  .segmented button { padding: 8px 14px; font-size: 14px; }
  .segmented.glyphs button { padding: 8px 12px; }
  .btn { padding: 9px 14px; font-size: 14px; }
  .btn.sm { padding: 7px 12px; font-size: 13px; }
  .btn.icon { padding: 9px 11px; }
  .tabs button { padding: 10px 14px 11px; font-size: 14px; }
  .tool { min-height: 46px; }
  .toggle-row { padding: 9px 8px; }
  .toggle-row input { width: 18px; height: 18px; }
  .clue { padding: 10px 8px; }
  .clue .kill { opacity: 1; padding: 6px 8px; }   /* no hover on touch */
  .log-row { padding: 8px; }

  .board { padding: var(--s2) 0; }
  .board-wrap { width: 100%; }
  #grid { border-radius: var(--r2); }
  .boardbar { gap: 6px; padding: 0 var(--s2); max-width: 100%; }
  .pane { padding: var(--s3); }

  /* the digit pad is the thing you reach for most, so give it its own row */
  .pad { order: -1; }
}

/* A coarse pointer means touch, whatever the screen size — a tablet in
   landscape is wide but still finger-driven. */
@media (pointer: coarse) {
  .clue .kill { opacity: 1; }
  .pad button, .btn, .tabs button { touch-action: manipulation; }
  /* stop a long press selecting text or firing the callout menu mid-drag */
  #grid, .pad, .boardbar {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
  }
}


/* ------------------------------------------------------------- the cube */
/* The canvas sits where the sheets do and only one of them is ever shown, so
   the board keeps its size and the toggle does not shift the page under you. */
#cube { display: block; width: 100%; aspect-ratio: 1 / 1; touch-action: none;
        cursor: grab; border-radius: 10px; }
#cube:active { cursor: grabbing; }
#cube[hidden], #grid[hidden] { display: none; }
.cubebar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
           margin: 0 0 8px; }
.cubebar[hidden] { display: none; }
.cubebar .seg { display: flex; gap: 2px; background: var(--surface-2);
                border-radius: 8px; padding: 2px; }
/* A `display` of its own beats the browser's [hidden] { display: none }, so
   every rule that sets one has to say what hidden means as well. Without this
   the slice stepper was never actually put away in the shell and cross views —
   `setShown` set the attribute, the flex above went on winning, and nothing
   noticed because the tests only ever asserted that it was *shown*. The same
   line already exists for .cubebar itself, which is where this was found the
   first time. */
.cubebar .seg[hidden] { display: none; }
.cubebar .seg .btn { border-radius: 6px; }
/* --ink, not --text: there is no --text in the palette, so this resolved to
   "invalid at computed-value time" and the selected view button fell back to
   inheriting its colour instead of taking the app's ink. Same missing name the
   cube canvas asked for, in a second costume. */
.cubebar .seg .btn.on { background: var(--accent-soft); color: var(--ink); }

/* The view key in Help: a name and what it shows, so six modes can be read
   down rather than picked out of a paragraph. */
.viewkey { border-collapse: collapse; margin: 6px 0 10px; }
.viewkey td { padding: 3px 12px 3px 0; vertical-align: top; }
.viewkey td:first-child { white-space: nowrap; }

.cubebar .slicenav { align-items: center; }
.cubebar .slicelabel { padding: 0 10px; font-size: 12px; color: var(--muted);
                       min-width: 8.5em; text-align: center; font-variant-numeric: tabular-nums; }
