/*
 * Puzz shared-shell — the app shell that caps the whole UI (header, board,
 * modals, builder panels) at a fixed mobile-like width and centers it, so
 * wide viewports get side background instead of a redesigned layout.
 * Identical across Tangle, Escape, and Split (copy-pasted, no build step
 * yet — see types.md). Pair with modal.css for the completion/daily
 * overlays, which are positioned relative to .game-shell too.
 *
 * Usage: give the page's single top-level wrapper (the element that
 * contains the header, the board/main area, and every modal/overlay) the
 * class "game-shell", and set `position: relative` isn't needed separately
 * — it's included below. Any overlay that used `position: fixed; inset: 0`
 * against the viewport should switch to `position: absolute; inset: 0`
 * once it's a descendant of .game-shell.
 *
 * Width is grid-driven: each game's board-sizing JS computes the puzzle
 * grid's pixel width from available height (the harder axis) and writes it
 * to --shell-computed-width on .game-shell, so the whole shell — header
 * included — hugs the grid instead of sitting in a fixed-width box with
 * side padding. --game-max-width is still the ceiling and 100% is the
 * pre-JS/no-JS fallback; --shell-min-width keeps the header/controls from
 * being squeezed narrower than they can lay out.
 */
:root {
  --game-max-width: 480px; /* shared across all three games — width ceiling */
  --shell-min-width: 380px; /* floor so header/controls don't get squeezed */
}

html, body {
  min-height: 100dvh;
}

body {
  margin: 0;
  display: flex;
  justify-content: center;
  background: var(--game-shell-backdrop, var(--bg, #0c141c));
}

.game-shell {
  position: relative;
  /* --shell-computed-width is set by JS per render (clamped to
     [--shell-min-width, --game-max-width] there already); the clamp() here
     is a defensive second clamp so a stale/unclamped value never breaks
     layout, and 100% is the fallback before JS has run. */
  width: clamp(
    min(var(--shell-min-width), 100%),
    var(--shell-computed-width, 100%),
    min(var(--game-max-width), 100%)
  );
  max-width: var(--game-max-width);
  min-height: 100dvh;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

/* Kicks in once the shell visibly detaches from the viewport edges */
@media (min-width: 481px) {
  .game-shell {
    box-shadow: 0 0 0 1px var(--border-strong, rgba(255, 255, 255, 0.15));
  }
}

/* Phones in landscape: reclaim vertical space for the grid/board */
@media (orientation: landscape) and (max-height: 500px) {
  .game-shell .game-header,
  .game-shell #header {
    padding-block: 6px;
  }
  .game-shell .game-header h1,
  .game-shell #header h1 {
    font-size: 14px;
  }
}

/* Minimum 44x44 hit area for interactive controls, regardless of visual
   size — apply via this class on elements whose visible box is smaller. */
.puzz-min-hit-area {
  position: relative;
}
.puzz-min-hit-area::after {
  content: '';
  position: absolute;
  inset: 50%;
  width: max(100%, 44px);
  height: max(100%, 44px);
  transform: translate(-50%, -50%);
}
