* {
  box-sizing: border-box;
}

/* The one palette both sides read from. The WebGL sky writes these custom
   properties from its own day/night parameters, so the page chrome and the
   scene can never drift apart. Values here are the daylight defaults, used
   before the scene has had a chance to report in. */
:root {
  color-scheme: light;
  font-family: system-ui, sans-serif;

  --page-bg: #f8f6f5;
  --accent: #e7162e;
  --fallback-fg: #a60c2b;

  background: var(--page-bg);
}

:root[data-sky='night'] {
  color-scheme: dark;

  --page-bg: #0c0a17;
  --accent: #ff7189;
  --fallback-fg: #ffa3b5;
}

/* Insurance for the case where the boot script in `index.html` never runs --
   scripting off, or a CSP hash that no longer matches -- and the page would
   otherwise sit on the daylight palette with no way out of it. The OS theme is
   a worse guess than the clock, but a dark page in daylight is a preference
   ignored, while a white one at night is the thing being fixed. Scoped to
   `:not([data-sky])` so it only applies before anything has decided: the
   moment the script or the scene sets the attribute, the real palettes above
   take over, including an explicit daylight one under a dark OS theme. */
@media (prefers-color-scheme: dark) {
  :root:not([data-sky]) {
    color-scheme: dark;

    --page-bg: #0c0a17;
    --accent: #ff7189;
    --fallback-fg: #ffa3b5;
  }
}

html,
body {
  min-width: 20rem;
  min-height: 100%;
  margin: 0;
}

/* Nothing on this page is meant to be read or selected -- the only text is the
   hidden status line and the fallback message -- and the page element takes the
   pointer events for the scene behind it. Without this, a drag over the rocket
   starts a selection and a fast double click selects a word, which is enough
   for the browser to pop its translate bubble over the sky. Set on the body
   rather than on `.page`, so a click that lands outside the grid is covered
   too; the script also cancels `selectstart`, because a double click can start
   a selection from a range the CSS never sees. */
body {
  min-height: 100svh;
  overflow-x: hidden;
  overflow-y: auto;
  background: var(--page-bg);
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* The page is exactly one viewport tall and there is nothing on it to scroll
   to, but a touch drag was still being claimed by the browser as a pan: the
   first move fired `pointercancel`, the stream of `pointermove` events stopped
   there, and the parallax -- which is driven by those events -- was dead on a
   phone no matter how you dragged. Taking the gesture back is what makes touch
   drag work at all, and it also stops the pull-to-refresh and the address bar
   sliding about under a drag across the sky. */
html,
body {
  touch-action: none;
  overscroll-behavior: none;
}

/* The sky is the whole viewport and sits behind everything. It has to be one
   canvas with the rocket rather than a second one underneath: objects only
   refract through the gum if they are in the same scene. */
.sky-canvas {
  position: fixed;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  cursor: default;
  user-select: none;
}

/* The only affordance left, now that there is no button: the cursor changes
   only where the raycast actually lands on the rocket. */
body.is-over-rocket .sky-canvas {
  cursor: pointer;
}

body.has-webgl-error .sky-canvas {
  visibility: hidden;
}

.page {
  position: relative;
  display: grid;
  min-height: 100svh;
  place-items: center;
  padding: 1.5rem;
  padding:
    max(1.5rem, env(safe-area-inset-top))
    max(1.5rem, env(safe-area-inset-right))
    max(1.5rem, env(safe-area-inset-bottom))
    max(1.5rem, env(safe-area-inset-left));
}

/* Not an interaction surface any more -- picking is a raycast against the 3D
   hull, and the reaction to it is geometry, not DOM. All that is left here is
   somewhere to put the fallback message, sized to roughly the rocket so it
   lands where the rocket would have been. It takes no pointer events. */
.rocket-stage {
  position: relative;
  display: grid;
  width: min(22rem, 70vw, 44svh);
  aspect-ratio: 1;
  place-items: center;
  pointer-events: none;
}

.webgl-fallback {
  position: absolute;
  max-width: 14rem;
  color: var(--fallback-fg);
  font-size: 0.875rem;
  font-weight: 650;
  line-height: 1.4;
  opacity: 0;
}

.rocket-stage.has-webgl-error .webgl-fallback {
  opacity: 1;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

@media (forced-colors: active) {
  .webgl-fallback {
    color: CanvasText;
  }
}
