/* The frame every game page sits in: the machine around the screen.
 *
 * hub.css does this for the root page; this is its counterpart for a game, and
 * the two are deliberately the same machine one size down — the same header from
 * shared.css, the same bloom on the title, the same scanlines, the same hairline
 * rules. A visitor moving from the hub into a game should not feel they changed
 * sites, which is why the wordmark and nav are now literally the same element
 * here as on the hub rather than a breadcrumb standing in for them.
 *
 * It is loaded *between* shared.css and the game's own style.css:
 *
 *   <link rel="stylesheet" href="../../shared.css">
 *   <link rel="stylesheet" href="../../game.css">
 *   <link rel="stylesheet" href="style.css">
 *
 * so a game can still override anything here, and tests/contract.test.js still
 * sees shared.css first.
 *
 * All six games wear it. tests/contract.test.js holds every game to that —
 * the link, its position between the other two sheets, and the frame's own
 * elements — so a seventh game cannot quietly ship on the bare page.
 *
 * The rule that shapes all of it: **chrome against screen.** Every glow, wash
 * and scanline belongs to the machine; the board is lifted out from under them
 * on z-index 7 with its own opaque ground, because a scanline over a Sudoku
 * digit or a chess hairline is texture bought at the cost of reading the game.
 */

/* ---------- the frame ---------- */

.game-page {
  position: relative;
  min-height: 100vh;
  overflow: hidden;
  margin: 0;
}

/* Scanlines. 1px of near-black every 3px — enough to read as a tube at arm's
   length, faint enough not to fight text. It sits above the wash and below the
   board, which is what "chrome against screen" means in z-index terms. */
.game-crt {
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.34) 0 1px,
    transparent 1px 3px
  );
}

/* Deliberately the hub's `.screen` geometry, to the pixel: same max-width, same
   horizontal padding, same padding-top. The wordmark sits in the top-left corner
   of both, and if these two disagree it visibly jumps as you move between them.
   Change one and change the other. */
.game-in {
  position: relative;
  max-width: 1080px;
  margin: 0 auto;
  padding: 2.6rem 1.8rem 2rem;
}

/* ---------- the head ---------- */

/* Holds the shared header. It used to be a row of its own - breadcrumb on one
   side, title on the other - and carried the hairline under the head of the
   page; the header brings both now. */
.game-top {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  padding-bottom: 0.55rem;
}

.game-title {
  margin: 0;
  font-size: 2.1rem;
  line-height: 1;
  letter-spacing: 0.09em;
  font-weight: 400;
  color: var(--p-hot);
  text-shadow: var(--bloom-lg);
}

/* ---------- the status strap ---------- */

/* #status, restyled. It keeps shared.css's reserved height so the board does
   not jump when the text changes, and gains the hub's fading block cursor —
   the device that says this is a terminal waiting on you. */
.game-strap {
  margin: 0.95rem 0 1.1rem;
  color: var(--p-pale);
  font-size: 1.22rem;
  letter-spacing: 0.03em;
  text-align: center;
}

/* Whatever the strap wants to emphasise — the side to move, the state of play.
   --strap-accent lets the game repoint it without a rule of its own. */
.game-strap .who {
  color: var(--strap-accent, var(--p-amber));
}

.game-strap::after {
  content: "";
  display: inline-block;
  width: 0.5em;
  height: 0.95em;
  margin-left: 0.45em;
  vertical-align: -0.1em;
  background: var(--p-amber);
  box-shadow: 0 0 12px rgba(255, 176, 0, 0.55);
  animation: game-cursor 2.4s ease-in-out infinite;
}

/* A cursor is what a terminal shows *after* something. On its own, with the
   strap's reserved height holding it out in the middle of the page, it reads as
   a stray mark rather than as a prompt — which is what it did in Pong, whose
   strap is deliberately empty during a rally and at the menu. The height stays
   reserved either way, so nothing moves when the text comes back. */
.game-strap:empty::after {
  display: none;
}

