/*
 * Game-specific overrides for "puzles" (slide the wooden blocks out of the
 * way and get the red one through the opening). The shared look, the
 * hud/stage/pad grid and the background live in shared/shell.css - only the
 * board itself is defined here.
 *
 * The board is a friendly toy, not a wood-table recreation: a warm cream
 * playfield in a deep purple frame, rounded blocks with a raised edge, and
 * a chalk arrow under the gap in the bottom wall.
 */

:root {
  --puz-frame: #6f4a86;        /* the deep purple board edge */
  --puz-frame-dark: #553669;
  --puz-floor: #fbf2e2;        /* warm cream playfield */
  --puz-line: rgba(111, 74, 134, .11);
  --puz-red: #e5453f;          /* the target block */
  --puz-red-dark: #ab2b2c;
  --puz-blue: #4c8fc4;
  --puz-blue-dark: #35668f;
  --puz-yellow: #efb63f;
  --puz-yellow-dark: #b7822a;
  --puz-wall: 10px;            /* frame thickness; also the exit gap depth */
}

/* one-line "how it works" under the start-screen title */
.start-hint {
  margin: -6px 0 0;
  max-width: 34ch;
  font-size: clamp(15px, 3.6vw, 19px);
  line-height: 1.25;
  color: var(--purple-dark);
  opacity: .9;
}

/* ---- board sizing -----------------------------------------------------
 * .board-wrap takes whatever vertical room the stage has left over after
 * the feedback row, and the board is sized by its aspect ratio inside it:
 * a width, and `max-height: 100%` that `aspect-ratio` transfers BACK onto
 * the width when the viewport is short. So it shrinks to fit a landscape
 * phone as readily as a narrow portrait one, with no JS measuring.
 * (Do not give it `height: 100%` - a definite height beats aspect-ratio,
 * and the board comes out stretched.) */
/* The rocket rail lives inside .puz-board and is pinned just outside its
   right edge, so it follows the board however the board is sized. The
   stage reserves the gutter it needs. */
.stage-area { padding-right: 46px; }
.puz-board .rocket-track {
  left: 100%;
  right: auto;
  margin-left: 18px;
  top: 4%;
  bottom: 4%;
  width: 30px;
}

