:root {
  /* Frozen palette — printed mid-century comic panel, flat inks only. */
  --ink: #1a1a1a;
  --sky-night: #14213d;
  --sky-horizon: #293a5c;
  --star: #f4ead6;
  --planet: #47526e;
  --hull: #bb8a3c;
  --hull-dark: #8d6830;
  --nose: #2a3d61;
  --stripe: #a4453a;
  --glass: #86a5b2;
  --suit: #66703f;
  --skin: #e2c6a4;
  --boot: #7a5a3c;
  --desk: #8d6238;
  --desk-edge: #63432a;
  --desk-grain: #75512f;
  --laptop: #b6bec6;
  --screen: #232e3a;
  --stroke-w: 6;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--sky-night);
  overflow: hidden;
}

#scene {
  display: block;
  width: 100vw;
  height: 100dvh;
  /* One inherited stroke for the whole drawing: uniform weight everywhere.
     Children only ever override the fill, or set stroke="none". */
  fill: none;
  stroke: var(--ink);
  stroke-width: var(--stroke-w);
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* The whole composition, zoomed as a unit on narrow viewports — see the media
   query at the foot of this file. The origin is the centre of the frame, so
   the zoom is easy to reason about: scale first, then nudge sideways to put
   the crop where the action is. */
#stage { transform-box: view-box; transform-origin: 800px 450px; }

/* Rig transform origins, so Task 5 can bank the ship and swing the limbs. */
#ship, #figure, #fig-arm-l, #fig-arm-r,
#ship-hatch, #ship-ramp, #ship-legs, #ship-flame, #screen-cursor {
  transform-box: fill-box;
}
#fig-arm-l, #fig-arm-r { transform-origin: 50% 10%; }  /* shoulder */
#ship { transform-origin: 50% 50%; }                   /* bank about centre */
#ship-hatch { transform-origin: 0% 50%; }              /* hinge on its left edge */

/* Hips and knees, pinned in user space rather than to a percentage of a
   bounding box. Each leg group now contains a shin that swings inside it, so
   its box changes every frame and a fill-box origin would crawl — the same
   trap #figure documents further down. These are the joints as drawn: hips on
   the line y = 660, knees on y = 679. */
#fig-leg-l, #fig-leg-r, #fig-shin-l, #fig-shin-r { transform-box: view-box; }
#fig-leg-l  { transform-origin: 595px 660px; }
#fig-leg-r  { transform-origin: 621px 660px; }
#fig-shin-l { transform-origin: 595px 679px; }
#fig-shin-r { transform-origin: 620px 679px; }
/* The ramp is drawn deployed, and extends by scaling along its own long axis
   about the hatch sill. Pin that pivot to the sill in user space: a fill-box
   percentage would move as the plank scales. */
#ship-ramp { transform-box: view-box; transform-origin: 305px 592px; }
#ship-flame { transform-origin: 50% 0%; opacity: 0; }  /* grows downward, off at rest */
#ship-legs { transform-origin: 50% 0%; }               /* gear stows up into the hull */

/* The poster — no JS, or prefers-reduced-motion — is the authored landed pose,
   and that pose has the ramp DOWN, because deployed is the ramp's true drawn
   geometry and shrinking it back is what made it read as a stretched strut.
   A shut hatch above a deployed ramp is then the one thing in the poster that
   cannot be true at once, so the RESTING hatch is the open one. Every rig
   animation runs fill: both across the whole master duration, so the keyframed
   scaleX(1) at offset 0 overrides this the instant main.js creates them; this
   value is only ever seen when it does not. */
#ship-hatch { transform: scaleX(0.06); }

/* The figure is mirrored when it turns around, so its transform must NOT be
   measured against its own bounding box: the swinging limbs change that box
   every frame and the mirror centre would crawl. Pin it to a fixed point in
   user space instead — the middle of the standing figure. */
#figure { transform-box: view-box; transform-origin: 606px 640px; }

/* Hide the authored landed pose until main.js has created the animations, so
   the loop never flashes its final frame first. Removed by main.js in both the
   animated and the reduced-motion branch. With JS disabled the class is never
   added, so the poster shows. */
.js-loading #scene { visibility: hidden; }

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

/* Portrait and squarer viewports — phones, and tablets held upright. The scene
   is composed 16:9, so "meet" fits it by width there and the artwork lands as a
   thin band; the backdrop bleed (see index.html) fills the rest of the screen
   with sky and desk, so the framing reads as a tall window on a wide world
   rather than as letterboxing. This zoom is what then makes the ship, the
   figure and the screen legible at phone size.
   Below 16:9 the fit is always width-limited, so the crop is the same in scene
   units at every such viewport: 1600 / 1.35 = 1185 units wide, and the 110-unit
   nudge centres it on x = 719. That leaves the window at x 127..1311 — about
   60 units of air outside the landing pad at 186 and outside the far corner of
   the laptop at 1250. The flight arc simply runs off the sides, which is what
   an arc does. The 180-unit drop is composition, not safety: the bleed means
   there is no edge to protect, and putting the desk line about two thirds of
   the way down spends the tall screen on the sky the ship flies through rather
   than on empty desk. */
@media (max-aspect-ratio: 1 / 1) {
  #stage { transform: translate(110px, 180px) scale(1.35); }
}
