/* puzzles.css - Puzzles: a jigsaw puzzle. Reuses tokens from styles.css
   and game-shell.css's shell/bar/pause chrome, same as every other game.
   Portrait-first layout: the square board sits at the top sized to the
   screen width, a strip of free "table" space below it for arranging
   pieces, and the pieces wait in a horizontally scrollable tray at the
   bottom. Pieces are rectangular slices of the chosen image (CSS
   background-position), dragged with Pointer Events so mouse and touch
   share one path. */

.puzzles-stage {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 10px;
}

.puzzles-col {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
  gap: 8px;
}

.puzzles-stats {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex: 0 0 auto;
  flex-wrap: wrap;
}

@media (max-width: 480px) {
  .puzzles-stats {
    padding: 0 var(--gs-bar-right-clear) 0 var(--gs-bar-left-clear);
    gap: 9px;
  }
  /* Same real-bug precedent as Numbers'/Slither's/Rodents'/Stacks' own
     mobile stat-row fix -- Coins is the least essential stat mid-play,
     so it's the one dropped when the shell's own button clearance
     squeezes this row. */
  .puzzles-stats .puzzles-stat-compact-hide {
    display: none;
  }
}

.puzzles-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.1;
  min-width: 52px;
}

.puzzles-stat-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 600;
  color: var(--muted);
}

