{"version":3,"file":"index.umd.cjs","sources":["../src/registry.ts","../src/modal.ts","../src/render.ts","../src/games/pong.ts","../src/games/minesweeper.ts","../src/games/snake.ts","../src/index.ts"],"sourcesContent":["import type { Game } from './types';\n\n/** A game's stable key for registry / config lookups. */\nexport function gameId(game: Game): string {\n  return game.id ?? game.name;\n}\n\nexport class GameRegistry {\n  private games = new Map<string, Game>();\n\n  add(game: Game): boolean {\n    if (!game || typeof game.name !== 'string' || !game.name) {\n      console.warn('[arcade-shelf] game missing name:', game);\n      return false;\n    }\n    if (typeof game.init !== 'function') {\n      console.warn(`[arcade-shelf] game \"${game.name}\" missing init()`);\n      return false;\n    }\n    const key = gameId(game);\n    if (this.games.has(key)) {\n      console.warn(\n        `[arcade-shelf] duplicate game id \"${key}\" — registration ignored`,\n      );\n      return false;\n    }\n    this.games.set(key, game);\n    return true;\n  }\n\n  remove(id: string): boolean {\n    return this.games.delete(id);\n  }\n\n  get(id: string): Game | undefined {\n    return this.games.get(id);\n  }\n\n  list(): Game[] {\n    return Array.from(this.games.values());\n  }\n\n  clear(): void {\n    this.games.clear();\n  }\n}\n","import type { Game, GameHandle } from './types';\n\nconst DEFAULT_SIZE = { width: 380, height: 280 };\n\nconst FOCUSABLE_SELECTOR =\n  'a[href], area[href], button:not([disabled]), input:not([disabled]), ' +\n  'select:not([disabled]), textarea:not([disabled]), iframe, ' +\n  '[tabindex]:not([tabindex=\"-1\"])';\n\nexport interface OpenedModal {\n  close(): void;\n}\n\nfunction isFocusable(el: Element | null): el is HTMLElement {\n  return !!el && el instanceof HTMLElement && typeof el.focus === 'function' && el.tabIndex !== -1;\n}\n\nconst LOCK_COUNT_ATTR = 'arcadeShelfLockCount';\nconst LOCK_PREV_ATTR = 'arcadeShelfPrevOverflow';\n\n// Page-global ref-counted body scroll lock. Reading/writing through\n// `document.body.dataset` rather than a module-scoped counter so that two\n// independently-bundled copies of arcade-shelf on the same page (e.g. host\n// app + iframe-less plugin) still cooperate on a single lock.\nfunction acquireBodyScrollLock(): void {\n  const ds = document.body.dataset;\n  const count = parseInt(ds[LOCK_COUNT_ATTR] ?? '0', 10);\n  if (count === 0) {\n    ds[LOCK_PREV_ATTR] = document.body.style.overflow;\n    document.body.style.overflow = 'hidden';\n  }\n  ds[LOCK_COUNT_ATTR] = String(count + 1);\n}\n\nfunction releaseBodyScrollLock(): void {\n  const ds = document.body.dataset;\n  const count = parseInt(ds[LOCK_COUNT_ATTR] ?? '0', 10);\n  const next = count - 1;\n  if (next <= 0) {\n    document.body.style.overflow = ds[LOCK_PREV_ATTR] ?? '';\n    delete ds[LOCK_PREV_ATTR];\n    delete ds[LOCK_COUNT_ATTR];\n  } else {\n    ds[LOCK_COUNT_ATTR] = String(next);\n  }\n}\n\n/**\n * Open a modal containing a canvas, call game.init(canvas), and start it.\n * Returns a handle with close() that stops the game and removes the modal.\n */\nexport function openGameModal(game: Game, triggerElement?: HTMLElement | null): OpenedModal {\n  const size = game.canvasSize ?? DEFAULT_SIZE;\n  // document.activeElement defaults to <body> when nothing is focused; body.focus()\n  // is a no-op unless tabindex is set, so only keep activeElement if it's actually focusable.\n  const activeEl = document.activeElement;\n  const fallbackFocus = isFocusable(activeEl) && activeEl !== document.body ? activeEl : null;\n  const lastFocus = triggerElement ?? fallbackFocus;\n\n  const overlay = document.createElement('div');\n  overlay.className = 'arcade-shelf-modal-overlay';\n\n  const dialog = document.createElement('div');\n  dialog.className = 'arcade-shelf-modal';\n  dialog.setAttribute('role', 'dialog');\n  dialog.setAttribute('aria-modal', 'true');\n  dialog.setAttribute('aria-label', `Playing: ${game.name}`);\n\n  const header = document.createElement('div');\n  header.className = 'arcade-shelf-modal-header';\n\n  const title = document.createElement('span');\n  title.className = 'arcade-shelf-modal-title';\n  title.textContent = game.name;\n  header.appendChild(title);\n\n  const closeBtn = document.createElement('button');\n  closeBtn.className = 'arcade-shelf-modal-close';\n  closeBtn.type = 'button';\n  closeBtn.setAttribute('aria-label', 'Close');\n  closeBtn.textContent = '×';\n  header.appendChild(closeBtn);\n\n  const canvas = document.createElement('canvas');\n  canvas.className = 'arcade-shelf-canvas';\n  canvas.width = size.width;\n  canvas.height = size.height;\n\n  dialog.appendChild(header);\n  dialog.appendChild(canvas);\n\n  // Read once — `footer` may be a getter that constructs a fresh element per call.\n  const footerContent = game.footer;\n  if (footerContent) {\n    const footer = document.createElement('div');\n    footer.className = 'arcade-shelf-modal-footer';\n    if (typeof footerContent === 'string') {\n      footer.textContent = footerContent;\n    } else {\n      footer.appendChild(footerContent);\n    }\n    dialog.appendChild(footer);\n  }\n\n  overlay.appendChild(dialog);\n  document.body.appendChild(overlay);\n\n  // Lock background scroll while the modal is open. Uses a page-global\n  // ref-counter so concurrent modals (e.g. two shelves on the same page)\n  // don't clobber each other's saved overflow on close.\n  acquireBodyScrollLock();\n\n  let handle: GameHandle | null = null;\n  try {\n    handle = game.init(canvas);\n    handle.start();\n  } catch (e) {\n    console.error(`[arcade-shelf] game \"${game.name}\" init/start failed:`, e);\n  }\n\n  let closed = false;\n  function close(): void {\n    if (closed) return;\n    closed = true;\n\n    if (handle) {\n      try {\n        handle.stop();\n      } catch (e) {\n        console.warn(`[arcade-shelf] game \"${game.name}\" stop() threw:`, e);\n      }\n    }\n\n    overlay.removeEventListener('click', onOverlayClick);\n    closeBtn.removeEventListener('click', close);\n    document.removeEventListener('keydown', onKeyDown);\n    document.removeEventListener('visibilitychange', onVisibilityChange);\n    window.removeEventListener('resize', onResize);\n    overlay.remove();\n\n    releaseBodyScrollLock();\n\n    if (isFocusable(lastFocus)) {\n      lastFocus.focus();\n    }\n  }\n\n  function onOverlayClick(e: MouseEvent): void {\n    if (e.target === overlay) close();\n  }\n\n  // Forward tab visibility so games can suspend their RAF / timers. Hooks\n  // are opt-in: a game that doesn't implement them simply keeps running.\n  function onVisibilityChange(): void {\n    if (!handle) return;\n    try {\n      if (document.hidden) handle.pause?.();\n      else handle.resume?.();\n    } catch (e) {\n      console.warn(`[arcade-shelf] game \"${game.name}\" pause/resume threw:`, e);\n    }\n  }\n\n  // Forward window resize so games can re-cache layout-dependent state\n  // (e.g. getBoundingClientRect for input → game coord translation). The\n  // canvas pixel size is unchanged; we just signal that the *displayed*\n  // size may have shifted.\n  function onResize(): void {\n    if (!handle) return;\n    try {\n      handle.resize?.(canvas.width, canvas.height);\n    } catch (e) {\n      console.warn(`[arcade-shelf] game \"${game.name}\" resize threw:`, e);\n    }\n  }\n\n  // Focus trap: keep Tab / Shift+Tab cycling inside the dialog. Without this,\n  // keyboard users can tab back into the underlying page while a modal is open.\n  function onKeyDown(e: KeyboardEvent): void {\n    if (e.key === 'Escape') {\n      e.preventDefault();\n      close();\n      return;\n    }\n    if (e.key !== 'Tab') return;\n\n    const focusables = Array.from(\n      dialog.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n    ).filter((el) => !el.hasAttribute('disabled') && el.offsetParent !== null);\n\n    if (focusables.length === 0) {\n      // Nothing focusable inside — just trap on the dialog itself.\n      e.preventDefault();\n      return;\n    }\n\n    const first = focusables[0]!;\n    const last = focusables[focusables.length - 1]!;\n    const active = document.activeElement as HTMLElement | null;\n\n    if (e.shiftKey && (active === first || !dialog.contains(active))) {\n      e.preventDefault();\n      last.focus();\n    } else if (!e.shiftKey && (active === last || !dialog.contains(active))) {\n      e.preventDefault();\n      first.focus();\n    }\n  }\n\n  overlay.addEventListener('click', onOverlayClick);\n  closeBtn.addEventListener('click', close);\n  document.addEventListener('keydown', onKeyDown);\n  document.addEventListener('visibilitychange', onVisibilityChange);\n  window.addEventListener('resize', onResize);\n\n  // Autofocus close button so Esc/Enter work immediately.\n  closeBtn.focus();\n\n  return { close };\n}\n","import type { Game, ShelfOptions } from './types';\nimport { gameId } from './registry';\nimport { openGameModal, type OpenedModal } from './modal';\n\ninterface RenderDeps {\n  getGames(): Game[];\n  getGame(id: string): Game | undefined;\n  options: ShelfOptions;\n  /**\n   * Called by render whenever it opens a modal, so the owning shelf can\n   * close it on unmount. Returning undefined leaves the modal unmanaged.\n   */\n  onModalOpen?(modal: OpenedModal): void;\n}\n\ninterface RenderedShelf {\n  root: HTMLElement;\n  destroy(): void;\n}\n\nfunction resolveContainer(target: HTMLElement | string): HTMLElement | null {\n  if (typeof target === 'string') {\n    return document.querySelector<HTMLElement>(target);\n  }\n  return target ?? null;\n}\n\nfunction sortGames(games: Game[], options: ShelfOptions): Game[] {\n  const { whitelist, order } = options;\n\n  let list = games;\n  if (whitelist && whitelist.length > 0) {\n    const allow = new Set(whitelist);\n    list = list.filter((g) => allow.has(gameId(g)));\n  }\n\n  const orderIndex = new Map<string, number>();\n  if (order) {\n    order.forEach((id, i) => orderIndex.set(id, i));\n  }\n\n  return list.slice().sort((a, b) => {\n    const ai = orderIndex.get(gameId(a));\n    const bi = orderIndex.get(gameId(b));\n    if (ai !== undefined && bi !== undefined) return ai - bi;\n    if (ai !== undefined) return -1;\n    if (bi !== undefined) return 1;\n\n    const ao = a.order ?? Number.POSITIVE_INFINITY;\n    const bo = b.order ?? Number.POSITIVE_INFINITY;\n    if (ao !== bo) return ao - bo;\n    return a.name.localeCompare(b.name);\n  });\n}\n\nexport function renderShelf(deps: RenderDeps): RenderedShelf {\n  const { getGames, getGame, options, onModalOpen } = deps;\n  const container = resolveContainer(options.container);\n  if (!container) {\n    throw new Error('[arcade-shelf] container not found');\n  }\n\n  const card = document.createElement('div');\n  card.className = 'arcade-shelf-card';\n\n  const header = document.createElement('div');\n  header.className = 'arcade-shelf-card-header';\n\n  const title = document.createElement('span');\n  title.className = 'arcade-shelf-card-title';\n  title.textContent = options.title ?? \"Let's play!\";\n\n  header.appendChild(title);\n\n  const list = document.createElement('ul');\n  list.className = 'arcade-shelf-list';\n  list.setAttribute('role', 'list');\n\n  const games = sortGames(getGames(), options);\n  for (const game of games) {\n    const item = document.createElement('li');\n    item.className = 'arcade-shelf-list-item';\n\n    const btn = document.createElement('button');\n    btn.className = 'arcade-shelf-list-btn';\n    btn.type = 'button';\n    btn.dataset.gameId = gameId(game);\n    if (game.description) {\n      btn.title = game.description;\n      btn.setAttribute('aria-label', `${game.name} — ${game.description}`);\n    } else {\n      btn.setAttribute('aria-label', game.name);\n    }\n\n    if (game.icon) {\n      const ic = document.createElement('span');\n      ic.className = 'arcade-shelf-list-icon';\n      ic.textContent = game.icon;\n      ic.setAttribute('aria-hidden', 'true');\n      btn.appendChild(ic);\n    }\n\n    const label = document.createElement('span');\n    label.className = 'arcade-shelf-list-label';\n    label.textContent = game.name;\n    btn.appendChild(label);\n\n    item.appendChild(btn);\n    list.appendChild(item);\n  }\n\n  card.appendChild(header);\n  card.appendChild(list);\n  container.appendChild(card);\n\n  function onClick(e: MouseEvent): void {\n    const target = e.target as HTMLElement | null;\n    const btn = target?.closest<HTMLButtonElement>('.arcade-shelf-list-btn');\n    if (!btn) return;\n    const id = btn.dataset.gameId;\n    if (!id) return;\n    const game = getGame(id);\n    if (!game) return;\n    const modal = openGameModal(game, btn);\n    onModalOpen?.(modal);\n  }\n\n  list.addEventListener('click', onClick);\n\n  function destroy(): void {\n    list.removeEventListener('click', onClick);\n    card.remove();\n  }\n\n  return { root: card, destroy };\n}\n","import type { Game, GameHandle } from '../types';\n\n/*\n * Pong — classic two-paddle, ball bounces off paddles and walls.\n *\n * Velocity units: \"pixels per 60fps frame\". The step() function multiplies\n * motion by a deltaTime (dt) ratio so a 144Hz display doesn't run 2.4× faster\n * than a 60Hz one. Authors tune numbers against the 60fps baseline and dt\n * handles the rest.\n */\nexport const pong: Game = {\n  name: 'Pong',\n  icon: '🎾',\n  description: 'Classic two-paddle — track the ball, beat the AI.',\n  order: 1,\n  canvasSize: { width: 380, height: 280 },\n\n  init(canvas: HTMLCanvasElement): GameHandle {\n    const ctxMaybe = canvas.getContext('2d');\n    if (!ctxMaybe) throw new Error('[arcade-shelf/pong] 2D context unavailable');\n    // Rebind with a non-nullable type so nested closures below don't need `!` assertions.\n    const ctx: CanvasRenderingContext2D = ctxMaybe;\n\n    // Board geometry — W/H are the canvas's internal pixel size, NOT its CSS\n    // size. setPlayerY() below scales mouse coords from CSS space into this.\n    const W = canvas.width;\n    const H = canvas.height;\n    const PADDLE_W = 8;\n    const PADDLE_H = 50;\n    const BALL = 7;\n    const PLAYER_X = 12;\n    const AI_X = W - 12 - PADDLE_W;\n    // 60fps baseline: one \"frame\" at 60Hz is ~16.67ms. dt = elapsed / FRAME_MS.\n    const FRAME_MS = 1000 / 60;\n\n    // Mutable game state. Kept in closure so start/stop share it without a class.\n    let playerY = (H - PADDLE_H) / 2;\n    let aiY = (H - PADDLE_H) / 2;\n    let ballX = W / 2;\n    let ballY = H / 2;\n    let vx = 0;\n    let vy = 0;\n    let scoreP = 0;\n    let scoreA = 0;\n    let started = false; // has the player ever clicked to serve?\n    let running = false; // is the RAF loop live right now?\n    let raf: number | null = null;\n    let lastTs = 0; // timestamp of previous step(), for dt calc\n    let rect: DOMRect | null = null; // cached canvas bounds, for mouse→game coords\n\n    // getBoundingClientRect() is expensive on every mousemove, so cache it.\n    // Refreshed on start() and on resize (layout can shift the canvas).\n    function refreshRect(): void {\n      rect = canvas.getBoundingClientRect();\n    }\n\n    // Serve the ball toward `dir` (+1 = right / toward AI, -1 = left / toward player).\n    // Small random vertical component so consecutive serves aren't identical.\n    function resetBall(dir: number): void {\n      ballX = W / 2;\n      ballY = H / 2;\n      const angle = Math.random() * 0.6 - 0.3; // radians, ~±17°\n      const speed = 3.2;\n      vx = Math.cos(angle) * speed * dir;\n      vy = Math.sin(angle) * speed;\n    }\n\n    function draw(): void {\n      // Full repaint every frame — cheaper than partial invalidation for a board this size.\n      ctx.fillStyle = '#000';\n      ctx.fillRect(0, 0, W, H);\n\n      // Dashed center line.\n      ctx.strokeStyle = '#333';\n      ctx.setLineDash([5, 5]);\n      ctx.beginPath();\n      ctx.moveTo(W / 2, 0);\n      ctx.lineTo(W / 2, H);\n      ctx.stroke();\n      ctx.setLineDash([]); // reset so other strokes don't inherit it\n\n      ctx.fillStyle = '#fff';\n      ctx.font = 'bold 22px monospace';\n      ctx.textAlign = 'center';\n      ctx.fillText(String(scoreP), W / 2 - 28, 28);\n      ctx.fillText(String(scoreA), W / 2 + 28, 28);\n\n      ctx.fillRect(PLAYER_X, playerY, PADDLE_W, PADDLE_H);\n      ctx.fillRect(AI_X, aiY, PADDLE_W, PADDLE_H);\n      // Ball is drawn from its top-left, but ballX/ballY track its center.\n      ctx.fillRect(ballX - BALL / 2, ballY - BALL / 2, BALL, BALL);\n\n      if (!started) {\n        ctx.font = '12px sans-serif';\n        ctx.fillText('Click / tap to start', W / 2, H - 14);\n      }\n    }\n\n    function step(ts: number): void {\n      if (!running) return;\n\n      // dt is \"how many 60fps frames' worth of time has passed since last step\".\n      // First frame: lastTs=0, use dt=1 (one baseline frame) to avoid a huge jump.\n      // Clamp to 32ms (~2 frames) so a backgrounded tab returning after 5s\n      // doesn't teleport the ball through a paddle.\n      const dt = lastTs === 0 ? 1 : Math.min(32, ts - lastTs) / FRAME_MS;\n      lastTs = ts;\n\n      ballX += vx * dt;\n      ballY += vy * dt;\n\n      // Top/bottom wall bounce. Snap position back inside the wall before\n      // flipping vy — otherwise a fast ball could \"stick\" outside the bound.\n      if (ballY < BALL / 2) {\n        ballY = BALL / 2;\n        vy = -vy;\n      }\n      if (ballY > H - BALL / 2) {\n        ballY = H - BALL / 2;\n        vy = -vy;\n      }\n\n      // Player paddle collision. The `vx < 0` guard is critical: without it,\n      // once the ball overlaps the paddle, every subsequent frame re-flips vx\n      // and traps the ball inside (tunneling artifact).\n      if (\n        ballX - BALL / 2 < PLAYER_X + PADDLE_W &&\n        ballX > PLAYER_X &&\n        ballY > playerY &&\n        ballY < playerY + PADDLE_H &&\n        vx < 0\n      ) {\n        vx = -vx * 1.05; // 5% speedup per hit → rallies get harder\n        // Angle reflection: hitting the paddle's top/bottom edge sends the\n        // ball off at up to ±4 units/frame vertical; hitting dead center → 0.\n        // rel ∈ [-1, 1], so vy ∈ [-4, 4].\n        const rel = (ballY - (playerY + PADDLE_H / 2)) / (PADDLE_H / 2);\n        vy = rel * 4;\n      }\n\n      // AI paddle collision — mirror of the player check. `vx > 0` guard for\n      // the same tunneling reason.\n      if (\n        ballX + BALL / 2 > AI_X &&\n        ballX < AI_X + PADDLE_W &&\n        ballY > aiY &&\n        ballY < aiY + PADDLE_H &&\n        vx > 0\n      ) {\n        vx = -vx * 1.05;\n        const rel = (ballY - (aiY + PADDLE_H / 2)) / (PADDLE_H / 2);\n        vy = rel * 4;\n      }\n\n      // AI tracks the ball's y-position, but at a capped speed the player can\n      // outpace — otherwise the AI is unbeatable. Dead zone of 6px prevents\n      // jitter when the ball is directly in line with the paddle center.\n      const aiCenter = aiY + PADDLE_H / 2;\n      const diff = ballY - aiCenter;\n      const aiSpeed = 2.4;\n      if (Math.abs(diff) > 6) aiY += Math.sign(diff) * aiSpeed * dt;\n      // Clamp so the paddle can't leave the board.\n      aiY = Math.max(0, Math.min(H - PADDLE_H, aiY));\n\n      // Score + serve toward the loser (classic Pong rules).\n      if (ballX < 0) {\n        scoreA++;\n        resetBall(1);\n      }\n      if (ballX > W) {\n        scoreP++;\n        resetBall(-1);\n      }\n\n      draw();\n      // Re-queue ourselves. RAF is not recursive in the stack-eating sense —\n      // each call schedules the next ~16ms later; no stack frame is retained.\n      raf = requestAnimationFrame(step);\n    }\n\n    // Translate a viewport Y (mouse/touch clientY) into the canvas's internal\n    // pixel space. Canvas CSS height may differ from canvas.height (e.g.\n    // responsive layout), so scale by H/rect.height.\n    function setPlayerY(clientY: number): void {\n      if (!rect) refreshRect();\n      if (!rect) return;\n      const y = (clientY - rect.top) * (H / rect.height);\n      // Center the paddle on the cursor, then clamp inside the board.\n      playerY = Math.max(0, Math.min(H - PADDLE_H, y - PADDLE_H / 2));\n    }\n\n    function onMouseMove(e: MouseEvent): void {\n      setPlayerY(e.clientY);\n    }\n    function onTouchMove(e: TouchEvent): void {\n      const t = e.touches[0];\n      if (t) setPlayerY(t.clientY);\n    }\n    // First tap serves the ball; subsequent taps while running are no-ops.\n    // preventDefault stops the browser from treating a canvas tap as a\n    // scroll/zoom gesture on mobile.\n    function onStart(e: Event): void {\n      e.preventDefault();\n      if (!started) {\n        started = true;\n        resetBall(Math.random() > 0.5 ? 1 : -1);\n      }\n      if (!running) {\n        running = true;\n        lastTs = 0; // force the dt=1 first-frame path\n        raf = requestAnimationFrame(step);\n      }\n    }\n\n    return {\n      start(): void {\n        refreshRect();\n        canvas.addEventListener('mousemove', onMouseMove);\n        // passive:true lets the browser scroll without waiting on our handler,\n        // which is the right call here since we never preventDefault on move.\n        canvas.addEventListener('touchmove', onTouchMove, { passive: true });\n        canvas.addEventListener('click', onStart);\n        canvas.addEventListener('touchstart', onStart);\n        draw(); // paint the initial \"click to start\" frame\n      },\n      stop(): void {\n        // Order matters: flip `running` first so an in-flight step() bails\n        // instead of queuing another RAF after we cancel the current one.\n        running = false;\n        if (raf !== null) cancelAnimationFrame(raf);\n        raf = null;\n        canvas.removeEventListener('mousemove', onMouseMove);\n        canvas.removeEventListener('touchmove', onTouchMove);\n        canvas.removeEventListener('click', onStart);\n        canvas.removeEventListener('touchstart', onStart);\n      },\n      // Suspend the RAF loop when the tab is hidden. Without this, a\n      // backgrounded game would still try to step, then return with the\n      // dt clamp kicking in and a visible jump.\n      pause(): void {\n        if (!running) return;\n        running = false;\n        if (raf !== null) cancelAnimationFrame(raf);\n        raf = null;\n      },\n      resume(): void {\n        // Only resume if the player has actually served — pre-serve, we sit\n        // on the \"click to start\" frame and don't need RAF.\n        if (running || !started) return;\n        running = true;\n        lastTs = 0;\n        raf = requestAnimationFrame(step);\n      },\n      // Modal forwards window resize here so we re-cache the bounding rect.\n      // Args unused: canvas pixel dims don't change, only its CSS size.\n      resize(): void {\n        refreshRect();\n      },\n    };\n  },\n};\n","import type { Game, GameHandle } from '../types';\n\n/*\n * Minesweeper — left-click to reveal, right-click (or long-press on touch) to flag.\n *\n * Ported from a Java/Swing implementation (https://github.com/shixuan/minesweeper). \n * Preserved from the original: cell state model, three difficulty presets, mine\n * placement via random-retry, right-click flag with minesLeft counter, win = all\n * non-mine cells revealed.\n *\n * Notable additions over the original:\n *   - First-click safety: mines are placed AFTER the first reveal, excluding\n *     the clicked cell and its 8 neighbours. Original could lose on move 1.\n *   - Flood fill uses a BFS queue instead of recursion. Java's recursive\n *     MSGui.showBlank could stack-overflow on large blank regions.\n *   - Canvas 2D rendering with classic Win95 raised/sunken borders, LED\n *     counter, smiley face, difficulty bar.\n *   - Touch support: 450ms long-press triggers flag (original was mouse-only).\n */\n\ninterface Cell {\n  isMine: boolean;\n  revealed: boolean;\n  flagged: boolean;\n  adjacent: number;\n}\n\ninterface Difficulty {\n  label: string;\n  cols: number;\n  rows: number;\n  mines: number;\n}\n\ntype GameState = 'idle' | 'playing' | 'won' | 'lost';\n\nexport const minesweeper: Game = {\n  name: 'Minesweeper',\n  icon: '💣',\n  description:\n    'Left-click to reveal, right-click to flag. First click is always safe.',\n  order: 2,\n  canvasSize: { width: 380, height: 420 },\n\n  // Attribution footer. Built lazily so that importing this module in a\n  // non-DOM environment (SSR, tests) doesn't blow up on `document`.\n  get footer(): HTMLElement | undefined {\n    if (typeof document === 'undefined') return undefined;\n    const a = document.createElement('a');\n    a.href = 'https://github.com/shixuan/minesweeper';\n    a.textContent = 'Ported from my Java version →';\n    a.target = '_blank';\n    a.rel = 'noopener';\n    return a;\n  },\n\n  init(canvas: HTMLCanvasElement): GameHandle {\n    const ctxMaybe = canvas.getContext('2d');\n    if (!ctxMaybe) throw new Error('[arcade-shelf/minesweeper] 2D context unavailable');\n    // Rebind non-null so closures below don't need `!` assertions.\n    const ctx: CanvasRenderingContext2D = ctxMaybe;\n\n    const W = canvas.width;\n    const H = canvas.height;\n\n    const TOOLBAR_H = 50;\n    const DIFF_H = 32;\n    const MARGIN = 10;\n    const GRID_W = W - MARGIN * 2;\n    const GRID_H = H - TOOLBAR_H - DIFF_H;\n\n    const DIFFS: Difficulty[] = [\n      { label: 'Easy', cols: 9, rows: 9, mines: 10 },\n      { label: 'Normal', cols: 12, rows: 12, mines: 20 },\n      { label: 'Hard', cols: 16, rows: 16, mines: 30 },\n    ];\n\n    // Classic minesweeper number colours (index 0 unused, matches \"adjacent\" count).\n    const NUM_COLORS: readonly string[] = [\n      '',\n      '#1565C0',\n      '#2E7D32',\n      '#C62828',\n      '#4527A0',\n      '#6D4C41',\n      '#00838F',\n      '#000000',\n      '#546E7A',\n    ];\n\n    let diffIdx = 0;\n    let grid: Cell[][] = [];\n    let cellSize = 0;\n    let offX = 0;\n    let offY = 0;\n    let minesLeft = 0;\n    let gameState: GameState = 'idle';\n    let timer = 0;\n    let timerInterval: number | null = null;\n    let firstClick = true;\n    let longPressTimer: number | null = null;\n    let longPressTriggered = false;\n\n    // diffIdx is maintained in [0, DIFFS.length) by all setters, so this is always defined.\n    function currentDiff(): Difficulty {\n      return DIFFS[diffIdx] as Difficulty;\n    }\n\n    // ── Game logic ────────────────────────────────────────────\n\n    function initGame(): void {\n      const { cols, rows, mines } = currentDiff();\n      if (timerInterval !== null) clearInterval(timerInterval);\n      timerInterval = null;\n      timer = 0;\n      minesLeft = mines;\n      firstClick = true;\n      gameState = 'idle';\n\n      grid = Array.from({ length: rows }, () =>\n        Array.from(\n          { length: cols },\n          (): Cell => ({ isMine: false, revealed: false, flagged: false, adjacent: 0 }),\n        ),\n      );\n\n      cellSize = Math.floor(Math.min(GRID_W / cols, GRID_H / rows));\n      offX = MARGIN + Math.floor((GRID_W - cellSize * cols) / 2);\n      offY = TOOLBAR_H + DIFF_H + Math.floor((GRID_H - cellSize * rows) / 2);\n\n      draw();\n    }\n\n    function cellAtRC(r: number, c: number): Cell {\n      // Callers already bounds-check r/c against the current difficulty's rows/cols.\n      return grid[r]![c]!;\n    }\n\n    function placeMines(safeR: number, safeC: number): void {\n      const { cols, rows, mines } = currentDiff();\n      let placed = 0;\n      while (placed < mines) {\n        const r = Math.floor(Math.random() * rows);\n        const c = Math.floor(Math.random() * cols);\n        const cell = cellAtRC(r, c);\n        // Exclude the first-click cell AND its 8 neighbours so move 1 is always safe\n        // and usually opens a reasonable flood.\n        if (\n          !cell.isMine &&\n          !(Math.abs(r - safeR) <= 1 && Math.abs(c - safeC) <= 1)\n        ) {\n          cell.isMine = true;\n          placed++;\n        }\n      }\n      for (let r = 0; r < rows; r++) {\n        for (let c = 0; c < cols; c++) {\n          const cell = cellAtRC(r, c);\n          if (cell.isMine) continue;\n          let n = 0;\n          for (let dr = -1; dr <= 1; dr++) {\n            for (let dc = -1; dc <= 1; dc++) {\n              const nr = r + dr;\n              const nc = c + dc;\n              if (\n                nr >= 0 &&\n                nr < rows &&\n                nc >= 0 &&\n                nc < cols &&\n                cellAtRC(nr, nc).isMine\n              ) {\n                n++;\n              }\n            }\n          }\n          cell.adjacent = n;\n        }\n      }\n    }\n\n    function revealBFS(startR: number, startC: number): void {\n      const { cols, rows } = currentDiff();\n      const queue: Array<[number, number]> = [[startR, startC]];\n      while (queue.length) {\n        const next = queue.shift()!;\n        const [r, c] = next;\n        const cell = cellAtRC(r, c);\n        if (cell.revealed || cell.flagged) continue;\n        cell.revealed = true;\n        if (cell.adjacent === 0) {\n          for (let dr = -1; dr <= 1; dr++) {\n            for (let dc = -1; dc <= 1; dc++) {\n              const nr = r + dr;\n              const nc = c + dc;\n              if (\n                nr >= 0 &&\n                nr < rows &&\n                nc >= 0 &&\n                nc < cols &&\n                !cellAtRC(nr, nc).revealed\n              ) {\n                queue.push([nr, nc]);\n              }\n            }\n          }\n        }\n      }\n    }\n\n    function checkWin(): boolean {\n      const { cols, rows } = currentDiff();\n      for (let r = 0; r < rows; r++) {\n        for (let c = 0; c < cols; c++) {\n          const cell = cellAtRC(r, c);\n          if (!cell.isMine && !cell.revealed) return false;\n        }\n      }\n      return true;\n    }\n\n    function revealMines(): void {\n      const { cols, rows } = currentDiff();\n      for (let r = 0; r < rows; r++) {\n        for (let c = 0; c < cols; c++) {\n          const cell = cellAtRC(r, c);\n          if (cell.isMine) cell.revealed = true;\n        }\n      }\n    }\n\n    // ── Drawing ───────────────────────────────────────────────\n\n    function draw(): void {\n      ctx.clearRect(0, 0, W, H);\n      ctx.fillStyle = '#c0c0c0';\n      ctx.fillRect(0, 0, W, H);\n      drawToolbar();\n      drawDiffBar();\n      drawGrid();\n    }\n\n    function drawToolbar(): void {\n      ctx.fillStyle = '#c0c0c0';\n      ctx.fillRect(0, 0, W, TOOLBAR_H);\n      raised3D(0, 0, W, TOOLBAR_H, 3, false);\n\n      // Mines counter (floor at -99 so the 3-digit LED never overflows).\n      drawLED(MARGIN + 4, 10, Math.max(-99, minesLeft));\n      // Elapsed seconds (cap at 999 to fit 3 digits).\n      drawLED(W - MARGIN - 4 - 40, 10, Math.min(999, timer));\n\n      const sx = W / 2;\n      const sy = TOOLBAR_H / 2;\n      const sr = 13;\n      ctx.beginPath();\n      ctx.arc(sx, sy, sr, 0, Math.PI * 2);\n      ctx.fillStyle = '#FFD700';\n      ctx.fill();\n      ctx.strokeStyle = '#999';\n      ctx.lineWidth = 1;\n      ctx.stroke();\n\n      ctx.fillStyle = '#222';\n      ctx.lineWidth = 1.5;\n      ctx.strokeStyle = '#222';\n\n      if (gameState === 'won') {\n        // Shades + big smile.\n        ctx.fillRect(sx - 9, sy - 5, 7, 5);\n        ctx.fillRect(sx + 2, sy - 5, 7, 5);\n        ctx.fillRect(sx - 9, sy - 5, 18, 2);\n        ctx.beginPath();\n        ctx.arc(sx, sy + 2, 6, 0.1, Math.PI - 0.1);\n        ctx.stroke();\n      } else if (gameState === 'lost') {\n        // X eyes + frown.\n        ctx.font = 'bold 7px sans-serif';\n        ctx.textAlign = 'center';\n        ctx.textBaseline = 'middle';\n        ctx.fillText('×', sx - 4, sy - 3);\n        ctx.fillText('×', sx + 4, sy - 3);\n        ctx.textBaseline = 'alphabetic';\n        ctx.beginPath();\n        ctx.arc(sx, sy + 8, 4, Math.PI, Math.PI * 2);\n        ctx.stroke();\n      } else {\n        // Dot eyes + smile.\n        ctx.beginPath();\n        ctx.arc(sx - 4, sy - 3, 1.5, 0, Math.PI * 2);\n        ctx.fill();\n        ctx.beginPath();\n        ctx.arc(sx + 4, sy - 3, 1.5, 0, Math.PI * 2);\n        ctx.fill();\n        ctx.beginPath();\n        ctx.arc(sx, sy + 2, 5, 0.1, Math.PI - 0.1);\n        ctx.stroke();\n      }\n    }\n\n    function drawLED(x: number, y: number, value: number): void {\n      const text = String(Math.abs(value)).padStart(3, '0');\n      const prefix = value < 0 ? '-' : '';\n      ctx.fillStyle = '#200';\n      ctx.fillRect(x, y, 40, 22);\n      raised3D(x, y, 40, 22, 1, true); // sunken\n      ctx.fillStyle = '#f00';\n      ctx.font = \"bold 17px 'Courier New', monospace\";\n      ctx.textAlign = 'left';\n      ctx.textBaseline = 'top';\n      ctx.fillText(prefix + text, x + 3, y + 3);\n      ctx.textBaseline = 'alphabetic';\n    }\n\n    function drawDiffBar(): void {\n      const btnW = Math.floor(GRID_W / DIFFS.length);\n      DIFFS.forEach((d, i) => {\n        const x = MARGIN + i * btnW;\n        const y = TOOLBAR_H + 4;\n        const bw = i === DIFFS.length - 1 ? GRID_W - i * btnW : btnW;\n        const bh = DIFF_H - 8;\n        const active = i === diffIdx;\n\n        ctx.fillStyle = active ? '#1976D2' : '#e0e0e0';\n        ctx.fillRect(x + 2, y, bw - 4, bh);\n        raised3D(x + 2, y, bw - 4, bh, 2, active);\n\n        ctx.fillStyle = active ? '#fff' : '#333';\n        ctx.font = 'bold 11px sans-serif';\n        ctx.textAlign = 'center';\n        ctx.textBaseline = 'middle';\n        ctx.fillText(d.label, x + bw / 2, y + bh / 2);\n        ctx.textBaseline = 'alphabetic';\n      });\n    }\n\n    function drawGrid(): void {\n      if (grid.length === 0) return;\n      const { cols, rows } = currentDiff();\n      for (let r = 0; r < rows; r++) {\n        for (let c = 0; c < cols; c++) {\n          drawCell(r, c);\n        }\n      }\n    }\n\n    function drawCell(r: number, c: number): void {\n      const x = offX + c * cellSize;\n      const y = offY + r * cellSize;\n      const s = cellSize;\n      const cell = cellAtRC(r, c);\n\n      if (cell.revealed) {\n        ctx.fillStyle = cell.isMine ? '#ff5252' : '#bdbdbd';\n        ctx.fillRect(x, y, s, s);\n        ctx.strokeStyle = '#999';\n        ctx.lineWidth = 0.5;\n        ctx.strokeRect(x + 0.5, y + 0.5, s - 1, s - 1);\n\n        if (cell.isMine) {\n          drawMineIcon(x + s / 2, y + s / 2, s * 0.3);\n        } else if (cell.adjacent > 0) {\n          ctx.fillStyle = NUM_COLORS[cell.adjacent] ?? '#000';\n          ctx.font = `bold ${Math.max(8, Math.floor(s * 0.55))}px sans-serif`;\n          ctx.textAlign = 'center';\n          ctx.textBaseline = 'middle';\n          ctx.fillText(String(cell.adjacent), x + s / 2, y + s / 2 + 1);\n          ctx.textBaseline = 'alphabetic';\n        }\n      } else {\n        ctx.fillStyle = '#c0c0c0';\n        ctx.fillRect(x, y, s, s);\n        raised3D(x, y, s, s, Math.max(1, Math.floor(s * 0.1)), false);\n        if (cell.flagged) drawFlagIcon(x + s / 2, y + s / 2, s * 0.3);\n      }\n    }\n\n    function raised3D(\n      x: number,\n      y: number,\n      w: number,\n      h: number,\n      t: number,\n      sunken: boolean,\n    ): void {\n      const light = sunken ? '#808080' : '#ffffff';\n      const dark = sunken ? '#ffffff' : '#808080';\n      ctx.fillStyle = light;\n      ctx.fillRect(x, y, w, t);\n      ctx.fillRect(x, y, t, h);\n      ctx.fillStyle = dark;\n      ctx.fillRect(x, y + h - t, w, t);\n      ctx.fillRect(x + w - t, y, t, h);\n    }\n\n    function drawMineIcon(cx: number, cy: number, r: number): void {\n      ctx.fillStyle = '#111';\n      ctx.beginPath();\n      ctx.arc(cx, cy, r, 0, Math.PI * 2);\n      ctx.fill();\n      ctx.strokeStyle = '#111';\n      ctx.lineWidth = Math.max(1, r * 0.3);\n      for (let i = 0; i < 8; i++) {\n        const a = (i / 8) * Math.PI * 2;\n        ctx.beginPath();\n        ctx.moveTo(cx + Math.cos(a) * r * 0.8, cy + Math.sin(a) * r * 0.8);\n        ctx.lineTo(cx + Math.cos(a) * r * 1.6, cy + Math.sin(a) * r * 1.6);\n        ctx.stroke();\n      }\n      ctx.fillStyle = 'rgba(255,255,255,0.55)';\n      ctx.beginPath();\n      ctx.arc(cx - r * 0.3, cy - r * 0.3, r * 0.28, 0, Math.PI * 2);\n      ctx.fill();\n    }\n\n    function drawFlagIcon(cx: number, cy: number, r: number): void {\n      ctx.strokeStyle = '#111';\n      ctx.lineWidth = Math.max(1, r * 0.25);\n      ctx.beginPath();\n      ctx.moveTo(cx, cy + r);\n      ctx.lineTo(cx, cy - r);\n      ctx.stroke();\n      ctx.fillStyle = '#e53935';\n      ctx.beginPath();\n      ctx.moveTo(cx, cy - r);\n      ctx.lineTo(cx + r * 1.1, cy - r * 0.35);\n      ctx.lineTo(cx, cy + r * 0.1);\n      ctx.closePath();\n      ctx.fill();\n      ctx.fillStyle = '#111';\n      ctx.fillRect(\n        cx - r * 0.7,\n        cy + r - Math.max(1, r * 0.25),\n        r * 1.4,\n        Math.max(1, r * 0.25),\n      );\n    }\n\n    // ── Hit testing ───────────────────────────────────────────\n\n    function canvasXY(clientX: number, clientY: number): { x: number; y: number } {\n      // Always re-query: modal CSS transitions can shift the canvas after\n      // start() runs, so a cached rect would be stale.\n      const rect = canvas.getBoundingClientRect();\n      return {\n        x: (clientX - rect.left) * (W / rect.width),\n        y: (clientY - rect.top) * (H / rect.height),\n      };\n    }\n\n    function cellAt(x: number, y: number): { r: number; c: number } | null {\n      const { cols, rows } = currentDiff();\n      const c = Math.floor((x - offX) / cellSize);\n      const r = Math.floor((y - offY) / cellSize);\n      if (r >= 0 && r < rows && c >= 0 && c < cols) return { r, c };\n      return null;\n    }\n\n    function onSmiley(x: number, y: number): boolean {\n      const dx = x - W / 2;\n      const dy = y - TOOLBAR_H / 2;\n      return Math.sqrt(dx * dx + dy * dy) <= 16;\n    }\n\n    function diffBarIdx(x: number, y: number): number {\n      if (y < TOOLBAR_H + 4 || y > TOOLBAR_H + DIFF_H - 4) return -1;\n      const btnW = Math.floor(GRID_W / DIFFS.length);\n      const i = Math.floor((x - MARGIN) / btnW);\n      return i >= 0 && i < DIFFS.length ? i : -1;\n    }\n\n    // ── Actions ───────────────────────────────────────────────\n\n    function reveal(r: number, c: number): void {\n      if (gameState === 'won' || gameState === 'lost') return;\n      const cell = cellAtRC(r, c);\n      if (cell.revealed || cell.flagged) return;\n\n      if (firstClick) {\n        firstClick = false;\n        placeMines(r, c);\n        gameState = 'playing';\n        timerInterval = window.setInterval(() => {\n          timer++;\n          draw();\n        }, 1000);\n      }\n\n      if (cell.isMine) {\n        cell.revealed = true;\n        gameState = 'lost';\n        if (timerInterval !== null) clearInterval(timerInterval);\n        timerInterval = null;\n        revealMines();\n      } else {\n        revealBFS(r, c);\n        if (checkWin()) {\n          gameState = 'won';\n          if (timerInterval !== null) clearInterval(timerInterval);\n          timerInterval = null;\n          minesLeft = 0;\n        }\n      }\n      draw();\n    }\n\n    function flag(r: number, c: number): void {\n      if (gameState === 'won' || gameState === 'lost') return;\n      const cell = cellAtRC(r, c);\n      if (cell.revealed) return;\n      cell.flagged = !cell.flagged;\n      minesLeft += cell.flagged ? -1 : 1;\n      draw();\n    }\n\n    // ── Listeners ─────────────────────────────────────────────\n\n    function onClick(e: MouseEvent): void {\n      // Long-press fires a flag on touchstart; the subsequent click should be swallowed\n      // so it doesn't also reveal the cell the player just flagged.\n      if (longPressTriggered) {\n        longPressTriggered = false;\n        return;\n      }\n      const { x, y } = canvasXY(e.clientX, e.clientY);\n\n      if (onSmiley(x, y)) {\n        initGame();\n        return;\n      }\n\n      const di = diffBarIdx(x, y);\n      if (di >= 0) {\n        diffIdx = di;\n        initGame();\n        return;\n      }\n\n      const pos = cellAt(x, y);\n      if (pos) reveal(pos.r, pos.c);\n    }\n\n    function onContextMenu(e: MouseEvent): void {\n      e.preventDefault();\n      const { x, y } = canvasXY(e.clientX, e.clientY);\n      const pos = cellAt(x, y);\n      if (pos) flag(pos.r, pos.c);\n    }\n\n    function onTouchStart(e: TouchEvent): void {\n      const touch = e.touches[0];\n      if (!touch) return;\n      const { clientX, clientY } = touch;\n      longPressTimer = window.setTimeout(() => {\n        longPressTriggered = true;\n        const { x, y } = canvasXY(clientX, clientY);\n        const pos = cellAt(x, y);\n        if (pos) flag(pos.r, pos.c);\n      }, 450);\n    }\n\n    function cancelLongPress(): void {\n      if (longPressTimer !== null) clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n\n    // Suppress the mobile long-press callout / text selection so our own\n    // long-press flag handler is the one that fires.\n    const TOUCH_CSS: Record<string, string> = {\n      userSelect: 'none',\n      webkitUserSelect: 'none',\n      webkitTouchCallout: 'none',\n      touchAction: 'none',\n    };\n    const savedCss: Record<string, string> = {};\n\n    return {\n      start(): void {\n        initGame();\n        for (const k of Object.keys(TOUCH_CSS)) {\n          savedCss[k] = (canvas.style as unknown as Record<string, string>)[k] ?? '';\n          (canvas.style as unknown as Record<string, string>)[k] = TOUCH_CSS[k]!;\n        }\n        canvas.addEventListener('click', onClick);\n        canvas.addEventListener('contextmenu', onContextMenu);\n        canvas.addEventListener('touchstart', onTouchStart, { passive: true });\n        canvas.addEventListener('touchend', cancelLongPress);\n        canvas.addEventListener('touchmove', cancelLongPress, { passive: true });\n      },\n      stop(): void {\n        if (timerInterval !== null) clearInterval(timerInterval);\n        timerInterval = null;\n        cancelLongPress();\n        for (const k of Object.keys(TOUCH_CSS)) {\n          (canvas.style as unknown as Record<string, string>)[k] = savedCss[k] ?? '';\n        }\n        canvas.removeEventListener('click', onClick);\n        canvas.removeEventListener('contextmenu', onContextMenu);\n        canvas.removeEventListener('touchstart', onTouchStart);\n        canvas.removeEventListener('touchend', cancelLongPress);\n        canvas.removeEventListener('touchmove', cancelLongPress);\n      },\n      // Freeze the wall-clock timer when the tab hides. Without this, a\n      // tab left open overnight would show a 30000-second game.\n      pause(): void {\n        if (timerInterval !== null) {\n          clearInterval(timerInterval);\n          timerInterval = null;\n        }\n        cancelLongPress();\n      },\n      resume(): void {\n        // Only re-arm the timer if a game is actually in progress — idle / won\n        // / lost states never ran a timer to begin with.\n        if (gameState === 'playing' && timerInterval === null) {\n          timerInterval = window.setInterval(() => {\n            timer++;\n            draw();\n          }, 1000);\n        }\n      },\n    };\n  },\n};\n","import type { Game, GameHandle } from '../types';\n\n/*\n * Snake — classic grid snake.\n *\n * Controls: arrow keys / WASD to turn, Space to restart after game over.\n * Board wraps at the edges (toroidal) — only running into yourself is fatal.\n *\n * This was added in v0.2 primarily as a keyboard-input integration test for\n * the modal: modal listens on `document` (Esc, Tab focus trap) while the game\n * listens on `window`. Bubble phase fires document handler before window, so\n * Esc / Tab are intercepted by the modal and arrow keys fall through to the\n * game — no Game-contract extension needed.\n *\n * Fixed-step simulation with a dt accumulator (not \"one tick per RAF\") so the\n * apparent speed is framerate-independent.\n */\n\ntype Point = { x: number; y: number };\ntype Dir = 'up' | 'down' | 'left' | 'right';\n\nconst CELL = 20;\nconst STEP_MS = 160;\n\nexport const snake: Game = {\n  name: 'Snake',\n  icon: '🐍',\n  description: 'Arrow keys / WASD or swipe to move. Space / tap to restart.',\n  order: 3,\n  canvasSize: { width: 380, height: 380 },\n\n  init(canvas: HTMLCanvasElement): GameHandle {\n    const ctxMaybe = canvas.getContext('2d');\n    if (!ctxMaybe) throw new Error('[arcade-shelf/snake] 2D context unavailable');\n    const ctx: CanvasRenderingContext2D = ctxMaybe;\n\n    const W = canvas.width;\n    const H = canvas.height;\n    const COLS = Math.floor(W / CELL);\n    const ROWS = Math.floor(H / CELL);\n    const OFFSET_X = Math.floor((W - COLS * CELL) / 2);\n    const OFFSET_Y = Math.floor((H - ROWS * CELL) / 2);\n\n    let body: Point[] = [];\n    let dir: Dir = 'right';\n    // Buffered turn: we validate against `pendingDir`, not `dir`, so that two\n    // fast presses (right -> up -> left) are rejected as a reversal chain.\n    let pendingDir: Dir = 'right';\n    let apple: Point = { x: 0, y: 0 };\n    let score = 0;\n    let over = false;\n    let acc = 0;\n    let lastTs = 0;\n    let raf: number | null = null;\n\n    function placeApple(): void {\n      // Random rejection sampling. Grid is small and rarely > 50% full,\n      // so the expected retry count is tiny.\n      for (;;) {\n        const x = Math.floor(Math.random() * COLS);\n        const y = Math.floor(Math.random() * ROWS);\n        if (!body.some((p) => p.x === x && p.y === y)) {\n          apple = { x, y };\n          return;\n        }\n      }\n    }\n\n    function reset(): void {\n      const cx = Math.floor(COLS / 2);\n      const cy = Math.floor(ROWS / 2);\n      body = [\n        { x: cx - 2, y: cy },\n        { x: cx - 1, y: cy },\n        { x: cx, y: cy },\n      ];\n      dir = 'right';\n      pendingDir = 'right';\n      score = 0;\n      over = false;\n      acc = 0;\n      lastTs = 0;\n      placeApple();\n    }\n\n    function setDir(next: Dir): void {\n      // Compare against the most recent intent, not the currently-executing\n      // direction, so rapid keypresses can't sneak in a reversal.\n      if (next === 'up' && pendingDir === 'down') return;\n      if (next === 'down' && pendingDir === 'up') return;\n      if (next === 'left' && pendingDir === 'right') return;\n      if (next === 'right' && pendingDir === 'left') return;\n      pendingDir = next;\n    }\n\n    function step(): void {\n      if (over) return;\n      dir = pendingDir;\n      const head = body[body.length - 1]!;\n      let nx = head.x;\n      let ny = head.y;\n      if (dir === 'up') ny--;\n      else if (dir === 'down') ny++;\n      else if (dir === 'left') nx--;\n      else nx++;\n\n      // Wrap at the edges (toroidal board) — only self-collision is fatal.\n      if (nx < 0) nx = COLS - 1;\n      else if (nx >= COLS) nx = 0;\n      if (ny < 0) ny = ROWS - 1;\n      else if (ny >= ROWS) ny = 0;\n\n      if (body.some((p) => p.x === nx && p.y === ny)) {\n        over = true;\n        return;\n      }\n      body.push({ x: nx, y: ny });\n      if (nx === apple.x && ny === apple.y) {\n        score++;\n        placeApple();\n      } else {\n        body.shift();\n      }\n    }\n\n    function draw(): void {\n      ctx.fillStyle = '#111';\n      ctx.fillRect(0, 0, W, H);\n\n      // Subtle grid\n      ctx.strokeStyle = 'rgba(255,255,255,0.04)';\n      ctx.lineWidth = 1;\n      for (let i = 0; i <= COLS; i++) {\n        ctx.beginPath();\n        ctx.moveTo(OFFSET_X + i * CELL + 0.5, OFFSET_Y);\n        ctx.lineTo(OFFSET_X + i * CELL + 0.5, OFFSET_Y + ROWS * CELL);\n        ctx.stroke();\n      }\n      for (let i = 0; i <= ROWS; i++) {\n        ctx.beginPath();\n        ctx.moveTo(OFFSET_X, OFFSET_Y + i * CELL + 0.5);\n        ctx.lineTo(OFFSET_X + COLS * CELL, OFFSET_Y + i * CELL + 0.5);\n        ctx.stroke();\n      }\n\n      // Apple\n      ctx.fillStyle = '#e8635a';\n      ctx.beginPath();\n      ctx.arc(\n        OFFSET_X + apple.x * CELL + CELL / 2,\n        OFFSET_Y + apple.y * CELL + CELL / 2,\n        CELL / 2 - 2,\n        0,\n        Math.PI * 2,\n      );\n      ctx.fill();\n\n      // Snake — head a bit brighter than tail\n      for (let i = 0; i < body.length; i++) {\n        const p = body[i]!;\n        ctx.fillStyle = i === body.length - 1 ? '#b7e88a' : '#7fd07f';\n        ctx.fillRect(\n          OFFSET_X + p.x * CELL + 1,\n          OFFSET_Y + p.y * CELL + 1,\n          CELL - 2,\n          CELL - 2,\n        );\n      }\n\n      // Score overlay\n      ctx.fillStyle = '#fff';\n      ctx.font = '13px system-ui, -apple-system, sans-serif';\n      ctx.textAlign = 'left';\n      ctx.textBaseline = 'top';\n      ctx.fillText(`Score: ${score}`, 8, 6);\n\n      if (over) {\n        ctx.fillStyle = 'rgba(0,0,0,0.7)';\n        ctx.fillRect(0, 0, W, H);\n        ctx.fillStyle = '#fff';\n        ctx.textAlign = 'center';\n        ctx.textBaseline = 'middle';\n        ctx.font = 'bold 24px system-ui, -apple-system, sans-serif';\n        ctx.fillText('Game Over', W / 2, H / 2 - 10);\n        ctx.font = '14px system-ui, -apple-system, sans-serif';\n        ctx.fillText(`Score: ${score} · Space or tap to restart`, W / 2, H / 2 + 18);\n      }\n    }\n\n    function tick(ts: number): void {\n      if (lastTs === 0) lastTs = ts;\n      // Clamp so a backgrounded tab doesn't fast-forward 100 steps on return.\n      const dt = Math.min(1000, ts - lastTs);\n      lastTs = ts;\n      acc += dt;\n      while (acc >= STEP_MS) {\n        step();\n        acc -= STEP_MS;\n      }\n      draw();\n      raf = requestAnimationFrame(tick);\n    }\n\n    function onKeyDown(e: KeyboardEvent): void {\n      switch (e.key) {\n        case 'ArrowUp':\n        case 'w':\n        case 'W':\n          e.preventDefault();\n          setDir('up');\n          return;\n        case 'ArrowDown':\n        case 's':\n        case 'S':\n          e.preventDefault();\n          setDir('down');\n          return;\n        case 'ArrowLeft':\n        case 'a':\n        case 'A':\n          e.preventDefault();\n          setDir('left');\n          return;\n        case 'ArrowRight':\n        case 'd':\n        case 'D':\n          e.preventDefault();\n          setDir('right');\n          return;\n        case ' ':\n        case 'Spacebar': // legacy IE/Edge name; harmless to keep\n          // Swallow even when not over, so Space never scrolls the page\n          // while the modal has focus.\n          e.preventDefault();\n          if (over) reset();\n          return;\n      }\n    }\n\n    // Touch: swipe on canvas sets direction; tap-on-gameover restarts.\n    // Threshold is in CSS pixels so it scales with device zoom.\n    const SWIPE_MIN = 18;\n    let touchStartX = 0;\n    let touchStartY = 0;\n    let touchStartId: number | null = null;\n\n    function onTouchStart(e: TouchEvent): void {\n      if (touchStartId !== null) return;\n      const t = e.changedTouches[0];\n      if (!t) return;\n      touchStartId = t.identifier;\n      touchStartX = t.clientX;\n      touchStartY = t.clientY;\n    }\n\n    function onTouchMove(e: TouchEvent): void {\n      // Suppress page scroll while the finger is on the canvas.\n      if (touchStartId !== null) e.preventDefault();\n    }\n\n    function onTouchEnd(e: TouchEvent): void {\n      if (touchStartId === null) return;\n      let end: Touch | null = null;\n      for (let i = 0; i < e.changedTouches.length; i++) {\n        const t = e.changedTouches[i]!;\n        if (t.identifier === touchStartId) {\n          end = t;\n          break;\n        }\n      }\n      touchStartId = null;\n      if (!end) return;\n\n      const dx = end.clientX - touchStartX;\n      const dy = end.clientY - touchStartY;\n      const adx = Math.abs(dx);\n      const ady = Math.abs(dy);\n\n      if (adx < SWIPE_MIN && ady < SWIPE_MIN) {\n        // Treat as a tap — only meaningful when game is over (restart).\n        if (over) reset();\n        return;\n      }\n\n      if (adx > ady) setDir(dx > 0 ? 'right' : 'left');\n      else setDir(dy > 0 ? 'down' : 'up');\n    }\n\n    reset();\n    draw();\n\n    return {\n      start(): void {\n        window.addEventListener('keydown', onKeyDown);\n        canvas.addEventListener('touchstart', onTouchStart, { passive: true });\n        canvas.addEventListener('touchmove', onTouchMove, { passive: false });\n        canvas.addEventListener('touchend', onTouchEnd);\n        canvas.addEventListener('touchcancel', onTouchEnd);\n        raf = requestAnimationFrame(tick);\n      },\n      stop(): void {\n        window.removeEventListener('keydown', onKeyDown);\n        canvas.removeEventListener('touchstart', onTouchStart);\n        canvas.removeEventListener('touchmove', onTouchMove);\n        canvas.removeEventListener('touchend', onTouchEnd);\n        canvas.removeEventListener('touchcancel', onTouchEnd);\n        if (raf !== null) cancelAnimationFrame(raf);\n        raf = null;\n        lastTs = 0;\n      },\n      // Suspend RAF when the tab hides. Resetting lastTs on resume avoids a\n      // dt accumulator burst — we'd otherwise process many queued steps the\n      // moment the player comes back.\n      pause(): void {\n        if (raf !== null) cancelAnimationFrame(raf);\n        raf = null;\n        lastTs = 0;\n      },\n      resume(): void {\n        if (raf !== null) return; // already running\n        raf = requestAnimationFrame(tick);\n      },\n    };\n  },\n};\n","import type { Game, Shelf, ShelfOptions } from './types';\nimport { GameRegistry } from './registry';\nimport { renderShelf } from './render';\nimport type { OpenedModal } from './modal';\nimport './style.css';\n\nexport type {\n  CanvasSize,\n  Game,\n  GameHandle,\n  Shelf,\n  ShelfOptions,\n} from './types';\n\nexport { openGameModal, type OpenedModal } from './modal';\nexport { pong } from './games/pong';\nexport { minesweeper } from './games/minesweeper';\nexport { snake } from './games/snake';\n\nexport function createShelf(options: ShelfOptions): Shelf {\n  const registry = new GameRegistry();\n  let rendered: { destroy(): void } | null = null;\n  // Track the currently-open modal (one at a time — the shelf renders a\n  // single list, and opening a second game would just reuse the same\n  // modal slot). On unmount we close it so the game inside stops and\n  // releases its RAF / listeners.\n  let activeModal: OpenedModal | null = null;\n\n  function render(): void {\n    if (rendered) rendered.destroy();\n    rendered = renderShelf({\n      getGames: () => registry.list(),\n      getGame: (id) => registry.get(id),\n      options,\n      onModalOpen(modal) {\n        // If a previous modal is somehow still tracked, close it first —\n        // shouldn't normally happen, but cheap and avoids orphan handles.\n        if (activeModal) activeModal.close();\n        activeModal = modal;\n      },\n    });\n  }\n\n  const shelf: Shelf = {\n    register(game: Game) {\n      const ok = registry.add(game);\n      // If already mounted, re-render so the new game shows up immediately.\n      // Cheap: the list is usually single-digit entries.\n      if (ok && rendered) render();\n      return shelf;\n    },\n    unregister(id: string) {\n      const ok = registry.remove(id);\n      if (ok && rendered) render();\n      return ok;\n    },\n    list() {\n      return registry.list();\n    },\n    mount() {\n      render();\n      return shelf;\n    },\n    unmount() {\n      if (activeModal) {\n        activeModal.close();\n        activeModal = null;\n      }\n      if (rendered) {\n        rendered.destroy();\n        rendered = null;\n      }\n    },\n  };\n\n  return shelf;\n}\n"],"names":["gameId","game","GameRegistry","key","id","DEFAULT_SIZE","FOCUSABLE_SELECTOR","isFocusable","el","LOCK_COUNT_ATTR","LOCK_PREV_ATTR","acquireBodyScrollLock","ds","count","releaseBodyScrollLock","next","openGameModal","triggerElement","size","activeEl","fallbackFocus","lastFocus","overlay","dialog","header","title","closeBtn","canvas","footerContent","footer","handle","e","closed","close","onOverlayClick","onKeyDown","onVisibilityChange","onResize","_a","focusables","first","last","active","resolveContainer","target","sortGames","games","options","whitelist","order","list","allow","g","orderIndex","i","a","b","ai","bi","ao","bo","renderShelf","deps","getGames","getGame","onModalOpen","container","card","item","btn","ic","label","onClick","modal","destroy","pong","ctxMaybe","ctx","W","H","PADDLE_W","PADDLE_H","BALL","PLAYER_X","AI_X","FRAME_MS","playerY","aiY","ballX","ballY","vx","vy","scoreP","scoreA","started","running","raf","lastTs","rect","refreshRect","resetBall","dir","angle","speed","draw","step","ts","dt","aiCenter","diff","setPlayerY","clientY","y","onMouseMove","onTouchMove","t","onStart","minesweeper","TOOLBAR_H","DIFF_H","MARGIN","GRID_W","GRID_H","DIFFS","NUM_COLORS","diffIdx","grid","cellSize","offX","offY","minesLeft","gameState","timer","timerInterval","firstClick","longPressTimer","longPressTriggered","currentDiff","initGame","cols","rows","mines","cellAtRC","r","c","placeMines","safeR","safeC","placed","cell","n","dr","dc","nr","nc","revealBFS","startR","startC","queue","checkWin","revealMines","drawToolbar","drawDiffBar","drawGrid","raised3D","drawLED","sx","sy","sr","x","value","text","prefix","btnW","d","bw","bh","drawCell","s","drawMineIcon","drawFlagIcon","w","h","sunken","light","dark","cx","cy","canvasXY","clientX","cellAt","onSmiley","dx","dy","diffBarIdx","reveal","flag","di","pos","onContextMenu","onTouchStart","touch","cancelLongPress","TOUCH_CSS","savedCss","k","CELL","STEP_MS","snake","COLS","ROWS","OFFSET_X","OFFSET_Y","body","pendingDir","apple","score","over","acc","placeApple","p","reset","setDir","head","nx","ny","tick","SWIPE_MIN","touchStartX","touchStartY","touchStartId","onTouchEnd","end","adx","ady","createShelf","registry","rendered","activeModal","render","shelf","ok"],"mappings":"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"}