/* game-primitives.css - shared layout primitives every game module MUST use.
 *
 * Exists because v0.4.27-v0.4.28 user testing surfaced a class of layout
 * failures that were all the same root cause: games writing ad-hoc
 * inline styles without shared proportional constraints. Shipping as
 * v0.4.29 alongside the layout.spec.js test suite that enforces use.
 *
 * The five primitives:
 *   .game-screen         outermost container every game render() goes into
 *   .game-action-btn     in-game primary action button (replaces raw .btn)
 *   .game-grid-square    grid container that stays square with equal rows
 *   .game-tile           individual grid cell with mandatory aspect-ratio:1
 *   .game-canvas-wrap    canvas wrapper with known sizing
 *
 * Rules enforced by tests/layout.spec.js and tests/contract.spec.js:
 *   1. Every game's top-level rendered element has class "game-screen" or
 *      starts with one. If not, layout.spec fails.
 *   2. Every in-game clickable action button has class "game-action-btn"
 *      (or is explicitly exempted via data-allow-raw-btn).
 *   3. No button renders with rect.width > 0.75 * viewport.width OR
 *      rect.height > 0.45 * viewport.height unless .game-action-btn--large
 *      or data-allow-large is set.
 *   4. Grids using .game-grid-square must set --grid-cols (and optionally
 *      --grid-rows). Tests assert the rendered grid has exactly
 *      rows x cols children.
 *
 * Games are allowed to nest custom layout inside these containers but not
 * replace them.
 */

/* -------------------------------------------------------------------
 * .game-screen - top-level container every game's render() puts content into
 * ------------------------------------------------------------------- */

.game-screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  width: 100%;
  height: 100%;
  /* v0.4.35: bumped from 720px fixed to a viewport-aware clamp. The
   * previous max-width gave game content ~30% of a desktop viewport
   * (the "3/10" the user named); this targets ~75-85% on any screen
   * by capping to min(960px, 90vw). On phones the 90vw branch wins
   * (e.g. 351px on a 390px iPhone). On desktop the 960px branch wins
   * but the children (grid / canvas) fill it via their own clamps. */
  max-width: min(calc(960px * var(--ui-scale, 1)), 92vw);
  margin: 0 auto;
  padding: var(--space-md);
  box-sizing: border-box;
  overflow: hidden;
  font-family: var(--font-sans);
}

/* Modifier: top-aligned content (for games that should stack from the top). */
.game-screen--stack {
  justify-content: flex-start;
}

/* Modifier: full-bleed (for games that need the whole play area, e.g. Snake). */
.game-screen--bleed {
  padding: 0;
  max-width: 100%;
}

/* Modifier: narrow play area (for split-screen / input-line games like
 * wyr, rps, bullscows, nim where the default 960px game-screen lets
 * content stretch unhelpfully wide at desktop). Keeps content at a
 * comfortable read-width while letting the painted backdrop fill the
 * rest of the screen. */
.game-screen--narrow {
  max-width: min(calc(640px * var(--ui-scale, 1)), 92vw);
}

/* -------------------------------------------------------------------
 * .chrome-chip / .chrome-panel - text protection over painted backdrops
 *
 * The painted in-game backdrops do visual work, but bare text on top of
 * them loses contrast (varies with where the brushwork lands - sky vs
 * forest vs water). v0.5.19: every progress label, prompt, score, or
 * status string that sits directly over a painted backdrop must use
 * one of these primitives so it reads at >=95% confidence on every
 * backdrop in the collection.
 *
 * Choice: solid dark pill ("T2" in the v0.5.19 sample comparison).
 * Rationale: 100% reading confidence, simplest CSS (no backdrop-filter
 * compatibility concerns), works the same on every browser the
 * collection supports.
 *
 * Use .chrome-chip for short inline labels ("Q3/15 | Score: 0",
 * "Round 1 of 5", "Pile 1", "Your turn"). Use .chrome-panel for
 * multi-line blocks (rules text, "Bull = right digit, right spot").
 * ------------------------------------------------------------------- */

