/* ── Pipes ────────────────────────────────────────────────────────────────
   The board is a schematic printed on paper — the same in either theme, like
   Queens. Pipes are outlined tubes: a dark casing with a paper fill, so each
   reads as a hollow channel with a rounded terminal at a dead end. Water fills
   the tube soft teal, sweeping out from the source as pipes connect. It borrows
   the shared puzzle chrome (q-chrome / q-stage / q-foot). Values from tokens.css. */

.pipes-play {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

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

.pi-board {
  --n: 6;
  display: grid;
  grid-template-columns: repeat(var(--n), 1fr);
  grid-template-rows: repeat(var(--n), 1fr);
  width: min(92vw, 66vh, 520px);
  aspect-ratio: 1;
  gap: 0;
  padding: var(--space-3);
  background: var(--pi-paper);
  outline: 2px solid var(--pi-frame);
  border-radius: var(--radius);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.pi-cell {
  position: relative;
  box-sizing: border-box;
  padding: 0;
  background: transparent;
  border: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* the rotating layer: only this turns, so the source hole stays centred */
.pi-rot {
  position: absolute;
  inset: 0;
  display: block;
  transform-origin: 50% 50%;
  transition: transform var(--duration-2) var(--ease);
  will-change: transform;
}
/* Arms are drawn 2 units PAST the cell edge (ARM_END in games/pipes/flow.js is
   -2 / 102) so neighbouring tiles overlap and no hairline can open up between
   them: the grid is `1fr` columns, so a cell is a fractional number of pixels
   (61.33 at 6×520) and two boxes that merely butt together antialias into a
   visible seam across every pipe.

   `overflow: hidden` used to clip that overhang away at exactly the box, which
   threw the overlap out and put the seams back. But plain `overflow: visible`
   is not the answer either: the arms are stroke-linecap:round, so a 31-wide
   casing ends in a cap reaching 15.5 further — with nothing clipping it, each
   tile paints a dark dome over its neighbour's water.

   So: let it overflow, and clip to exactly the overhang. inset(-2%) is the 2
   units the arms actually extend (2% of the 100-unit tile), which covers the
   seam and cuts the caps off. */
.pi-svg { display: block; width: 100%; height: 100%; overflow: visible; clip-path: inset(-2%); }

/* Three stacked layers hollow the tube. The dark casing … */
.pi-cline { stroke: var(--pi-ink); stroke-linecap: round; fill: none; }
.pi-cdisc { fill: var(--pi-ink); }
/* … a paper channel that is ALWAYS fully drawn, so an empty pipe is a clean
   hollow (never the dark casing showing through as "black") … */
.pi-fline { stroke: var(--pi-paper); stroke-linecap: round; fill: none; }
.pi-fdisc { fill: var(--pi-paper); }
/* … and the teal water on top, present only where water actually is. The flow
   animation draws THIS layer, leaving the paper hollow untouched. */
.pi-wline { stroke: none; stroke-linecap: round; fill: none; stroke-dasharray: 56; }
.pi-wdisc { fill: none; transform-box: fill-box; transform-origin: center; }
.pi-cell.watered .pi-wline { stroke: var(--pi-water); }
.pi-cell.watered .pi-wdisc { fill: var(--pi-water); }
/* a draining pipe keeps its water visible while it recedes; JS clears it after */
.pi-cell.pi-drain .pi-wline { stroke: var(--pi-water); }
.pi-cell.pi-drain .pi-wdisc { fill: var(--pi-water); }

/* the flow wave. It runs pipe by pipe from the source; within a pipe the water
   rises continuously (linear) — the inlet arm over the first half, the outlet
   arm(s) over the second, back-to-back so the front never stalls. Each arm's
   direction (--df → --dt) and delay are set inline per-arm from JS. */
@keyframes pi-arm { from { stroke-dashoffset: var(--df, 56); } to { stroke-dashoffset: var(--dt, 0); } }
@keyframes pi-wdisc-in  { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes pi-wdisc-out { from { transform: scale(1); } to { transform: scale(0); } }

.pi-cell.pi-flow .pi-wline,
.pi-cell.pi-drain .pi-wline { animation: pi-arm var(--pipe-half, 60ms) linear both; }
.pi-cell.pi-flow .pi-wdisc { animation: pi-wdisc-in var(--disc-dur, 40ms) linear both; }
.pi-cell.pi-drain .pi-wdisc { animation: pi-wdisc-out var(--disc-dur, 40ms) linear both; }

/* ── the source: a donut, drawn in the tile itself ───────────────────────────
   The hub grows into a ring with a hole punched through it (tileSVG in
   games/pipes/flow.js), so the water fills the RING and the hole stays dry.
   It used to be a DOM disc floating over the tile, which could only ever sit
   ON the water rather than be shaped by it. */
.pi-hole { fill: var(--pi-paper); stroke: var(--pi-ink); stroke-width: 3; }

/* The donut's water is an annulus: it STROKES where an ordinary hub fills. It
   still answers to .pi-wdisc because applyFlow() looks that up by name, which
   means the `.pi-cell.watered .pi-wdisc { fill }` rule above also lands on it —
   so these have to name both classes to outrank it and put the fill back to
   none. Fill it as well as stroke it and the hole silently plugs itself.
   The thumbnail shows water by tinting the FILL layer instead, so it wants no
   part of this. */
.pi-wring { stroke: none; }
.pi-cell.watered .pi-wdisc.pi-wring,
.pi-cell.pi-drain .pi-wdisc.pi-wring { fill: none; stroke: var(--pi-water); }

/* ── locked: a faint ink wash, and a hairline tick in the corner ─────────── */
.pi-cell.locked { cursor: default; }
.pi-cell.locked::after {
  content: "";
  position: absolute;
  inset: 8%;
  background: var(--pi-lock);
  border-radius: var(--radius-sm);
  pointer-events: none;
}

/* the hint pulse */
.pi-cell.hinted { animation: pi-hint 1.4s var(--ease) 2; z-index: 2; }
@keyframes pi-hint {
  0%, 100% { box-shadow: inset 0 0 0 0 var(--accent); }
  50% { box-shadow: inset 0 0 0 4px var(--accent-line); }
}

/* ── landscape phone: board left, controls to the sides ───────────────── */
@media (orientation: landscape) and (max-height: 700px) {
  .pipes-play .pi-board { width: min(88vh, 78vw); }
}

/* ── the thumbnail on a journey level card ────────────────────────────── */
.pi-mini {
  display: grid;
  grid-template-columns: repeat(var(--n), 1fr);
  aspect-ratio: 1;
  width: 100%;
  padding: var(--space-2);
  background: var(--pi-paper);
  outline: 1.5px solid var(--pi-frame);
  border-radius: var(--radius-sm);
}
.pi-mini i { display: block; }
/* a solved level's thumbnail shows the player's answer, watered */
.pi-mini.watered .pi-fline { stroke: var(--pi-water); }
.pi-mini.watered .pi-fdisc { fill: var(--pi-water); }
