/* ── Blocks ──────────────────────────────────────────────────────────────────
   A silhouette cut out of the bench and six painted blocks that fill it.

   The board is one element per SILHOUETTE cell, in the engine's own dense order,
   so `.bk-cell:nth-child(k)` is engine cell k. That is what lets the cat's
   teaching overlay (src/ui/deduce.js) address cells by index without this file
   or the play screen doing any mapping.

   A block does not draw itself. Its cells wear its ink, and the block's OUTLINE
   is drawn per-cell on whichever sides face a different block or open bench —
   so four cells of one ink read as one solid piece with no internal seams, and
   two blocks that happen to share an ink still show the join. Same trick LITS
   uses for its regions; corners mitre with no gaps because every cell carries
   all four of its own borders.

   IDENTITY IS THREE CHANNELS, not one. Shape is the first (the generator throws
   away any board that shows one fixed shape twice), texture is the second, ink
   is the third. Remove the colour entirely and the tray is still readable — which
   is the test this had to pass, since the letters that used to do this job are
   gone.                                                                        */

.blocks-play .q-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-7);
}

/* ── the board ───────────────────────────────────────────────────────────── */

.bk-board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(var(--bk-w), var(--bk-cs));
  grid-auto-rows: var(--bk-cs);
  touch-action: none;              /* the whole board is a drag surface */
}

/* An open cell of the silhouette: the bench, lightly ruled. Cells outside the
   silhouette are not rendered at all — the ragged edge IS the puzzle, so there
   must be nothing there to mistake for a place a block could go. */
.bk-cell {
  position: relative;
  box-sizing: border-box;
  background: var(--bk-paper);
  border: var(--hairline) solid var(--bk-grid);
  grid-column: calc(var(--c) + 1);
  grid-row: calc(var(--r) + 1);
}

/* the silhouette's own edge — the shape you are trying to fill */
.bk-cell.st { border-top-color: var(--bk-wall); }
.bk-cell.sr { border-right-color: var(--bk-wall); }
.bk-cell.sb { border-bottom-color: var(--bk-wall); }
.bk-cell.sl { border-left-color: var(--bk-wall); }

/* ── a laid block ────────────────────────────────────────────────────────── */

.bk-cell.on { background: var(--bk-ink); border-color: transparent; }

/* the block's outline, only where it meets something that is not itself */
.bk-cell.on.et { border-top: var(--hairline) solid var(--bk-seam); }
.bk-cell.on.er { border-right: var(--hairline) solid var(--bk-seam); }
.bk-cell.on.eb { border-bottom: var(--hairline) solid var(--bk-seam); }
.bk-cell.on.el { border-left: var(--hairline) solid var(--bk-seam); }

/* Six inks, and six textures that ride with them one-for-one. The texture is
   the redundant channel: it is what still separates two blocks for a player who
   cannot separate the hues, and it is why the ladder below never repeats a
   direction. `--bk-ink` is what a cell paints with; `--bk-tex` is the pattern
   laid over it, one flat overlay, no gradient shading. */
.b0 { --bk-ink: var(--bk-1); }
.b1 { --bk-ink: var(--bk-2); }
.b2 { --bk-ink: var(--bk-3); }
.b3 { --bk-ink: var(--bk-4); }
.b4 { --bk-ink: var(--bk-5); }
.b5 { --bk-ink: var(--bk-6); }

/* b0 stays plain — one block with no texture gives the eye a rest and a
   reference. The other five each take a direction of their own. */
.b1 .bk-tex { background-image: repeating-linear-gradient(45deg, var(--bk-tex) 0 2px, transparent 2px 6px); }
.b2 .bk-tex { background-image: repeating-linear-gradient(-45deg, var(--bk-tex) 0 2px, transparent 2px 6px); }
.b3 .bk-tex { background-image: repeating-linear-gradient(0deg, var(--bk-tex) 0 2px, transparent 2px 7px); }
.b4 .bk-tex { background-image: repeating-linear-gradient(90deg, var(--bk-tex) 0 2px, transparent 2px 7px); }
.b5 .bk-tex {
  background-image:
    repeating-linear-gradient(45deg, var(--bk-tex) 0 2px, transparent 2px 7px),
    repeating-linear-gradient(-45deg, var(--bk-tex) 0 2px, transparent 2px 7px);
}

/* The texture layer fills its square and nothing else. It is absolute, so every
   square that carries one MUST be positioned — a .bk-tex whose nearest
   positioned ancestor is the page paints the whole viewport, which is exactly
   what happened the first time this ran. Both hosts are pinned below. */