.board-wrap {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.puz-board {
  position: relative;
  aspect-ratio: var(--cols, 4) / var(--rows, 5);
  width: min(100%, calc(var(--cols, 4) * 90px));
  height: auto;
  max-height: 100%;
  background-color: var(--puz-floor);
  /* faint cell rules, one grid step wide/tall, so the snapping reads as
     deliberate rather than magnetic guesswork */
  background-image:
    linear-gradient(to right, var(--puz-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--puz-line) 1px, transparent 1px);
  background-size: calc(100% / var(--cols, 4)) calc(100% / var(--rows, 5));
  border-radius: 12px;
  /* the frame is a ring drawn outside the playfield, so the grid maths
     stays in clean percentages of the board itself */
  box-shadow:
    0 0 0 var(--puz-wall) var(--puz-frame),
    0 0 0 calc(var(--puz-wall) + 3px) rgba(85, 54, 105, .32),
    inset 0 2px 10px rgba(111, 74, 134, .16);
  /* the red block slides out through the bottom, past the board edge */
  overflow: visible;
  touch-action: none;
}

/* The opening: paints sky over the bottom wall across the exit columns, so
   the frame genuinely reads as having a hole in it. */
.puz-gap {
  position: absolute;
  left: calc(var(--exit-start, 1) / var(--cols, 4) * 100%);
  width: calc(var(--exit-w, 2) / var(--cols, 4) * 100%);
  top: 100%;
  height: calc(var(--puz-wall) + 5px);
  background: var(--sky);
  pointer-events: none;
}

/* chalk arrow under the opening - a hint of "this way out", no instruction.
   Positioned off the exit columns rather than the wrapper's centre, so it
   stays under the hole whatever the board's size or exit position. */
.puz-arrow {
  position: absolute;
  left: calc((var(--exit-start, 1) + var(--exit-w, 2) / 2) / var(--cols, 4) * 100%);
  top: calc(100% + var(--puz-wall) + 6px);
  transform: translateX(-50%);
  font-size: 30px;
  line-height: 1;
  color: #fff;
  opacity: .95;
  text-shadow: 0 2px 4px rgba(85, 54, 105, .35);
  animation: puzArrow 1.8s ease-in-out infinite;
  pointer-events: none;
}
@keyframes puzArrow {
  0%, 100% { transform: translate(-50%, 0); opacity: .6; }
  50%      { transform: translate(-50%, 6px); opacity: 1; }
}

.puz-pieces { position: absolute; inset: 0; }

/* the move counter sits between the score and the round in the shared HUD */
.hud-moves::before { content: "\21C4\00a0"; }

/* ---- a block -----------------------------------------------------------
 * Positioned in percentages of the board, so everything stays fluid. The
 * padding is the gutter between neighbours, which keeps the grid maths
 * exact (the face shrinks, the footprint doesn't). */
.piece {
  position: absolute;
  left: calc(var(--x) / var(--cols, 4) * 100%);
  top: calc(var(--y) / var(--rows, 5) * 100%);
  width: calc(var(--w) / var(--cols, 4) * 100%);
  height: calc(var(--h) / var(--rows, 5) * 100%);
  padding: 3px;
  border: none;
  background: none;
  font: inherit;
  cursor: grab;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  z-index: 1;
}
/* Only the leftover finger offset animates on release: game.js commits the
   new cell with the transition off and re-applies that residual as a
   transform, so this eases it back to zero (see the FLIP note there). */
.piece.settling { transition: transform .16s ease-out; }
.piece.dragging { cursor: grabbing; z-index: 5; }

.piece-face {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 11px;
  background: var(--face);
  box-shadow:
    inset 0 3px 0 rgba(255, 255, 255, .42),
    inset 0 -4px 0 rgba(0, 0, 0, .16),
    0 3px 0 var(--face-dark);
  transition: box-shadow .12s, filter .12s;
}
.piece.dragging .piece-face {
  filter: brightness(1.06);
  box-shadow:
    inset 0 3px 0 rgba(255, 255, 255, .42),
    inset 0 -4px 0 rgba(0, 0, 0, .16),
    0 9px 14px rgba(0, 0, 0, .32);
}

.piece-blue   { --face: var(--puz-blue);   --face-dark: var(--puz-blue-dark); }
.piece-yellow { --face: var(--puz-yellow); --face-dark: var(--puz-yellow-dark); }
.piece-red    { --face: var(--puz-red);    --face-dark: var(--puz-red-dark); z-index: 2; }
/* the target carries a white ring so it is unmistakable at a glance */
.piece-red .piece-face {
  box-shadow:
    inset 0 0 0 4px rgba(255, 255, 255, .5),
    inset 0 3px 0 rgba(255, 255, 255, .32),
    inset 0 -4px 0 rgba(0, 0, 0, .18),
    0 3px 0 var(--puz-red-dark);
}

/* the winning slide out through the opening */
.piece.escaping { transition: top .45s ease-in, transform .16s ease-out, opacity .3s .3s; opacity: 0; }

/* ---- Pista: ring the piece to move and point the way ---- */
.piece.is-hint .piece-face { animation: puzHint 1s ease-in-out 3; }
@keyframes puzHint {
  0%, 100% { box-shadow: inset 0 3px 0 rgba(255,255,255,.42), 0 3px 0 var(--face-dark), 0 0 0 0 rgba(255,255,255,.9); }
  50%      { box-shadow: inset 0 3px 0 rgba(255,255,255,.42), 0 3px 0 var(--face-dark), 0 0 0 7px rgba(255,255,255,.85); }
}
.piece .hint-arrow {
  position: absolute;
  left: 50%;
  top: 50%;
  font-size: clamp(20px, 5vw, 30px);
  line-height: 1;
  color: #fff;
  text-shadow: 0 2px 3px rgba(0, 0, 0, .35);
  pointer-events: none;
  animation: hintNudge .9s ease-in-out infinite;
}

/* ---- controls (pad area) ---- */
.puz-controls {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.puz-goal {
  flex-basis: 100%;
  margin: 0;
  text-align: center;
  font-size: 16px;
  color: var(--purple-dark);
  opacity: .85;
}
.puz-btn {
  font-family: inherit;
  font-size: 19px;
  color: #fff;
  border: none;
  border-radius: 999px;
  padding: 11px 26px;
  cursor: pointer;
  transition: transform .05s, filter .12s;
}
.puz-btn:active { transform: translateY(3px); }
.puz-btn[disabled] { filter: grayscale(.6); opacity: .6; cursor: default; }
.puz-btn-restart { background: var(--purple); box-shadow: 0 5px 0 var(--purple-dark); }
.puz-btn-restart:active { box-shadow: 0 2px 0 var(--purple-dark); }
.puz-btn-hint { background: var(--orange); box-shadow: 0 5px 0 #b06d17; }
.puz-btn-hint:active { box-shadow: 0 2px 0 #b06d17; }

/* landscape / wide: the controls column stacks under the goal line */
@media (min-width: 640px) and (orientation: landscape) {
  .puz-controls { flex-direction: column; }
  .puz-btn { width: min(210px, 100%); }
  .puz-goal { flex-basis: auto; }
}

/* short landscape phone: claw back vertical room around the board */
@media (max-height: 430px) {
  .feedback { min-height: 32px; }
  .puz-goal { font-size: 14px; }
  .puz-btn { font-size: 16px; padding: 8px 20px; }
}

@media (prefers-reduced-motion: reduce) {
  .puz-arrow, .piece .hint-arrow, .piece.is-hint .piece-face { animation: none !important; }
}

@keyframes hintNudge {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(-50%, -50%) scale(1.22); }
}
