/* ── Pivot ───────────────────────────────────────────────────────────────────
   Pinned pieces, turned back onto their board.

   The stage is ONE grid, an apron of a square all round the real board, because
   a scrambled piece hangs off the edge and the player has to see it hanging.
   Inside that grid two things are stacked:

     .pv-sq   the board's own squares, W×H, in row-major order — the deduce
              overlay addresses these by index, so nothing may be appended
              between them
     .pv-tile one per cell of a piece's CURRENT placement, laid over the top

   Errors are stroke counts, never colours (see tokens.css): a bare square is
   left bare, a piece off the board wears one stroke, a doubled square wears two.
   The four inks are then free to mean only "which piece".                      */

.flip-play .q-stage {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Everything is absolutely placed off one number (the square size), in three
   stacked layers: the board's squares, then the pieces, then the error marks.
   Nothing is in a CSS grid, and that is deliberate — a piece hanging off the
   board used to address a grid line before the first one, which grew implicit
   tracks in front of the board and shifted the whole thing sideways. */
.pv-stage {
  position: relative;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.pv-squares, .pv-over, .pv-pins {
  position: absolute;
  top: 0;
  left: 0;
}
.pv-over { pointer-events: none; }

/* The pins are the topmost thing on the board, in their own layer. Inside a
   piece each pin was confined to that piece's stacking context, so a neighbour
   drawn later simply covered it — and the pin is the one mark that must always
   be visible, because it is what the player aims at. */
.pv-pins {
  z-index: var(--z-chrome);
  pointer-events: none;
}

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

.pv-sq {
  position: absolute;
  box-sizing: border-box;
  background: var(--pv-paper);
  border: var(--hairline) solid var(--pv-line);
}

/* (the board's edge is drawn as .pv-frame-box, over the pieces — see below) */

/* ── the pieces ──────────────────────────────────────────────────────────── */

/* One element per piece, sitting exactly over its pinned square. A turn is a
   rotation of this element about its own centre — which IS the pin — so the
   quarter-turn animates, and animates about the right point. */
.pv-piece {
  position: absolute;
  transform-origin: 50% 50%;
  transition: transform var(--duration-3) var(--ease);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) { .pv-piece { transition: none; } }

.pv-tile {
  position: absolute;
  box-sizing: border-box;
  background: var(--pv-ink);
  transition: opacity var(--duration-1) var(--ease);
}
.t0 { --pv-ink: var(--pv-1); }
.t1 { --pv-ink: var(--pv-2); }
.t2 { --pv-ink: var(--pv-3); }
.t3 { --pv-ink: var(--pv-4); }

/* the piece's own outline, drawn only where it faces something that is not
   itself — so a piece reads as one object even against a piece of the same ink */
.pv-tile.et { border-top: 1.5px solid var(--pv-frame); }
.pv-tile.er { border-right: 1.5px solid var(--pv-frame); }
.pv-tile.eb { border-bottom: 1.5px solid var(--pv-frame); }
.pv-tile.el { border-left: 1.5px solid var(--pv-frame); }

/* The two errors, as strokes. One = this cell is off the board. Two = this
   square is carrying more than one piece. Neither borrows a hue.

   Both have to be drawn OVER the pieces. A doubled square is by definition
   hidden under two of them, and the board's own edge is the thing pieces cross
   — mark either one underneath and it is invisible exactly when it matters. */
/* A square outside the frame keeps its piece's full colour — it is the same
   piece, and fading it made a spilled piece read as a different, paler object
   than the one still on the board. What marks it is a hatch and one red stroke:
   the square is still that piece, it is simply not on the board. */
.pv-tile.off {
  background-image: repeating-linear-gradient(45deg,
    var(--pv-err) 0 2px, transparent 2px 6px);
  box-shadow: inset 0 0 0 1.5px var(--pv-err);
}

.pv-dbl {
  position: absolute;
  box-sizing: border-box;
  pointer-events: none;
  box-shadow:
    inset 0 0 0 1.5px var(--pv-err),
    inset 0 0 0 3.5px transparent,
    inset 0 0 0 5px var(--pv-err);
}

/* the board's own edge, over everything: the line nothing may cross */
.pv-frame-box {
  position: absolute;
  top: 0;
  left: 0;
  box-sizing: border-box;
  border: 2.5px solid var(--pv-frame);
  border-radius: 2px;
  pointer-events: none;
}

/* the piece the next tap will turn, when a square is contested */
.pv-piece.aim .pv-tile { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ── the pin, and the direction the piece is facing ──────────────────────── */

/* A pin is hardware: it reads as the thing the piece turns ABOUT, so it is drawn
   over the piece, centred, and never moves for the life of the board. */
.pv-pin {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: var(--z-panel);
  border-radius: var(--radius-full);
  background: var(--pv-paper);
  border: 1.5px solid var(--pv-pin);
  transform: translate(-50%, -50%);
  pointer-events: none;
}

/* the arm: which way this piece is currently facing. A piece that looks the
   same either way has no arm to show and gets a second ring instead — the board
   never implies one of two identical turns is the right one. */
.pv-arm {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: var(--z-panel);
  height: 1.5px;
  background: var(--pv-pin);
  transform-origin: 0 50%;
  pointer-events: none;
}
.pv-pin.sym::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: var(--radius-full);
  border: 1.5px solid var(--pv-pin);
}

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

/* Every piece keeps its own ink — the map you rebuilt is the reward, so nothing
   is drained to grey. Nothing is added either: the victory sheet is already on
   its way, and a travelling highlight underneath it read as noise. */
.pv-stage.pv-solved .pv-tile.aim { outline: none; }

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

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