/* ==========================================================================
   Loading screen
   ==========================================================================
   A full-viewport card over the staged (still-hidden) home. In the middle of
   the screen the author's vector animation plays (2026-09-27): a white ball
   bounces for as long as the real preload runs, then morphs into the horse,
   which flies up onto the masthead logo while the card lifts. No number, no
   bar — the animation is the indicator. Driven entirely by js/loader.js; the
   motion is js/loader-motion.js.

   The backdrop is a separate layer from the art so the lift can fade it
   (and the hint) WITHOUT fading the horse — the flying horse swaps for the
   real logo only once it has landed on it at the logo's size. z ladder: --z-loader.
   ========================================================================== */
.loader {
  position: fixed;
  inset: 0;
  z-index: var(--z-loader);
  display: grid;
  place-items: center;
}
.loader[hidden] { display: none; }

/* Deliberately transparent. The loader sits inside #screen, directly over the
   real site ground — the body gradient AND the room's ambient glow
   (css/home.css .room__ambient), which is not staged and so is already painted
   behind the loader. Painting an opaque gradient here reproduced only the linear
   part and hid the ambient, so the glow "appeared" when the card lifted — a
   visible seam. Showing the actual ground instead makes loading and home
   pixel-identical by construction, so the hand-off has no colour change at all.
   The staged home content (TV, tapes, readout, nav) is opacity 0 and the
   masthead logo is held hidden by .is-loading, so nothing but the ground and the
   animation is visible while it runs. Kept as an element (not removed) so the
   lift can still fade it with the hint under the flying horse; fading a
   transparent layer is a harmless no-op. */
.loader__backdrop {
  position: absolute;
  inset: 0;
  z-index: -1;
}

/* The author's 512 x 512 drawing, inline and dead centre of the screen. It
   starts invisible: js/loader.js sets the ball bouncing and then fades it up,
   so it never sits frozen while the page starts or shows the first hitchy
   frames at full strength (author, 2026-09-27). Sized in --u on desktop (384
   at 1920: a ~55px ball), fixed on smaller screens. */
.loader__art {
  display: block;
  opacity: 0;
  inline-size: 288px;
  aspect-ratio: 1;
  overflow: visible;
  /* Pure white (author, 2026-09-27) — the same white as the masthead logo it
     lands on, so the swap at the end is invisible. */
  color: #FFFFFF;
  fill: currentColor;
  transform-origin: 50% 50%;
}
@media (min-width: 1025px) {
  .loader__art { inline-size: calc(384 * var(--u)); }
}

/* Surfaced only when the load is dragging (~8s). Held below the animation so
   it never pushes the art off centre. Faded in from JS via the toast token,
   so it starts fully transparent. */
.loader__hint {
  position: absolute;
  inset-inline: 0;
  inset-block-start: calc(50% + 170px);
  margin: 0;
  opacity: 0;
  font: var(--fw-mono) var(--fs-body)/1.5 var(--font-mono);
  letter-spacing: var(--ls-mono-ui);
  text-align: center;
  color: var(--color-text);
}
.loader__hint[hidden] { display: none; }

/* The lift, run under the flight (modal exit): the backdrop and the hint fade
   while the sprite — untouched here — is moved onto the logo by JS. */
.loader--lifting .loader__backdrop,
.loader--lifting .loader__hint {
  opacity: 0;
  transition: opacity var(--motion-modal-exit);
}

/* The masthead logo is held invisible while the loader owns the screen, so it
   cannot show through next to the flying horse; js/loader.js clears this class
   once the horse has landed on it, then fades the horse away. Set on
   <html>, so any failure path that removes the class (or never adds it) leaves
   the logo visible. */
.is-loading .masthead__logo { opacity: 0; }

/* Before the first paint. index.html's head script marks the page before any
   of it is drawn — the site's scripts are modules and only run after the
   first paint, which is what used to flash the finished home screen before
   the loader (or the entrance) hid it again:
     is-booting   the home pieces the entrance brings in stay hidden until
                  js/main.js has staged them (it drops the class right after);
     no-loader    a visit that will not show the loader (returning session,
                  ?skiploading, a case-study link) does not flash the ball;
     boot-work    a case-study link does not flash the home screen before the
                  router draws the page.
   The head script clears all of it after 10s if the modules never run, so a
   failure can only leave the page visible. */
.is-booting #viewHome .plane--tv,
.is-booting #viewHome .tape,
.is-booting #viewHome .readout,
.is-booting #viewHome .nav__link { opacity: 0; }
.no-loader #loader { display: none; }
.boot-work #viewHome { visibility: hidden; }