.chrome-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: 6px 14px;
  background: rgba(15, 17, 22, 0.78);
  color: #fff;
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.2;
  border-radius: 999px;
  /* Keep chip from expanding to fill flex container. */
  flex: 0 0 auto;
}

.chrome-chip--sm { padding: 4px 10px; font-size: var(--text-xs); }
.chrome-chip--lg { padding: 8px 18px; font-size: var(--text-base); }

.chrome-panel {
  background: rgba(15, 17, 22, 0.78);
  color: #fff;
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-md, 12px);
  line-height: 1.5;
}

/* -------------------------------------------------------------------
 * .game-action-btn - in-game primary action button
 *
 * Replaces raw .btn for in-game actions. Critically NOT flex:1, so
 * dropping it in a column flex container does not cause it to stretch.
 * ------------------------------------------------------------------- */

.game-action-btn {
  flex: 0 0 auto;
  align-self: center;
  height: var(--button-height, 52px);
  min-width: 140px;
  max-width: 280px;
  padding: 0 var(--space-xl);
  border: none;
  border-radius: var(--button-radius, 8px);
  background: var(--game-accent, var(--accent));
  color: var(--bg);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: var(--font-weight-bold);
  cursor: pointer;
  transition: transform var(--motion-duration-fast) var(--motion-ease);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.game-action-btn:active {
  transform: scale(0.97);
}

.game-action-btn:disabled {
  opacity: 0.5;
  cursor: default;
}

/* Secondary / cancel variant. */
.game-action-btn--secondary {
  background: var(--bg-elevated);
  color: var(--text-primary);
  border: 1px solid var(--border);
}

/* Large circular hero button (Tap Speed, Reaction Time). Still constrained
 * so it cannot take over the screen. */
.game-action-btn--large {
  height: 180px;
  width: 180px;
  min-width: 180px;
  max-width: 180px;
  border-radius: 50%;
  font-size: var(--text-2xl);
  padding: 0;
}

/* -------------------------------------------------------------------
 * .game-grid-square - a grid that must stay square with equal rows
 *
 * Use with CSS custom properties:
 *   --grid-cols: number of columns (default 3)
 *   --grid-rows: number of rows   (default = --grid-cols, for square grids)
 *
 * Example: Tic-Tac-Toe sets --grid-cols: 3 and inherits grid-rows: 3.
 * Connect 4 sets --grid-cols: 7, --grid-rows: 6 and uses --landscape modifier.
 * ------------------------------------------------------------------- */

.game-grid-square {
  display: grid;
  gap: var(--game-grid-gap, var(--space-sm));
  width: 100%;
  /* v0.4.35: bumped to a viewport-aware clamp targeting ~75-85% of
   * the SHORTER viewport axis (vmin). Was 400px fixed which read tiny
   * on desktop. min(640px, 80vmin) targets the same ~80% on phones
   * AND on desktop. */
  max-width: min(calc(640px * var(--ui-scale, 1)), 80vmin);
  aspect-ratio: calc(var(--grid-cols, 3) / var(--grid-rows, var(--grid-cols, 3)));
  grid-template-columns: repeat(var(--grid-cols, 3), 1fr);
  grid-template-rows: repeat(var(--grid-rows, var(--grid-cols, 3)), 1fr);
  box-sizing: border-box;
}

.game-grid-square--landscape {
  /* Explicit hint for wider-than-tall boards (Connect 4). Wider clamp
   * since the layout is horizontally biased. */
  max-width: min(calc(720px * var(--ui-scale, 1)), 90vmin);
}

/* -------------------------------------------------------------------
 * .game-tile - individual grid cell
 *
 * Critically has aspect-ratio:1 + min-width:0 + min-height:0 so cells
 * NEVER change size when their content changes (the Tic-Tac-Toe
 * regression from v0.4.27-v0.4.28).
 * ------------------------------------------------------------------- */

.game-tile {
  aspect-ratio: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  box-sizing: border-box;
}

/* -------------------------------------------------------------------
 * .game-canvas-wrap - wrapper around games that render to <canvas>
 *
 * Ensures the canvas has a known max size and proper aspect ratio,
 * avoiding the "compressed thin" rendering when the underlying canvas
 * element is stretched by its parent.
 * ------------------------------------------------------------------- */

.game-canvas-wrap {
  width: 100%;
  height: auto;
  /* v0.4.35: same vmin treatment as .game-grid-square - ~80% of shorter
   * viewport axis on any screen, capped at 720px so it doesn't get
   * comically large on huge monitors. */
  max-width: min(calc(720px * var(--ui-scale, 1)), 80vmin);
  max-height: min(calc(720px * var(--ui-scale, 1)), 80vmin);
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
}

.game-canvas-wrap canvas {
  width: 100% !important;
  height: 100% !important;
  display: block;
}

/* -------------------------------------------------------------------
 * .game-stat-bar - header row for score / timer / moves
 *
 * Sits above the play area. Constrained width so it never spans wider
 * than the game area.
 * ------------------------------------------------------------------- */

.game-stat-bar {
  display: flex;
  flex: 0 0 auto;
  gap: var(--space-md);
  width: 100%;
  max-width: 480px;
  justify-content: space-around;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.game-stat-bar__cell {
  text-align: center;
  min-width: 60px;
}

.game-stat-bar__value {
  display: block;
  font-size: var(--text-lg);
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
}

.game-stat-bar__label {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* -------------------------------------------------------------------
 * .game-ready - the pre-game "ready" / "start" screen template
 *
 * Many games have an identical pre-game state: hero asset, big title,
 * sub-text, single primary action button. Before this primitive, every
 * game wrote ad-hoc inline styles for that surface, leading to the
 * "Tap UI looks terrible" / "Higher Lower UI looks terrible" feedback
 * (Tap Speed had bare text on dark; Higher/Lower started identically).
 *
 * Use as:
 *   <div class="game-screen">
 *     <div class="game-ready">
 *       <div class="game-ready__art"><img src="..." alt=""></div>
 *       <h1 class="game-ready__title">Hot Potato</h1>
 *       <p class="game-ready__subtitle">Pass it before time runs out!</p>
 *       <button class="game-action-btn game-ready__cta">Start</button>
 *     </div>
 *   </div>
 * ------------------------------------------------------------------- */

.game-ready {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-lg);
  width: 100%;
  max-width: 360px;
  padding: var(--space-xl) var(--space-lg);
  text-align: center;
  /* v0.5.19: opaque card background so the title + subtitle (which sit
   * directly on the painted backdrop) read at >=95% confidence. Matches
   * the chrome-panel contract from the same release. */
  background: rgba(15, 17, 22, 0.78);
  border-radius: var(--radius-md, 12px);
  color: #fff;
}

.game-ready__art {
  width: 120px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-sm);
}

.game-ready__art img,
.game-ready__art svg {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 8px 24px rgba(0, 0, 0, 0.45));
}

.game-ready__title {
  font-family: var(--font-display, var(--font-sans));
  font-size: var(--text-3xl, 2rem);
  font-weight: var(--font-weight-display);
  color: var(--text-primary);
  letter-spacing: -0.02em;
  margin: 0;
}

.game-ready__subtitle {
  font-size: var(--text-base);
  color: var(--text-secondary);
  margin: 0;
  line-height: 1.5;
  max-width: 28ch;
}

.game-ready__cta {
  margin-top: var(--space-md);
  min-width: 200px;
}

/* -------------------------------------------------------------------
 * .game-reveal - the between-rounds reveal screen template (RPS, etc.)
 * ------------------------------------------------------------------- */

.game-reveal__result {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-bold);
  text-align: center;
  min-height: 1.6em;
}

.game-reveal__result--win { color: var(--color-success, var(--game-accent)); }
.game-reveal__result--lose { color: var(--color-error); }
.game-reveal__result--draw { color: var(--text-secondary); }

/* -------------------------------------------------------------------
 * Reduced motion + accessibility
 * ------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .game-action-btn { transition: none; }
  .game-action-btn:active { transform: none; }
}

.reduce-motion .game-action-btn { transition: none; }
.reduce-motion .game-action-btn:active { transform: none; }
