/* ── Nonogram ───────────────────────────────────────────────────────────────
   A paper grid with clue gutters on the top and left. The play chrome
   (.q-chrome / .q-stage / .q-foot) is the shared shell from queens.css; below is
   Nonogram's own — the frame, the gutters, the cells, and the fill/cross marks.
   Sizing tokens (--no-cell, --no-cols, --no-rows, --no-lg, --no-tg) are set on
   .no-hold by the JS to fit the stage; everything is theme-aware via tokens.

   The grid belongs to the CELLS (see .no-cell), not to the board's background —
   a rule and the cell it divides must be the same object, or they drift. */

.nono-play { display: flex; flex-direction: column; height: 100%; min-height: 0; }
/* tight stage padding: at phone sizes every frame px is paid for in cell size,
   and the clue gutters already hold the board off the screen edge */
.nono-play .q-stage { padding: var(--space-2); overflow: auto; }
.no-hold { display: inline-block; }

/* ── the frame: [corner | column clues] over [row clues | board] ────────────
   The board's track has to carry its BORDER as well as its cells. It used to be
   `cols * cell`, but the board also wears a --no-edge-w frame on each side, so
   its inner box came out 2*--no-edge-w short of what the cells demanded and the
   last column and row were quietly clipped by 4px. */
.no-frame {
  display: grid;
  grid-template-columns: var(--no-lg) calc(var(--no-cols) * var(--no-cell) + 2 * var(--no-edge-w));
  grid-template-rows: var(--no-tg) calc(var(--no-rows) * var(--no-cell) + 2 * var(--no-edge-w));
}
.no-corner { grid-area: 1 / 1; }

/* Column clues, bottom-aligned. No pill behind them: on a ledger board the
   numbers sit naked on the page and the divider does all the work. The cost is
   real — a pill is a bigger tap target than a numeral — but nothing here is
   tappable, so it was only ever ink.

   Inset by the board's border, so a clue sits over its own column: the track is
   the board's OUTER width now, and the cells start one border in. */
.no-cols {
  grid-area: 1 / 2; display: grid;
  grid-template-columns: repeat(var(--no-cols), var(--no-cell));
  padding-inline: var(--no-edge-w);
  align-items: end;
}
.no-ch { height: 100%; display: flex; align-items: flex-end; justify-content: center; padding: 0 2px 3px; }
.no-cw {
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  gap: 1px; width: 100%; padding: 4px 0 4px; min-height: calc(var(--no-cell) * 0.9);
}

/* row clues, right-aligned — naked on the page like the columns, and inset by
   the board's border for the same reason */
.no-rows {
  grid-area: 2 / 1; display: grid;
  grid-template-rows: repeat(var(--no-rows), var(--no-cell));
  padding-block: var(--no-edge-w);
}
.no-rh { width: 100%; display: flex; align-items: center; justify-content: flex-end; padding: 3px 3px 3px 0; }
.no-rw {
  display: flex; align-items: center; justify-content: flex-end;
  gap: calc(var(--no-cell) * 0.14); height: 100%; padding: 0 5px 0 3px; min-width: calc(var(--no-cell) * 0.9);
}

/* clue numbers */
.no-cw i, .no-rw i {
  font-family: var(--font-mono); font-style: normal; font-weight: 700;
  font-size: calc(var(--no-cell) * 0.44); line-height: 1.05; color: var(--text);
}
/* a satisfied line's clue fades back */
.no-rh.done .no-rw, .no-ch.done .no-cw { opacity: 0.4; }

/* ── the board: just a frame. The grid is drawn by the cells ───────────────── */
.no-board {
  grid-area: 2 / 2;
  display: grid;
  grid-template-columns: repeat(var(--no-cols), var(--no-cell));
  grid-template-rows: repeat(var(--no-rows), var(--no-cell));
  /* The cells cover this completely — it only ever shows through a sub-pixel
     seam. So it is the RULE colour, not the paper: if the board lands on a
     fractional device pixel despite the snapping in sizeBoard(), what leaks
     through reads as a hairline rule rather than as a gap in the picture. */
  background-color: var(--no-block);
  border: var(--no-edge-w) solid var(--no-block);
  /* a ledger board: square. The divider is the only furniture, so a rounded
     card fights it — and a square corner is one less thing for a filled cell to
     escape. overflow stays: a fill must never paint past the frame. */
  border-radius: 0;
  overflow: hidden;
  touch-action: none; user-select: none; -webkit-user-select: none;
}

/* A cell is the paper AND its own two rules: one down its right side, one along
   its bottom. The last column/row carry none — the board's border is that edge.

   The rules are BARS, not borders. Two borders meeting on one box are joined
   with a diagonal MITRE, so where a 1px pale rule met the 2px divider it ate the
   divider's last pixel — nicking it once per cell until the whole line read as
   broken. Bars are plain rectangles: they overlap instead of mitring, and
   z-index decides which one owns the corner. */
