/* === Shared shell for game play pages ===
 *
 * Every game page used to carry its own copy of this: the palette, the
 * header, the panel and HUD layout, the touch controls. Four copies meant
 * a palette change was a five-file edit, and it was about to become ten.
 *
 * Play pages deliberately do NOT load /styles.css, that stylesheet is
 * built around the marketing layout (.wrap, .card, .hero) and its rules
 * would fight the game HUD. This file is the game equivalent.
 *
 * Per-game differences belong in a small <style> block on the page, or in
 * the custom properties below:
 *
 *   --canvas-ratio   aspect ratio of the game canvas (default 960/640)
 */

:root {
  --ink: #e6edf3;
  --muted: #9ab;
  --panel: #121821;
  --card: #1a2230;
  --accent: #7ce7a2;
  --edge: #1f2b3d;
  --canvas-ratio: 960/640;
  --font-display: 'Press Start 2P', ui-monospace, SFMono-Regular, Menlo, monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: #0a0e14;
  color: var(--ink);
  font: 16px/1.5 Inter, system-ui, "Segoe UI", Roboto, Helvetica, Arial;
}

/* --- chrome --- */

footer { background: var(--panel); }

/* The objective, generated onto every play page from tools/registry.py.
   Play pages used to list the controls and never say what you were trying
   to do; the landing page had a blurb, but nobody reads the landing page on
   the way to a game they have already clicked. */
.objective {
  max-width: 68ch;
  margin: 0 0 14px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.6;
}

/* Matches .wrap in styles.css and .site-header-inner, so the header, the
   game and the marketing pages all share one content edge. */
main {
  max-width: 1060px;
  margin: auto;
  padding: 24px;
}

main > h1 {
  font-family: var(--font-display);
  font-size: 18px;
  line-height: 1.5;
  margin: 6px 0 14px;
}

footer {
  padding: 20px;
  text-align: center;
  color: var(--muted);
}

/* --- game surface --- */

#gameWrap {
  background: #0b111b;
  border: 1px solid #1d2840;
  border-radius: 16px;
  overflow: hidden;
  position: relative;
}

#c {
  display: block;
  max-width: 100%;
  height: auto;
  aspect-ratio: var(--canvas-ratio);
  background: #02060d;
  margin: 0 auto;
}

.hud {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 0;
  color: var(--muted);
}

.panel {
  background: var(--panel);
  border: 1px solid var(--edge);
  border-radius: 16px;
  padding: 14px;
  margin-top: 12px;
}

.panel h2 {
  font-family: var(--font-display);
  font-size: 13px;
  line-height: 1.6;
  margin: 0 0 12px;
}

.row {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  align-items: center;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border-radius: 999px;
  padding: 6px 10px;
  background: #10192a;
  border: 1px solid var(--edge);
  color: var(--muted);
  font-size: 12px;
}

/* --- buttons --- */

.btn {
  appearance: none;
  border: 0;
  border-radius: 12px;
  padding: 9px 13px;
  background: var(--card);
  color: var(--ink);
  font-weight: 600;
  cursor: pointer;
}

.btn:hover { background: #212b3c; }

.btn.primary {
  background: linear-gradient(135deg, #10b981, #22d3ee);
  color: #00130b;
  font-weight: 700;
}

/* --- touch controls ---
 * Hidden on pointer devices, shown on narrow screens. Sized for thumbs:
 * every target clears the 44px minimum. */

#touchWrap {
  display: none;
  gap: 8px;
  margin-top: 8px;
}

#touchWrap button {
  flex: 1;
  min-height: 52px;
  padding: 14px;
  border-radius: 12px;
  border: 1px solid #24344e;
  background: #0f1521;
  color: var(--ink);
  font-weight: 700;
  font-size: 15px;
}

#touchWrap button:active {
  background: #1f2b3d;
  transform: translateY(1px);
}

/* Any touch device gets the controls, not just narrow ones. A tablet is
   as unable to press an arrow key as a phone. */
@media (max-width: 1024px), (pointer: coarse) {
  #touchWrap { display: flex; }
}

@media (max-width: 700px) {
  main { padding: 18px; }   /* matches .site-header-inner at this width */
}

/* --- touch controls, drawn over the board --- */

/* A thumb pad under the left thumb and an action button under the right,
   floating on the game rather than sitting under it in the page. The old
   row of five small buttons was in the middle of the page, nowhere near
   either thumb, and too small to hit without looking. */

/* Fixed to the screen, not to the board. Thumbs are at the bottom corners
   of the phone wherever the page happens to be scrolled to, and the first
   version anchored these to the game wrap: the wrap runs past the bottom
   of a phone screen, so both controls sat about 125 pixels below the fold
   and could not be reached at all without scrolling away from the game. */
.touch-layer {
  position: fixed;
  inset: 0;
  pointer-events: none;   /* only the controls themselves take input */
  z-index: 40;
}

.touch-pad,
.touch-action {
  position: fixed;
  bottom: max(16px, env(safe-area-inset-bottom, 0px));
  pointer-events: auto;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  backdrop-filter: blur(2px);
}

.touch-pad {
  left: 16px;
  /* Sized off the short side of the screen so it is the same physical
     size in either orientation. */
  width: clamp(110px, 26vmin, 190px);
  aspect-ratio: 1;
  border-radius: 50%;
  border: 2px solid rgba(124, 231, 162, .45);
  background: radial-gradient(circle at 50% 50%,
              rgba(124, 231, 162, .10), rgba(6, 10, 20, .55) 70%);
  display: grid;
  place-items: center;
}