.bk-tex {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* ── the drag preview ────────────────────────────────────────────────────── */

/* Where the block would land, drawn on the BOARD rather than by moving the block
   there. The squares are RINGED, not filled: the block you are carrying is
   floating over them, and a solid fill underneath a solid block just reads as
   one muddy shape. A ring survives being covered — you can see the outline of
   the footprint around and between the block's own squares. The faint wash is
   there only to tie the ringed squares together as one footprint. */
/* Solid --accent and --red rather than the half-alpha --accent-line/--danger-line
   pair the rest of the app outlines with: this ring is drawn UNDER a block at
   0.85 opacity, so anything translucent is being read through two veils and
   disappears exactly where it is needed. */
.bk-cell.prev {
  box-shadow: inset 0 0 0 2.5px var(--accent);
  background: var(--bk-ghost);
}
.bk-cell.prev-bad {
  box-shadow: inset 0 0 0 2.5px var(--red);
  background: var(--bk-no);
}

/* The block riding the finger, drawn at BOARD scale — it is the size it will
   be, so there is no moment of surprise on release. It follows the pointer
   freely and never snaps to the grid; the ringed squares below say where it
   lands, and its own outline says whether it fits there. */
.bk-ghost {
  position: fixed;
  z-index: var(--z-ghost);
  pointer-events: none;
  /* see-through enough that the ringed footprint reads underneath it */
  opacity: 0.85;
  transition: opacity var(--duration-1) var(--ease);
}
.bk-ghost.no { opacity: 0.5; }
.bk-ghost.ok .bk-chip-in { outline: 2px solid var(--accent); outline-offset: 1px; }
.bk-ghost.no .bk-chip-in { outline: 2px solid var(--danger-line); outline-offset: 1px; }

/* ── the tray ────────────────────────────────────────────────────────────── */

/* `touch-action: none` is the whole reason drag works on a phone: without it the
   browser reads a press-and-move on a chip as a page scroll, takes the gesture,
   and cancels the pointer stream mid-drag. The shared palette sets this on
   `.ng-pal`, which this tray deliberately is not — so it has to say it itself.
   The same goes for the ghost, which is under the finger for the whole drag. */
.bk-tray {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  max-width: 100%;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.bk-tray .ng-chip, .bk-ghost, .bk-board {
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/* One chip per block, drawn as its own little grid of its own fixed shape —
   which is the shape it will land in, because blocks never turn.

   The chip BUTTON belongs to the shared palette (play-options.js gives it
   .ng-chip.po-chip and owns arming and dragging); everything below dresses that
   button for this game rather than replacing it, so a block chip arms, ghosts
   and drops exactly like a digit chip in KenKen. */
.bk-tray .ng-chip {
  position: relative;
  display: grid;
  padding: var(--space-3);
  min-width: 0;
  background: none;
  border: var(--hairline) solid transparent;
  border-radius: var(--radius);
  cursor: grab;
  transition: border-color var(--duration-1) var(--ease), opacity var(--duration-1) var(--ease);
}
/* No armed state: a block is dragged, never selected, so there is nothing for a
   selection ring to mean and nothing is ever chosen on the player's behalf. */
.bk-tray .ng-chip:hover { border-color: var(--line-2); }
.bk-tray .ng-chip.used { opacity: 0.18; pointer-events: none; }
/* the chip a finger has picked up: its place in the tray is held, but the block
   itself is now on the board, so the slot reads as empty rather than duplicated */
.bk-tray .ng-chip.lifting { opacity: 0.22; }

/* the shape inside a chip — and inside the drag ghost, which is the same markup */
.bk-chip-in { position: relative; }
.bk-chip-in i {
  position: relative;
  display: block;
  background: var(--bk-ink);
  grid-column: calc(var(--c) + 1);
  grid-row: calc(var(--r) + 1);
}

/* ── the cat's marks, and the hint flash ─────────────────────────────────── */

/* A revealed block is locked; the accent says so once, then stops shouting. */
.bk-cell.hinted { animation: bk-flash 1.4s var(--ease); }
@keyframes bk-flash {
  0%, 100% { box-shadow: inset 0 0 0 0 var(--accent); }
  30%      { box-shadow: inset 0 0 0 3px var(--accent); }
}
@media (prefers-reduced-motion: reduce) { .bk-cell.hinted { animation: none; } }

/* ── solved ──────────────────────────────────────────────────────────────── */

/* The finished silhouette keeps every block its own colour and does nothing
   else. The picture you built is the reward; the victory sheet is already
   arriving, and a second flourish underneath it was noise. */

/* ── the level-card / hub thumbnail ──────────────────────────────────────── */

.bk-mini {
  display: grid;
  grid-template-columns: repeat(var(--bk-w), 1fr);
  width: 100%;
  aspect-ratio: var(--bk-w) / var(--bk-h);
}
.bk-mini i {
  box-sizing: border-box;
  grid-column: calc(var(--c) + 1);
  grid-row: calc(var(--r) + 1);
  background: var(--bk-paper);
  border: 0.5px solid var(--bk-grid);
}
.bk-mini i.on { background: var(--bk-ink); border-color: var(--bk-seam); }
