/**
 * Ponoki. Desktop frame.
 *
 * The games are built portrait-first. On a laptop or a large monitor they
 * used to render full-bleed, so a layout tuned for a 390px phone stretched
 * across 1920px and lost the proportions it was designed in. This sheet
 * centres each game's play surface in a phone-shaped column and lets the
 * ambient Ponoki background fill the space around it. Home and Zen already
 * do this on their own (.home-wrapper, .zen-wrapper) and are not linked here.
 *
 * Additive only. Everything is gated behind min-width: 900px, so phones,
 * portrait tablets and the Android TWA (which reports phone width) are
 * untouched. 900px matches the desktop heuristic already used on the home
 * page for the mobile-first notice.
 *
 * IMPORTANT, do not "simplify" this to a transform or a contain:
 *   The frame is centred with `inset: 0 + width + margin-inline: auto`
 *   precisely because that does NOT create a containing block for
 *   position:fixed descendants. Several games (pop-spiral's particle and
 *   score layers, its burst flashes, name-it's seed/droplet/spore particles)
 *   write viewport coordinates from getBoundingClientRect() into fixed or
 *   body-level absolute elements. Those layers must stay anchored to the
 *   real viewport or every particle lands offset by the frame's left margin.
 *   transform, filter, contain and backdrop-filter would all break that.
 *
 * Load order matters: this must be the last stylesheet on the page, since it
 * beats the games' own equal-specificity .screen / .stage rules on source
 * order alone.
 */

:root {
  /* Widest the play column ever gets. The dvh term keeps the frame
     phone-shaped rather than squat on short laptop screens: 480px at
     1080p and 900p, 448px at 800p. Height is deliberately left alone so
     the games' existing max-height media queries keep matching the real
     frame height. */
  --pk-frame-w: min(480px, 56dvh);
  --pk-frame-edge: hsla(220, 20%, 60%, 0.07);
  /* Distance from a viewport edge to the frame edge. Per-game rules use this
     to pull viewport-anchored chrome back inside the frame. */
  --pk-frame-gutter: max(0px, calc((100vw - var(--pk-frame-w)) / 2));
}

@media (min-width: 900px) {
  /* .screen: firefly-catch, grow, name-it, pop-spiral, star-weaver,
              thought-untangler
     .stage:  lantern, lumen, wisp (also drops their 100vw)
     Full-bleed siblings stay full-bleed on purpose and are not listed:
     .bg blobs, #particle-canvas, .canvas-container, and the end-of-session
     .overlay dialogs, which read correctly as centred modal cards over a
     dimmed page. The one piece of body-level chrome that did need nudging
     back inside is thought-untangler's .mute-btn, handled in that game's
     own stylesheet using --pk-frame-gutter. */
  .screen,
  .stage {
    inset: 0;
    width: var(--pk-frame-w);
    max-width: 100%;
    margin-inline: auto;
    box-shadow: 0 0 0 1px var(--pk-frame-edge);
  }

  /* Air Mode only (lantern, lumen, wisp are the only .stage games). Their
     HUD, back button, recalibrate button, guidance and mic overlay are all
     position: fixed children of .stage, so they would sit at the real
     viewport edges while the canvas sat in the frame. Containment makes
     .stage their containing block so every one of them follows the frame,
     with no per-element geometry to keep in sync.
     Safe here specifically because these three never write viewport
     coordinates into a fixed element: the only rect they read is the HUD's
     bottom edge, and .stage is flush with the viewport top, so that y value
     is unchanged. Do NOT copy this to the .screen games (see the note at the
     top of this file). */
  .stage {
    contain: layout paint;
  }
}