.touch-knob {
  width: 42%;
  height: 42%;
  border-radius: 50%;
  background: rgba(124, 231, 162, .55);
  border: 2px solid rgba(124, 231, 162, .85);
  transition: transform .06s linear;
  pointer-events: none;
}

.touch-action {
  right: 16px;
  width: clamp(76px, 18vmin, 130px);
  aspect-ratio: 1;
  border-radius: 50%;
  border: 2px solid rgba(244, 114, 182, .7);
  background: rgba(244, 114, 182, .22);
  color: #fde7f3;
  font: 700 15px/1 Inter, system-ui, sans-serif;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.touch-action:active {
  background: rgba(244, 114, 182, .45);
  transform: scale(.96);
}

/* Portrait on a phone gives a 3:2 board about a third of the screen. The
   controls still work, but the board is small, so say the one thing that
   fixes it rather than letting people conclude the game is broken. */
.rotate-hint {
  display: none;
  margin: 8px 0 0;
  text-align: center;
  color: var(--muted);
  font-size: .85rem;
}

@media (pointer: coarse) and (orientation: portrait) {
  .rotate-hint { display: block; }
}

/* Edge to edge on a phone. The page padding, the wrap border and the
   rounded corners cost about forty pixels of board width, which is a
   tenth of the screen on a phone and worth more than the styling. */
@media (max-width: 700px) {
  #gameWrap {
    margin-left: -18px;
    margin-right: -18px;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
  }
}

/* Room for the board on a phone.
   The objective paragraph and the row of numbers under the canvas are
   both redundant on a touch screen now: the objective is on the start
   banner and the numbers are drawn on the board itself. Between them
   they were costing about sixty pixels of height, which on a 342 pixel
   landscape screen is a quarter of the board. They stay in the document
   for screen readers. */
@media (pointer: coarse) {
  .objective,
  .hud .hud-readout {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .hud { padding: 6px 0; }
}

/* Landscape on a phone is how these are meant to be played, so give the
   board the screen.

   Measured on an 844x390 landscape phone, the canvas started 226 pixels
   down the page: fifty for the site header, then the title, then two
   instruction pills that wrap onto two lines at that width. That left
   164 pixels of screen for a board that wants to be at least 200 tall,
   so it hung off the bottom and you were playing a game you could only
   half see. The edge to edge rule above did not help because it is
   keyed on a 700 pixel width and a landscape phone is wider than that.

   The title is in the tab and in the header, and the controls and the
   scoring tip are both on the start banner, so nothing above the board
   is load bearing while a run is going. All of it stays in the document
   for screen readers and for anyone rotating back to portrait. */
@media (pointer: coarse) and (orientation: landscape) {
  main { padding: 8px 12px 18px; }

  main > h1,
  main > .row {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  #gameWrap {
    margin-left: -12px;
    margin-right: -12px;
    padding: 0;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
  }
}

/* --- fullscreen --- */

/* Fullscreen should be the game, not the page at a bigger size.

   Measured on a 3440x1440 ultrawide: the board came out 1554x1036, which
   is 45 percent of the width and 72 percent of the height, floating in
   black with the page readout pinned to the bottom left corner and the
   button row to the bottom right. Two separate causes. The wrap becomes
   the screen when it goes fullscreen, so its children stretch to the
   screen edges instead of sitting under a 1060 pixel column; and the
   height budget in each game is a fraction of the window written for a
   page that also has a leaderboard on it, which is the wrong number once
   the page is gone. This file fixes the first, the games fix the second.

   The button row stays, faded, along the bottom edge. Escape leaves
   fullscreen on a desktop but there is no Escape key on a phone, so
   hiding the way out is not an option. */
#gameWrap:fullscreen {
  --fs-rail: 132px;   /* the control column, reserved rather than overlaid */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--fs-rail) 0 0;
  border: 0;
  border-radius: 0;
  background: #02060d;
}

/* The controls in fullscreen live in the letterbox, not on the board.

   The first version floated them along the bottom edge, centred. On a
   phone that put them straight across the city row, which is the half of
   Last Salvo you need to see, and there is no hover on a phone so the
   focus left behind by the tap held them at full brightness for the rest
   of the run. (js/fullscreen-ui.js drops that focus now as well.)

   Any screen wider than the board leaves a black bar down each side: a
   3:2 board on a 16:9 desktop or a 20:9 phone has hundreds of pixels of
   nothing to either side. The controls go there, stacked down the right
   hand edge and dimmed, where they cover no part of the game.

   The column is reserved as padding on the wrap rather than floated over
   it, because the bar is not always wide enough to hold it: Breakout's
   board is 960x560, which on a 16:9 laptop leaves 34 pixels a side, and a
   floating column covered five percent of the right hand edge, exactly
   where the paddle lives. Reserving it costs a width bound board those
   pixels and costs a height bound board, which is nearly all of them,
   nothing at all. */
#gameWrap:fullscreen .hud {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: auto;
  width: var(--fs-rail);
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 8px;
  padding: 12px;
  margin: 0;
  background: none;
  opacity: .35;
  transition: opacity .18s;
}

#gameWrap:fullscreen .hud:hover,
#gameWrap:fullscreen .hud:focus-within {
  opacity: 1;
}

/* The buttons sit in a div of their own inside the hud, which has to
   stack with the column rather than stay a row. */
#gameWrap:fullscreen .hud > div {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
}

#gameWrap:fullscreen .hud .btn {
  padding: 7px 11px;
  font-size: 13px;
}

#gameWrap:fullscreen .hud .hud-readout,
#gameWrap:fullscreen .rotate-hint,
#gameWrap:fullscreen #touchWrap {
  display: none;
}
