/* PuzzleFit styling, the same palette the other games use: a black page, the
   grid on a lighter grey rounded panel, one light pill button, and that app's
   die colours — sky, amber, orange-red, purple, green.

   The roles here are Unblock's: orange-red `--bad` for the red car, because it
   is the one piece that has to stand out from every other; sky `--player` for a
   car that slides sideways and amber `--op` for one that slides up and down, so
   which way a car goes is readable without touching it; purple `--accent` for
   the car under your finger or your cursor. Green stays off the board entirely,
   exactly as it does there. */
:root {
  --bg: #0a0a0a;
  --board-panel: #242424;      /* the tray the dice sit on */
  --card: #000000;             /* outlined cards */
  --outline: rgba(255, 255, 255, .92);
  --square: #2f2f2f;           /* an empty square */
  --grid: rgba(0, 0, 0, .35);  /* the hairline between two of them */
  --op: #efbc4a;
  --player: #5cc8f7;
  --tile: #4ed35e;
  --accent: #ab8dfa;
  --bad: #ff5722;
  --light: #e3e3e3;            /* the primary button */
  --primary-text: #0a0a0a;     /* ...and the text on it */
  --text: #ffffff;
  --muted: #9b9b9b;
}

/* A PGSDK host can report that it is running light; the die colours are the
   brand and stay put, everything around them inverts. Set by applyDarkMode(). */
body.light {
  --bg: #f1f1f4;
  --board-panel: #dededf;
  --card: #ffffff;
  --outline: rgba(0, 0, 0, .88);
  --square: #c9c9cf;
  --grid: rgba(0, 0, 0, .18);
  --light: #14141a;
  --primary-text: #f4f4f6;
  --text: #101014;
  --muted: #5c5c66;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;                       /* the game owns the viewport */
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif;
  -webkit-tap-highlight-color: transparent;
}

/* One screenful: the header takes what it needs, the board gets the rest. */
.app {
  max-width: 460px;
  height: 100vh;
  height: 100dvh;
  margin: 0 auto;
  padding: max(10px, env(safe-area-inset-top)) 12px calc(12px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;                        /* narrow phones drop the tools to a second line */
}

.tools {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin-left: auto;
}

[hidden] { display: none; }

select {
  background: var(--card);
  color: var(--text);
  border: 2px solid var(--outline);
  border-radius: 999px;
  padding: 8px 14px;
  font-size: 15px;
  font-weight: 700;
}

.clock {
  font-size: 20px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* The move count, which is the score here — the clock is only company. */
.moves {
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--primary-text);
  background: var(--light);
  border-radius: 999px;
  padding: 2px 10px;
}

/* The board is laid out at a fixed square size; the viewport transform below
   is what scales it to fit, so type never has to be recomputed. */
.viewport {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;                          /* let it shrink inside the column */
  overflow: hidden;
  border-radius: 26px;
  background: var(--board-panel);
  touch-action: none;
  overscroll-behavior: contain;
}

.viewport.panning { cursor: grabbing; }

.stage {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  will-change: transform;
}

.stage.animating { transition: transform .22s ease; }

/* No gap between squares: the cars are absolutely positioned over the grid, and
   one step of that geometry is exactly one square. The hairline is drawn inside
   the square instead, where it costs no width. */
.board {
  display: grid;
  grid-template-columns: repeat(var(--cols, 6), var(--cell));
  padding: var(--pad);
}

.cell {
  width: var(--cell);
  height: var(--cell);
  background: var(--square);
  box-shadow: inset 0 0 0 1px var(--grid);
}

/* The gap in the wall on the exit row: where the red car leaves. There is no
   square there — the board stops — so it is drawn over the padding instead. */
.gate {
  position: absolute;
  width: var(--pad);
  height: var(--cell);
  background: linear-gradient(90deg, transparent, var(--bad));
  opacity: .6;
}

/* The cars, over the grid. Positioned by game.js in the same units the board is
   laid out in, so one place decides the geometry. */
.cars {
  position: absolute;
  top: var(--pad);
  left: var(--pad);
  pointer-events: none;                   /* the viewport handles every gesture */
}

.car {
  position: absolute;
  border-radius: 12px;
  background: var(--player);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .35);
  transition: left .12s ease, top .12s ease;
}

/* Which way a car goes, without having to try it first. */
.car.down { background: var(--op); }

/* The red one. It is the only piece with somewhere to be, so it is the only
   piece that is not a traffic colour. */
.car.red {
  background: var(--bad);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, .45), 0 0 0 2px rgba(255, 87, 34, .35);
}

/* Under a finger, or under the keyboard's selection. */
.car.held {
  box-shadow: inset 0 0 0 3px var(--accent);
  transition: none;                       /* it follows the finger, not a clock */
  z-index: 2;
}

/* The nose, so a three is not just a longer two. */
.car::after {
  content: '';
  position: absolute;
  border-radius: 999px;
  background: rgba(0, 0, 0, .22);
}

.car.across::after { top: 22%; bottom: 22%; right: 12%; width: 8%; }
.car.down::after { left: 22%; right: 22%; bottom: 12%; height: 8%; }

/* The drive out, once the way is clear. The board is won the moment the red car
   reaches the wall; this is it taking the gap. */
.car.escaped {
  transition: left .45s ease-in, opacity .45s ease-in;
  opacity: 0;
}

.car.shake { animation: shake .3s; }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

.btn {
  background: var(--card);
  color: var(--text);
  border: 2px solid var(--outline);
  border-radius: 999px;
  padding: 16px 20px;
  font-size: 17px;
  font-weight: 700;
  cursor: pointer;
}

/* The header row: small enough that four of them cost the board a few pixels. */
.btn.mini {
  padding: 5px 9px;
  font-size: 12px;
  border-width: 1px;
}

.btn:active { transform: scale(.97); }
.btn.primary { background: var(--light); border-color: var(--light); color: var(--primary-text); }
.btn.hidden { display: none; }

.overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .72);
  display: grid;
  place-items: center;
  padding: 20px;
}

.overlay.hidden { display: none; }

.panel {
  background: var(--card);
  border-radius: 22px;
  border: 2px solid var(--outline);
  padding: 26px 22px;
  text-align: center;
  max-width: 320px;
  width: 100%;
}

.panel h2 { margin: 0 0 8px; font-size: 28px; font-weight: 800; }
.panel p { margin: 0 0 18px; color: var(--muted); font-size: 15px; line-height: 1.5; }
.panel .btn { width: 100%; }
.panel .btn + .btn { margin-top: 10px; }
