:root {
  --bg: #0f1220;
  --panel: #181c2e;
  --panel-2: #20253c;
  --line: #2c3354;
  --ink: #e8eaf2;
  --muted: #9aa3c4;
  --accent: #6ea8fe;
  --good: #51cf66;
  --bad: #ff6b6b;
  --yes: #2f9e44;
  --no: #495063;
  --radius: 12px;
  --cell: 2.2rem;        /* square grid cell */
  --rowlab: 4.75rem;     /* fixed row-label column width */
  --header-h: 6.25rem;   /* fixed column-header band height */
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: radial-gradient(1200px 600px at 50% -10%, #1a1f38 0%, var(--bg) 60%);
  color: var(--ink);
  min-height: 100vh;
  padding: 1.5rem clamp(1rem, 4vw, 3rem) 3rem;
}

header { text-align: center; margin-bottom: 1.5rem; }
h1 { margin: 0 0 .25rem; font-size: clamp(1.6rem, 4vw, 2.4rem); }
.tagline { color: var(--muted); margin: 0; }
.tagline b { color: var(--ink); font-weight: 600; }

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: end;
  justify-content: center;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  max-width: 1100px;
  margin: 0 auto 1.5rem;
}
.controls label[hidden] { display: none; }  /* flex below would defeat [hidden] */
.controls label {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  font-size: .8rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.controls label.check {
  flex-direction: row;
  align-items: center;
  gap: .45rem;
  text-transform: none;
  letter-spacing: normal;
  font-size: .95rem;
  color: var(--ink);
  align-self: end;
  padding-bottom: .5rem;
  cursor: pointer;
}
.controls label.check input { width: auto; padding: 0; margin: 0; accent-color: var(--accent); }

select, input, button {
  font: inherit;
  color: var(--ink);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: .5rem .7rem;
}
input { width: 9rem; }
button { cursor: pointer; transition: border-color .15s, background .15s, transform .05s; }
button:hover { border-color: var(--accent); }
button:active { transform: translateY(1px); }
button:disabled { opacity: .4; cursor: default; transform: none; }
button:disabled:hover { border-color: var(--line); }
button.primary { background: var(--accent); color: #0b1020; border-color: var(--accent); font-weight: 600; }
button.primary:hover { filter: brightness(1.08); }

.puzzle-head { text-align: center; max-width: 800px; margin: 0 auto 1.5rem; }
#p-name { margin: 0 0 .4rem; font-size: 1.6rem; }
.desc { color: var(--muted); margin: 0 0 .5rem; line-height: 1.5; }
.meta { color: var(--muted); font-size: .85rem; margin: 0; }
.meta .muted { font-style: italic; opacity: .85; }
.meta code { background: var(--panel-2); padding: .1rem .4rem; border-radius: 5px; }

/* Desktop: clues · grid · sidebar (table on top, hint/feedback below).
   Medium: drop the sidebar under the grid. Mobile: single column. */
.layout {
  display: grid;
  /* sidebar width (--side-w) is sized to the table so its columns never scroll */
  grid-template-columns: minmax(200px, 250px) minmax(0, 1fr) var(--side-w, 320px);
  grid-template-areas: "clues grids side";
  gap: 1.5rem;
  max-width: 1380px;
  margin: 0 auto;
  align-items: start;
}
.clues-panel { grid-area: clues; }
.grids-panel { grid-area: grids; }
.side-panel  { grid-area: side; display: flex; flex-direction: column; gap: 1.25rem; }

/* Below the 3-column breakpoint, drop the table+hint under the grid where they
   get the full content width (so the table fits without scrolling). */
@media (max-width: 1299px) {
  .layout {
    grid-template-columns: minmax(220px, 300px) minmax(0, 1fr);
    grid-template-areas:
      "clues grids"
      "clues side";
  }
}
@media (max-width: 820px) {
  .layout {
    grid-template-columns: 1fr;
    grid-template-areas: "clues" "grids" "side";
  }
}

.clues-panel, .grids-panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
}
.clues-panel h3, .grids-panel h3 { margin: 0 0 .75rem; }
.clues-head { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; margin: 0 0 .75rem; }
.clues-head h3 { margin: 0; }
#uncross { font-size: .75rem; padding: .15rem .5rem; color: var(--muted); }
#uncross:hover { color: var(--ink); }
/* When hidden, keep the button's box in the layout (invisible, not gone) so
   revealing it never changes the header row's height and bumps the clues. */
#uncross[hidden] { display: inline-block; visibility: hidden; }
#clues { margin: 0; padding-left: 1.4rem; line-height: 1.7; }
#clues li { padding-left: .2rem; cursor: pointer; border-radius: 4px; }
#clues li:hover { color: #fff; }
#clues li:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#clues li::marker { color: var(--accent); }
/* click a clue to strike it through once you've used it */
#clues li.done { text-decoration: line-through; opacity: .45; }
#clues li.done::marker { color: var(--muted); }

.grid-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  align-items: center;
  margin-bottom: 1rem;
}
.hint-btn { border-color: var(--accent); color: var(--accent); }
.hint-btn:hover { background: rgba(110, 168, 254, .12); }