.puzzles-stat-value {
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

/* Thumb-reachable peek + new-puzzle buttons, in the stats row rather
   than buried in a menu. */
.puzzles-peek-btn,
.puzzles-new-btn {
  border: 1px solid var(--border);
  background: var(--bg, #161b22);
  color: var(--text);
  border-radius: 999px;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  padding: 9px 12px;
  cursor: pointer;
  touch-action: manipulation;
  white-space: nowrap;
}

.puzzles-peek-btn.is-open {
  background: var(--accent, #34d399);
  color: #0b0f14;
  border-color: transparent;
}

/* -- Canvas: board on top, free table space below it, both inside one
   relatively-positioned box so free pieces can sit anywhere in it. */

.puzzles-canvas-wrap {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  background: #1b2530;
  overflow: hidden;
  touch-action: none;
}

.puzzles-board {
  position: absolute;
  top: 0;
  left: 0;
  background-color: #10161d;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .18);
}

/* The ghost of the finished picture, faded well back behind the pieces
   so it is only a faint hint of where things belong -- it should not do
   the work for the player. */
.puzzles-board-ghost {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: .08;
  pointer-events: none;
}

/* -- Pieces: one canvas per piece, clipped to a real jigsaw shape
   (tabs and blanks) by puzzles.js. The canvas draws its own edge, so
   there is no CSS border or box-shadow here -- a rectangular shadow
   would be wrong on a shaped piece. */

.puzzles-piece {
  position: absolute;
  z-index: 3;
  display: block;
  background: transparent;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

.puzzles-piece.is-dragging {
  z-index: 9;
  cursor: grabbing;
  /* Slight lift while dragging so the piece reads as "picked up". */
  filter: brightness(1.12);
}

.puzzles-piece.is-locked {
  cursor: default;
  pointer-events: none;
  z-index: 2;
}

/* Brief flash when a tap joins pieces into a group. */
@keyframes puzzles-join-flash {
  0% { filter: brightness(1.7); }
  100% { filter: brightness(1); }
}
.puzzles-piece.just-joined {
  animation: puzzles-join-flash .45s ease-out;
}

/* -- Win celebration: when the puzzle is completed, the finished
   picture pops out and glows for 7 seconds before the high-score
   flow covers it. The wrap holds the board and all its pieces, so
   scaling it scales the finished picture as one unit (scaling the
   pieces individually would pull them apart). The pulsing glow hugs
   the BOARD square itself (the finished puzzle), not the outer
   canvas box: it is a box-shadow on the board, and the wrap's
   overflow is opened while celebrating so the glow is not clipped
   at the wrap's edges (the board spans the wrap's full width). */
@keyframes puzzles-win-pop {
  0% { transform: scale(1); }
  35% { transform: scale(1.06); }
  65% { transform: scale(1.03); }
  100% { transform: scale(1.03); }
}
@keyframes puzzles-win-glow {
  0%, 100% {
    box-shadow: inset 0 0 0 3px rgba(242, 177, 52, .9),
      inset 0 0 28px rgba(242, 177, 52, .35),
      0 0 28px 6px rgba(242, 177, 52, .55),
      0 0 72px 18px rgba(242, 177, 52, .28);
  }
  50% {
    box-shadow: inset 0 0 0 3px rgba(242, 177, 52, .9),
      inset 0 0 28px rgba(242, 177, 52, .35),
      0 0 46px 12px rgba(242, 177, 52, .85),
      0 0 110px 28px rgba(242, 177, 52, .45);
  }
}
.puzzles-canvas-wrap.is-celebrating {
  /* Hold the popped size once the pop animation finishes. */
  transform: scale(1.03);
  animation: puzzles-win-pop .6s ease-out;
  /* Let the board's glow show past the wrap's edges. */
  overflow: visible;
  z-index: 5;
}
/* The glow lives on the board square: a golden edge plus the pulsing
   outer halo, so the finished puzzle itself glows. */
.puzzles-canvas-wrap.is-celebrating .puzzles-board {
  box-shadow: inset 0 0 0 3px rgba(242, 177, 52, .9),
    inset 0 0 28px rgba(242, 177, 52, .35);
  animation: puzzles-win-glow 1.5s ease-in-out .6s infinite;
}

/* -- Peek overlay: covers the canvas area only, never the shell chrome
   or the tray -- the tray stays usable while it is open. */

.puzzles-peek {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: rgba(10, 13, 16, .88);
  padding: 12px;
}

.puzzles-peek[hidden] { display: none; }

.puzzles-peek-img {
  max-width: 100%;
  max-height: calc(100% - 34px);
  object-fit: contain;
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .6);
}

.puzzles-peek-note {
  color: var(--muted);
  font-size: 13px;
  text-align: center;
}

/* -- Overlays (start/game-over) -- same pattern as every other game. */

.puzzles-overlay {
  position: absolute;
  inset: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(10, 13, 16, .78);
  border-radius: var(--radius);
  overflow-y: auto;
}

.puzzles-overlay[hidden] { display: none; }

.puzzles-overlay-card {
  text-align: center;
  padding: 20px;
  width: 100%;
  max-width: 460px;
}

.puzzles-overlay-title {
  font-family: Georgia, serif;
  font-size: 26px;
  color: var(--text);
  margin-bottom: 8px;
}

.puzzles-overlay-text {
  color: var(--muted);
  font-size: 14px;
  margin: 0 0 16px;
}

.puzzles-picker-label {
  color: var(--text);
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 10px;
}

.puzzles-image-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
}

.puzzles-image-pick {
  padding: 0;
  border: 2px solid transparent;
  border-radius: 8px;
  background: none;
  cursor: pointer;
  overflow: hidden;
  line-height: 0;
}

.puzzles-image-pick img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
}

.puzzles-image-pick span {
  display: block;
  line-height: 1.2;
  font-size: 10px;
  color: var(--text);
  background: rgba(10, 13, 16, .85);
  padding: 3px 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.puzzles-image-pick:hover,
.puzzles-image-pick:focus-visible {
  border-color: var(--accent, #34d399);
  outline: none;
}

.puzzles-image-pick.is-fable img {
  outline: 2px solid rgba(192, 132, 252, .55);
  outline-offset: -2px;
}

.puzzles-size-row {
  display: flex;
  gap: 8px;
  justify-content: center;
}

.puzzles-size-btn {
  flex: 1 1 0;
  max-width: 96px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg, #161b22);
  color: var(--text);
  font-size: 18px;
  font-weight: 800;
  line-height: 1.25;
  padding: 12px 4px;
  cursor: pointer;
}

.puzzles-size-btn span {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
}

.puzzles-size-btn:hover,
.puzzles-size-btn:focus-visible {
  border-color: var(--accent, #34d399);
  outline: none;
}

.puzzles-back-btn {
  margin-top: 14px;
  border: none;
  background: none;
  color: var(--muted);
  font-size: 13px;
  cursor: pointer;
  text-decoration: underline;
}

/* -- Tray: a horizontally scrollable row of touch-sized pieces below
   the board. Tray pieces keep touch-action: pan-x so a horizontal
   swipe scrolls the tray instead of grabbing a piece; lifting a piece
   is an upward (vertical) drag, which pointer events still deliver. */

.puzzles-tray-wrap {
  flex: 0 0 auto;
}

.puzzles-tray-label {
  color: var(--muted);
  font-size: 12px;
  text-align: center;
  margin-bottom: 5px;
}

.puzzles-tray {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 6px 4px;
  min-height: 78px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, .03);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}

.puzzles-tray .puzzles-piece {
  position: relative;
  flex: 0 0 auto;
  left: auto !important;
  top: auto !important;
  touch-action: pan-x;
  z-index: 1;
}