.no-cell {
  box-sizing: border-box;
  width: var(--no-cell); height: var(--no-cell);
  padding: 0; margin: 0; border: 0;
  background: var(--no-paper);
  display: grid; place-items: center; cursor: pointer; position: relative;
  --no-rule-r: transparent; --no-rule-rw: 1px;
  --no-rule-b: transparent; --no-rule-bw: 1px;
}
.no-cell::before, .no-cell::after { content: ""; position: absolute; pointer-events: none; z-index: 1; }
.no-cell::before { top: 0; bottom: 0; right: 0; width: var(--no-rule-rw); background: var(--no-rule-r); }
.no-cell::after { left: 0; right: 0; bottom: 0; height: var(--no-rule-bw); background: var(--no-rule-b); }

.no-r { --no-rule-r: var(--no-grid); }
.no-b { --no-rule-b: var(--no-grid); }
/* every fifth: the heavy divider that makes a 15×15 countable at a glance. It
   OWNS every corner it passes through — it is the one line that has to read as
   unbroken, so it outranks the hairlines it crosses. */
.no-br { --no-rule-r: var(--no-block); --no-rule-rw: var(--no-edge-w); }
.no-bb { --no-rule-b: var(--no-block); --no-rule-bw: var(--no-edge-w); }
.no-br::before, .no-bb::after { z-index: 2; }

/* A filled cell is thread, edge to edge: its own hairlines go to ink so a run
   fuses into one unbroken mass rather than a row of tiles held apart by the
   weave. The picture is the payoff, and it only lands if the stitches touch.
   The every-fifth divider still cuts through — without it a 15×15 stops being
   countable, and counting is the other half of the game. */
.no-cell.on { background: var(--no-ink); --no-rule-r: var(--no-ink); --no-rule-b: var(--no-ink); }
.no-cell.on.no-br { --no-rule-r: var(--no-block); }
.no-cell.on.no-bb { --no-rule-b: var(--no-block); }
/* "definitely empty": half an ✕. It keeps the struck-out reading at half the
   ink, which matters because sizeBoard() floors the cell at 13px and a full ✕
   is mud at that size. Drawn rather than typed, so it needs no glyph from the
   font and can never be confused with mass the way a heavy ✕ can. */
.no-x { display: block; line-height: 0; pointer-events: none; }
.no-x::before {
  content: "";
  display: block;
  width: calc(var(--no-cell) * 0.62);
  height: max(1.5px, calc(var(--no-cell) * 0.085));
  border-radius: 2px;
  background: var(--no-block);
  transform: rotate(-45deg);
}

/* the finished picture: a soft settle on the filled cells */
.no-board.no-solved .no-cell.on { animation: no-settle var(--duration-3) var(--ease) both; }
@keyframes no-settle { from { transform: scale(0.72); opacity: 0.4; } to { transform: none; opacity: 1; } }

/* ── footer: the two brush chips (fill / cross), via play-options chips ─────
   The play screen's brush select is optionChips() in .no-pal — icon-only
   .ng-chip.po-chip squares carrying the swatches below. The armed chip goes
   accent, so its swatch flips to the on-accent ink to stay legible. */
.nono-foot { justify-content: center; gap: var(--space-5); }
.no-swatch { width: 16px; height: 16px; border-radius: 3px; display: grid; place-items: center; flex: none; font-size: 12px; line-height: 1; }
.no-sw-fill { background: var(--text); }
.no-sw-cross { color: var(--mute); box-shadow: inset 0 0 0 var(--hairline) var(--line); }
.no-pal .no-swatch, .po-ghost .no-swatch { width: 20px; height: 20px; font-size: 14px; }
.no-pal .po-chip.armed .no-sw-fill { background: var(--on-accent); }
.no-pal .po-chip.armed .no-sw-cross { color: var(--on-accent); box-shadow: inset 0 0 0 var(--hairline) var(--on-accent); }

/* the labelled Fill/Cross toggle — the TUTORIAL still builds this control
   (src/ui/tutorials/nonogram.js); the play screen no longer does */
.no-brush { display: inline-flex; border: var(--hairline) solid var(--line); border-radius: var(--radius); overflow: hidden; }
.no-bt {
  display: inline-flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-5); background: var(--surface); color: var(--mute);
  font-size: var(--text-sm); border: 0; cursor: pointer; transition: var(--t);
}
.no-bt + .no-bt { border-left: var(--hairline) solid var(--line); }
.no-bt.is-on { background: var(--accent-dim); color: var(--text); }

/* ── level-card thumbnail: the picture, sampled down, revealed once solved ── */
.no-mini {
  display: grid; gap: 1px;
  grid-template-columns: repeat(var(--mc), 1fr);
  grid-template-rows: repeat(var(--mr), 1fr);
  width: 44px; height: 44px; margin: 0 auto;
}
.no-mini i { border-radius: 1px; background: var(--line-2); opacity: 0.25; }
.no-mini.done i { opacity: 1; background: var(--line); }
.no-mini i.on { opacity: 1; background: var(--text); }

@media (prefers-reduced-motion: reduce) {
  .no-board.no-solved .no-cell.on { animation: none; }
}