/* Solve timer — pinned to the right of the actions bar, tabular so the digits
   don't jitter as the tenths roll over. Greens out once the puzzle is solved. */
.timer {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  font-size: .95rem;
  color: var(--muted);
  letter-spacing: .02em;
}
.timer.done { color: var(--good); font-weight: 600; }

/* Check lights up once the live solution table is fully filled in. */
#check.ready {
  background: var(--good);
  color: #06210d;
  border-color: var(--good);
  font-weight: 600;
  animation: check-ready 1.3s ease-in-out infinite;
}
@keyframes check-ready { 50% { box-shadow: 0 0 0 4px rgba(81, 207, 102, .25); } }

/* --- Feedback banner (hints + check results). Reserves its height so showing
   or clearing it never shifts the grid below; invisible when empty. --- */
.feedback {
  min-height: 2.6rem;  /* sits at the foot of the sidebar, so it can't shift the grid */
  margin: 0;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  padding: .65rem .85rem;
  line-height: 1.5;
  font-size: .92rem;
  /* Centers the single wrapper div setFeedback puts around every message.
     The wrapper is load-bearing: bare inline children would each become
     their own flex item, and flex swallows the spaces between items
     ("Press Hint" hugged). Inside the div, text flows normally. */
  display: flex;
  align-items: center;
}
/* persistent status bar even with no message (muted), so it never pops in/out */
.feedback.empty { border-left-color: var(--line); color: var(--muted); }
.feedback.good { border-left-color: var(--good); color: var(--good); }
.feedback.warn { border-left-color: #f0b429; color: #f6c453; }
.feedback.bad { border-left-color: var(--bad); color: var(--bad); }
.feedback b { color: inherit; }
.hint-tier {
  display: inline-block;
  background: var(--accent);
  color: #0b1020;
  font-weight: 700;
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  padding: .12rem .45rem;
  border-radius: 5px;
  margin-right: .5rem;
  vertical-align: middle;
}
.hint-cta { color: var(--muted); }
.hint-placed { color: var(--good); font-weight: 600; }
.hint-chain { margin-top: .5rem; }
.hint-chain > summary {
  cursor: pointer;
  color: var(--accent);
  font-weight: 600;
  font-size: .85rem;
  list-style: none;
}
.hint-chain > summary::before { content: "▸ "; }
.hint-chain[open] > summary::before { content: "▾ "; }
.hint-chain ol {
  margin: .4rem 0 .2rem;
  padding-left: 1.4rem;
  color: var(--muted);
  font-size: .9rem;
  line-height: 1.45;
}
.hint-chain ol li { margin: .12rem 0; }
.hint-chain ol li:last-child { color: var(--text); font-weight: 600; }

/* the cell a pending hint points at: a soft pulse until revealed */
td.cell.hint-target { outline: 2px solid var(--accent); outline-offset: -2px; animation: hint-pulse 1s ease-in-out infinite; }
@keyframes hint-pulse { 50% { outline-color: #fff; } }
td.cell.hint-flash { animation: hint-flash .8s ease-out; }
@keyframes hint-flash { 0% { background: var(--accent); } 100% { } }

/* --- Answer key (print only) --- */
.answer-key { max-width: 1200px; margin: 1.5rem auto 0; }
.key-table { border-collapse: collapse; }
.key-table th, .key-table td { border: 1px solid var(--line); padding: .4rem .7rem; text-align: left; font-size: .9rem; }
.key-table th { background: var(--panel-2); }

/* --- Live solution table: fills in from the user's ✓ links --- */
.progress {
  margin: 0;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
}
.progress h3 { margin: 0 0 .6rem; font-size: 1rem; display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.progress-count { font-size: .82rem; font-weight: 600; color: var(--muted); }
.progress-count.done { color: var(--good); }
/* Equal-width columns (table-layout: fixed) sized to fit by the sidebar width,
   so there is no horizontal scroll and every column is the same width. */
.progress-table { width: 100%; table-layout: fixed; }
.progress-table th, .progress-table td {
  padding: .35rem .45rem;
  font-size: .76rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.progress-table td { transition: color .15s, background .15s; }
.progress-table td.blank { background: var(--panel-2); }
.progress-table td:first-child, .progress-table th:first-child { color: var(--ink); font-weight: 600; }

#grids {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.5rem 1.25rem;
}
#grids.board-staircase { display: block; overflow-x: auto; }
.staircase-wrap { display: flex; justify-content: center; min-width: max-content; }

/* ---- Desktop interlocked staircase grid ---- */
table.staircase { table-layout: fixed; border-collapse: collapse; }
col.sc-catcol { width: 1.7rem; }
col.sc-rowlab-col { width: var(--rowlab); }
table.staircase th, table.staircase td {
  border: 1px solid var(--line);
  text-align: center;
  overflow: hidden;
}
table.staircase .sc-corner { border: none; background: transparent; }
th.sc-colcat {
  font-size: .82rem;
  font-weight: 600;
  color: var(--ink);
  padding: .3rem .2rem;
  background: var(--panel-2);
}
th.sc-rowcat { background: var(--panel-2); padding: 0; vertical-align: middle; }
th.sc-rowcat span {
  display: inline-block;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
  font-size: .82rem;
  font-weight: 600;
  color: var(--ink);
}
table.staircase td.void { border: none; background: transparent; cursor: default; }
table.staircase .blk-left { border-left: 2px solid var(--muted); }
table.staircase .blk-top { border-top: 2px solid var(--muted); }

/* Thin (1px) solid sub-dividers between the groups of a hierarchical category —
   thinner than the 2px category dividers, and solid so the dashes don't read as
   gaps in the color-coded band. */
table.staircase .grp-left, table.grid .grp-left { border-left: 1px solid var(--muted); }
table.staircase .grp-top, table.grid .grp-top { border-top: 1px solid var(--muted); }

/* Labelled, color-coded guild band over a grouped category's items, on the top
   (horizontal) and left (vertical) axes. The label is ABSOLUTELY placed inside an
   inner .gl-i capped to the padded box, so it is out of flow and can never grow a
   data cell — squares stay square and it can't push the table wider. JS
   (fitGuildBands / sizeGuildColumns) grows the band's free dimension — the top
   band's height (--gband-h), the left band's column width — then only shrinks the
   font if a single word still overflows the cell-bound dimension. Ungrouped
   categories get a plain filler so no color bleeds under them. */
th.sc-guild, th.g-band, th.sc-rowguild, th.sc-rowsuper {
  position: relative;
  padding: 0;
  background-color: var(--panel-2);  /* translucent guild tint over the panel — no
     color-mix, so the color also renders on older mobile browsers */
  background-image: linear-gradient(var(--gcolor-soft, transparent), var(--gcolor-soft, transparent));
}
th.sc-guild, th.g-band { border-bottom: 2px solid var(--gcolor); height: var(--gband-h, 2.4rem); }
th.sc-rowguild, th.sc-rowsuper { border-right: 2px solid var(--gcolor); }
col.sc-rowguild-col, col.sc-rowsuper-col { width: 1.9rem; }   /* starting width; JS widens it to fit */
.gl {
  position: absolute;
  inset: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px;
}
.gl-i {
  max-width: 100%;
  max-height: 100%;
  min-width: 0;                 /* flex items default to min-content width, which
     would let the box grow to the longest word so it never "overflows" and the
     shrink-to-fit can't see it — pin to 0 so the word overflows and is detected */
  min-height: 0;
  overflow: hidden;
  text-align: center;
  line-height: 1.12;
  white-space: normal;
  overflow-wrap: normal;        /* wrap only at word boundaries — never mid-word */
  word-break: normal;
  font-size: var(--glfs, .72rem);
  font-weight: 600;
  color: var(--ink);
}
th.sc-rowguild .gl-i, th.sc-rowsuper .gl-i { writing-mode: vertical-rl; transform: rotate(180deg); }  /* match the row-category label */
/* Band cells drop their base borders, but the thin grp-left/grp-top divider
   between adjacent tags stays (the higher-specificity .grp-left/.grp-top
   rules above win the border side they set) — with two stacked band tiers, a
   color change alone doesn't mark a split as crisply as the divider running
   through both tiers and the grid below. Category dividers (blk-left/blk-top)
   and each band's colored edge (bottom for top, right for left) still show. */
th.sc-guild, th.g-band { border-left-width: 0; border-right-width: 0; }
th.sc-rowguild, th.sc-rowsuper { border-top-width: 0; border-bottom-width: 0; }

.grid-block {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.grid-block h4 {
  margin: 0 0 .5rem;
  font-size: .9rem;
  color: var(--muted);
  font-weight: 600;
  text-align: center;
}
.grid-block h4 b { color: var(--ink); }

/* --- Groups panel: distinct scratch grids for hierarchy membership --- */
/* table-layout:fixed + colgroup => identical dimensions regardless of text */
table.grid { table-layout: fixed; border-collapse: collapse; }
col.rowlab-col { width: var(--rowlab); }
col.cell-col { width: var(--cell); }

table.grid th, table.grid td {
  border: 1px solid var(--line);
  text-align: center;
  overflow: hidden;
}

th.col {
  height: var(--header-h);
  padding: 0 0 4px;       /* ~4px below the label, between it and the data cells */
  vertical-align: bottom;
}
th.col span {            /* column label rotated to a vertical band */
  display: inline-block;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
  line-height: var(--cell);
  max-height: calc(var(--header-h) - 4px - .35rem);
  text-overflow: ellipsis;
  font-size: .68rem;
  font-weight: 500;
  color: var(--muted);
}
th.row {
  font-size: .72rem;
  font-weight: 500;
  color: var(--muted);
  text-align: right;
  padding: 0 .4rem;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* The top-left blank should read as empty space, not a boxed cell. Scoped to
   table.grid so it beats the `table.grid th` border rule (higher specificity);
   transparent so a guild band's tint/divider never bleeds across it. */
table.grid th.corner, th.corner { border: none; background: transparent; }

td.cell {
  width: var(--cell);
  height: var(--cell);
  padding: 0;
  cursor: pointer;
  font-size: calc(var(--cell) * 0.55);  /* glyph scales with the cell */
  font-weight: 600;
  line-height: 1;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation; /* kill the 300ms / double-tap-zoom delay on mobile */
  background: var(--panel-2);
  transition: background .1s;
}
td.cell:hover { background: #2a3150; }
td.cell.yes { color: var(--good); }
/* A × is dim by default (tentative); a hand-placed one is bright white. */
td.cell.no { color: var(--no); opacity: .45; }
td.cell.no.lit { opacity: 1; color: #ffffff; }
td.cell.wrong { background: rgba(255, 107, 107, .25); }
td.cell.right { background: rgba(81, 207, 102, .18); }

/* --- Color-blind mode (body.cblind, toggled in the controls) --------------
   The most common color-vision deficiencies (deuter-/protanopia) make the
   green "✓ / correct / good" and red "✗-mistake / bad" cues hard to tell apart.
   The ✓(=) and ✗(×) glyphs already differ by *shape*, so the grid marks stay
   legible regardless; this swap targets the places where color is the only
   signal — a correct vs mistaken cell, a good vs bad banner — repainting the
   red/green pair as blue/orange, which stays distinct across all common types.
   It only re-points the shared palette variables (plus the two hard-coded cell
   tints), so every dependent element re-colors automatically. */
body.cblind {
  --good: #4dabf7;   /* links, correct marks, success banners → blue   */
  --bad:  #f08c2e;   /* mistakes, error banners               → orange */
  --yes:  #1c7ed6;
}
body.cblind td.cell.wrong { background: rgba(240, 140, 46, .30); }
body.cblind td.cell.right { background: rgba(77, 171, 247, .22); }

.loading { text-align: center; color: var(--muted); }
.error { text-align: center; color: var(--bad); background: rgba(255,107,107,.1); border: 1px solid var(--bad); border-radius: 8px; padding: .75rem; max-width: 600px; margin: 1rem auto; }

footer { text-align: center; color: var(--muted); font-size: .8rem; margin-top: 2.5rem; }
/* Subtle "Hire me" — its own centered line below the footer note, low-key until hover. */
footer .hire {
  display: block;
  margin-top: .5rem;
  font-size: .72rem;
  letter-spacing: .03em;
  color: var(--muted);
  text-decoration: none;
  opacity: .45;
  transition: opacity .15s, color .15s;
}
footer .hire:hover { opacity: 1; color: var(--accent); }
/* Low-key link to the GitHub repo, part of the footer note line. */
footer .src { color: var(--muted); text-decoration: underline; text-underline-offset: 2px; }
footer .src:hover { color: var(--accent); }

/* nav link to the guide from the solver header */
.nav-links { text-align: center; margin: .25rem 0 0; }
.nav-links a { color: var(--accent); text-decoration: none; font-size: .9rem; }
.nav-links a:hover { text-decoration: underline; }

/* ============================ Guide / how-to page ============================ */
.guide .crumb { margin: 0 0 1rem; }
.guide .crumb a, .btn-link { color: var(--accent); text-decoration: none; }
.guide .crumb a:hover, .btn-link:hover { text-decoration: underline; }
.guide-body { max-width: 980px; margin: 0 auto; }

.guide-body .card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.4rem 1.5rem;
  margin: 0 auto 1.5rem;
}
.guide-body h2 { margin: 0 0 .5rem; font-size: 1.35rem; }
.guide-body h3.sub { margin: 1.25rem 0 .4rem; font-size: 1.05rem; color: var(--ink); }
.guide-body p { line-height: 1.65; margin: 0 0 .85rem; }
.guide-body .lead { color: var(--muted); }
.guide-body b { color: var(--ink); }
.guide-body i { color: var(--ink); font-style: italic; }
.guide-body em { color: var(--accent); font-style: normal; font-weight: 600; }

.tip {
  background: var(--panel-2);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  padding: .65rem .85rem;
  color: var(--muted);
}
.tip b { color: var(--ink); }

/* Inline link (=) / cross icons, matching the marks on the puzzle grid:
   masked squares that inherit the surrounding text's size, so they sit flush
   in any font context (the raw unicode glyphs came from fallback fonts and
   looked out of place). The = takes the grid's link color; the cross inherits
   the text color around it. */
.mk {
  display: inline-block;
  width: .85em; height: .85em;
  background: currentColor;
  /* sits a touch below the baseline so the glyph centers on the x-height of
     the surrounding text (chips center it themselves, so this only matters
     for icons free-floating in a line of text) */
  vertical-align: -.125em;
  -webkit-mask: var(--mk-icon) center / contain no-repeat;
  mask: var(--mk-icon) center / contain no-repeat;
}
.mk-yes {
  color: var(--good);
  --mk-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.2 5.6h9.6M3.2 10.4h9.6' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round'/%3E%3C/svg%3E");
}
.mk-no  { --mk-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.7 3.7l8.6 8.6M12.3 3.7l-8.6 8.6' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }

/* legend chips and inline ✓/✗ marks */
.legend { list-style: none; padding: 0; margin: 0 0 .85rem; display: grid; gap: .5rem; }
/* chip + text wrapper: flex centers the chip against the text line(s) */
.legend li { line-height: 1.5; display: flex; align-items: center; }
.chip {
  display: inline-grid;
  place-items: center;
  width: 1.5rem; height: 1.5rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-2);
  font-weight: 700;
  vertical-align: middle;
  margin-right: .35rem;
}
.chip.yes { color: var(--good); }
.chip.no { color: #fff; }
.chip.blank { color: transparent; }

/* clue cards */
.rules { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem; }
.rule {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 1rem 1.1rem;
}
.rule h3 { margin: 0 0 .55rem; font-size: 1.05rem; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.rule p { margin: 0 0 .5rem; font-size: .92rem; line-height: 1.55; }
.rule p:last-child { margin-bottom: 0; }
.rule .eg { color: var(--accent); font-style: italic; }

.tag {
  font-size: .62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  padding: .15rem .45rem;
  border-radius: 999px;
  white-space: nowrap;
}
.tag.pos   { background: rgba(81, 207, 102, .18); color: var(--good); }
.tag.neg   { background: rgba(255, 107, 107, .16); color: var(--bad); }
.tag.ord   { background: rgba(110, 168, 254, .18); color: var(--accent); }
.tag.logic { background: rgba(201, 167, 255, .18); color: #c9a7ff; }
.tag.group { background: rgba(255, 196, 110, .18); color: #ffc46e; }

/* technique ladder */
.techniques { list-style: none; counter-reset: tier; padding: 0; margin: 0; display: grid; gap: 1rem; }
.techniques li {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: 10px;
  padding: .85rem 1.1rem;
}
.techniques .tier {
  display: inline-block;
  font-weight: 700;
  color: var(--accent);
  font-size: .9rem;
  margin-bottom: .3rem;
}
.techniques p { margin: 0; font-size: .94rem; line-height: 1.6; }

.strategy { margin: 0; padding-left: 1.3rem; line-height: 1.75; }
.strategy li { margin-bottom: .4rem; }
.strategy li::marker { color: var(--accent); }

.back-cta { text-align: center; margin: .5rem 0 0; }

/* --- Print: clean black-on-white puzzle + a tear-off answer key page --- */
@media print {
  body { background: #fff; color: #000; padding: .5rem; }
  .controls, .grid-actions, #uncross, #feedback, #progress, #claim, .board-panel, footer, .tagline, .nav-links, #loading, #error { display: none !important; }
  header { margin-bottom: .75rem; }
  header h1 { color: #000; font-size: 1.4rem; }
  #p-name, #p-desc, .meta, .meta code { color: #000; }
  .meta code { background: none; }

  .layout { display: block; max-width: none; }
  .clues-panel, .grids-panel { background: none; border: none; border-radius: 0; padding: 0; margin-bottom: 1rem; }
  .clues-panel h3, .grids-panel h3 { color: #000; }
  #clues, #clues li { color: #000; }
  #clues li::marker { color: #000; }
  #clues li.done { opacity: 1; }   /* keep struck clues legible on paper */

  /* black grid lines, blank cells (the marks are hidden so it can be solved on paper) */
  #grids.board-staircase { overflow: visible; }
  table.grid th, table.grid td,
  table.staircase th, table.staircase td { border-color: #000; }
  th.col span, th.row, .grid-block h4, .grid-block h4 b,
  th.sc-colcat, th.sc-rowcat span, .gl-i { color: #000 !important; }
  table.staircase .blk-left, table.staircase .blk-top,
  .grp-left, .grp-top { border-color: #000 !important; }
  th.sc-guild, th.g-band, th.sc-rowguild, th.sc-rowsuper { background: #eee !important; border-color: #000 !important; }
  td.cell { background: #fff !important; color: transparent !important; }

  /* answer key starts a fresh page so it can be torn off */
  .answer-key { display: block !important; break-before: page; page-break-before: always; }
  .answer-key h3 { color: #000; }
  .key-table th, .key-table td { border-color: #000; color: #000; }
  .key-table th { background: #eee; }
}

/* --- Daily challenge: leaderboard + claim panels (sidebar, /daily only) --- */
.daily-info {
  font-size: .8rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  align-self: center;
}
.board-panel, .claim {
  margin: 0;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
}
.board-panel h3, .claim h3 { margin: 0 0 .6rem; font-size: 1rem; display: flex; align-items: baseline; gap: .5rem; }
.board-list { margin: 0; padding-left: 1.6rem; }
.board-list li {
  display: flex;
  justify-content: space-between;
  gap: .75rem;
  padding: .25rem 0;
  font-size: .88rem;
  border-bottom: 1px solid var(--panel-2);
}
.board-list li:last-child { border-bottom: none; }
.board-list li::marker { color: var(--muted); font-size: .8rem; }
.board-list li.own { color: var(--accent); font-weight: 600; }
.board-list li.own::marker { color: var(--accent); }
.board-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-time { font-variant-numeric: tabular-nums; color: var(--muted); flex-shrink: 0; }
.board-list li.own .board-time { color: var(--accent); }
.board-empty { margin: .25rem 0 0; font-size: .85rem; color: var(--muted); }

.claim-time { margin: 0 0 .75rem; font-size: .9rem; color: var(--muted); }
.claim-time b { color: var(--good); }
.claim label {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  font-size: .8rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-bottom: .75rem;
}
.claim input {
  width: 100%; /* the global input rule is 9rem (free play's seed box) */
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--ink);
  padding: .5rem .6rem;
  font-size: .95rem;
}
.claim input:focus { outline: none; border-color: var(--accent); }
.claim-error { margin: .6rem 0 0; font-size: .85rem; color: var(--bad); }
.claim-note { margin: 0 0 .75rem; font-size: .82rem; color: var(--muted); }
.claim-note a { color: var(--accent); }

/* Big-puzzles catalog: difficulty tabs, size layers, puzzle tiles. */
.catalog { max-width: 900px; margin: 0 auto; padding: 0 1rem; }
.band-tabs { display: flex; gap: .4rem; flex-wrap: wrap; justify-content: center; margin: .5rem 0 1rem; }
.band-tab {
  background: var(--panel);
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .35rem .9rem;
  font-size: .85rem;
  cursor: pointer;
}
.band-tab:hover { color: var(--ink); border-color: var(--accent); }
.band-tab.active { color: var(--ink); border-color: var(--accent); background: var(--panel-2); font-weight: 600; }
.layer-head { margin: 1.1rem 0 .5rem; font-size: .95rem; color: var(--muted); font-weight: 600; }
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: .6rem; }
.tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .45rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: .7rem .8rem;
  cursor: pointer;
  text-align: left;
  color: var(--ink);
  font: inherit;
}
.tile:hover { border-color: var(--accent); }
.tile-id { font-weight: 700; font-size: 1.05rem; }
.tile-tags { display: flex; flex-wrap: wrap; gap: .3rem; }
.tile-tags .tag {
  font-size: .7rem;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .1rem .5rem;
  white-space: nowrap;
}
.tile-tags .tag-adjusted { color: var(--accent); border-color: var(--accent); }
.tile-kin { font-size: .74rem; color: var(--muted); }
.tile-kin a { color: var(--accent); text-decoration: none; }
.tile-kin a:hover { text-decoration: underline; }
#big-back[hidden] { display: none; }

/* Daily controls bar: only text + the colorblind switch live here, so center
   the row. The label's own align-self:end + bottom padding exist to line it
   up with free play's taller pickers — both must go here too, or they win
   over the container's centering. */
body[data-mode="daily"] .controls { align-items: center; }
body[data-mode="daily"] .controls label.check { align-self: center; padding-bottom: 0; }
.daily-info a { color: var(--accent); }

/* --- Colorblind toggle: style the checkbox as a switch (both pages) --- */
.controls label.check { cursor: pointer; }
.controls label.check input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 2.15rem;
  height: 1.2rem;
  margin: 0;
  flex-shrink: 0;
  border-radius: 999px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  position: relative;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.controls label.check input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 50%;
  left: .16rem;
  transform: translateY(-50%);
  width: .82rem;
  height: .82rem;
  border-radius: 50%;
  background: var(--muted);
  transition: left .15s, background .15s;
}
.controls label.check input[type="checkbox"]:checked {
  background: rgba(110, 168, 254, .28);
  border-color: var(--accent);
}
.controls label.check input[type="checkbox"]:checked::after {
  left: calc(100% - .98rem);
  background: var(--accent);
}
.controls label.check input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