@keyframes game-cursor {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.12; }
}

@media (prefers-reduced-motion: reduce) {
  .game-strap::after {
    animation: none;
    opacity: 0.75;
  }
}

/* ---------- the stage ---------- */

/* The board and anything standing beside it. z-index 7 and an opaque ground
   lift it clear of the scanlines above.
 *
 * Centred, and so is everything under it. The frame is as wide as the window
 * and most boards are a few hundred pixels, so left-aligned they sat in the
 * corner of a very large empty page with the title floating off to the right —
 * which is what it looked like, and it looked like a mistake. Pong is the
 * exception and turns this off: its cabinet is already a centred column of its
 * own, and centring inside that column as well would be centring twice. */
.game-stage {
  position: relative;
  z-index: 7;
  display: flex;
  gap: 1.6rem;
  align-items: flex-start;
  justify-content: center;
  flex-wrap: wrap;
}

/* The controls row under the board rides above the scanlines too, or the
   buttons pick up stripes their labels have to be read through. */
.game-page .controls {
  position: relative;
  z-index: 7;
  margin-top: 1.1rem;
  justify-content: center;
}

/* ---------- what stands with the board ---------- */

/* A board's own readout — score, timer, flags left — directly above it and as
   wide as it is, which is why it sits inside the stack in the markup rather
   than beside the title. */
.hud {
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  margin-bottom: 0.5rem;
  color: var(--p-dim);
  font-size: 1.05rem;
  letter-spacing: 0.06em;
}

/* #instructions, and anything else a game folds out under its controls. Four
   games carried four near-identical copies of this block; the frame is where it
   belongs, and a game keeps only the part that is its own — Sudoku's headings,
   Minesweeper's armed reset.
 *
 * Selectors are single-class on purpose. game.css is linked by game pages and
 * nothing else, so there is no need to fence these off with `.game-page` — and
 * doing so would raise their specificity above the game's own style.css, which
 * loads *after* this file precisely so it can override it.
 *
 * No `display` rule here, on purpose: without one the `hidden` attribute alone
 * closes the panel. Adding one would need scoping to :not([hidden]) or every
 * panel on the site renders open on load. */
.instructions,
.settings {
  position: relative;
  z-index: 7;
  max-width: 460px;
  margin: 1rem auto 0;
  padding: 0.85rem 1rem;
  background: var(--p-panel);
  border: 1px solid var(--p-hairline);
  border-radius: 0;
  font-size: 1rem;
  color: var(--p-desc);
}

.instructions b {
  color: var(--p-pale);
  font-weight: 400;
}

.instructions p {
  margin: 0;
  color: var(--p-dim);
}

.instructions ul {
  margin: 0 0 0.6rem;
  padding-left: 1.1rem;
}

.instructions li {
  margin-bottom: 0.2rem;
}

/* ---------- the foot ---------- */

/* Standing instructions live here rather than in #status: the contract keeps
   the status line for game state only, and a hint that never changes is not
   state. One span sits left; a second, if a game has something worth saying,
   sits right. Chess carries one — the rules it quietly handles for you were
   there and Gabriel took them out. */
.game-foot {
  position: relative;
  z-index: 7;
  margin-top: 1.3rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--p-hairline);
  color: var(--p-dim);
  font-size: 1rem;
  letter-spacing: 0.05em;
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.game-foot b {
  color: var(--p-soft);
  font-weight: 400;
}

/* The hub narrows at 760px, so this does too and at the same values - see
   `.game-in` above, and `.screen` in hub.css. A different breakpoint here would
   put the wordmark in two different places between 620px and 760px. */
@media (max-width: 760px) {
  .game-in {
    padding: 1.8rem 1.1rem 2.6rem;
  }
}

@media (max-width: 620px) {
  .game-title {
    font-size: 1.7rem;
  }

  /* Two columns of hint text on a phone is two unreadable columns. */
  .game-foot {
    flex-direction: column;
    gap: 0.2rem;
  }
}
