/* ── The void ───────────────────────────────────────────────── */
#universe-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

/*
 * The air of the current region. It is a masked colour rather than a gradient
 * so it can transition smoothly as the camera crosses from one region of the
 * universe into the next.
 */
.atmosphere {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-color: var(--air);
  -webkit-mask-image: radial-gradient(ellipse 120% 85% at 50% 45%, #000, transparent 68%);
  mask-image: radial-gradient(ellipse 120% 85% at 50% 45%, #000, transparent 68%);
  transition: background-color 1.6s var(--ease-in-out);
}

.atmosphere::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: var(--air-warm);
  -webkit-mask-image: radial-gradient(ellipse 90% 60% at 50% 118%, #000, transparent 72%);
  mask-image: radial-gradient(ellipse 90% 60% at 50% 118%, #000, transparent 72%);
  transition: background-color 1.6s var(--ease-in-out);
}

/* ── Intro ──────────────────────────────────────────────────── */
#intro {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: grid;
  place-content: center;
  background: var(--void);
  transition: opacity var(--speed-slow) var(--ease-out);
}

#intro.is-leaving {
  opacity: 0;
  pointer-events: none;
}

.intro__mark {
  display: flex;
  gap: 0.5em;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.4rem, 3.4vw, 2.4rem);
  letter-spacing: 0.4em;
  color: var(--text-strong);
}

.intro__mark span {
  opacity: 0;
}

#intro.is-running .intro__mark span {
  animation: intro-in 1s var(--ease-out) forwards;
}

#intro.is-running .intro__mark span:nth-child(2) { animation-delay: 0.1s; }
#intro.is-running .intro__mark span:nth-child(3) { animation-delay: 0.2s; }
#intro.is-running .intro__mark span:nth-child(4) { animation-delay: 0.3s; }
#intro.is-running .intro__mark span:nth-child(5) { animation-delay: 0.4s; }

@keyframes intro-in {
  to {
    opacity: 1;
  }
}

/* ── The world ──────────────────────────────────────────────── */
/*
 * Places are fixed layers. Scrolling never moves them up the page — the camera
 * changes their distance and their lateral offset, and the shared perspective
 * below must match FOCAL in js/universe/constants.js so the HTML and the
 * starfield are projected through one lens.
 */
.world {
  position: fixed;
  inset: 0;
  z-index: 2;
  perspective: var(--focal);
  perspective-origin: 50% 50%;
  pointer-events: none;
}

.region {
  display: contents;
}

.place {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  transform-style: preserve-3d;
  visibility: hidden;
}

.place.is-present {
  visibility: visible;
}

.place__inner {
  width: var(--shell);
  max-height: 100vh;
  opacity: 0;
  pointer-events: auto;
  will-change: transform, opacity, filter;
  transform-style: preserve-3d;
}

.place__inner--wide {
  width: min(1320px, 92vw);
}

/* Nothing behind the camera should intercept a click. */
.place:not(.is-present) .place__inner {
  pointer-events: none;
}

#scroll-track {
  position: relative;
  width: 100%;
  pointer-events: none;
}

/* ── Continue control ───────────────────────────────────────── */
.region-skip {
  position: fixed;
  right: clamp(1rem, 4vw, 3rem);
  bottom: clamp(1.2rem, 4vh, 2.6rem);
  z-index: 60;
  display: inline-flex;
  align-items: baseline;
  gap: 0.55rem;
  font-size: 0.66rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-faint);
  transition: color var(--speed-fast) ease;
}

.region-skip::after {
  content: "";
  width: 26px;
  height: 1px;
  background: var(--hairline-strong);
  transition: width var(--speed) var(--ease-out);
}

.region-skip:hover {
  color: var(--text);
}

.region-skip:hover::after {
  width: 40px;
}

.region-skip__target {
  color: var(--violet);
}

/* display on the base rule would otherwise defeat the hidden attribute. */
.region-skip[hidden] {
  display: none;
}

html.has-overlay .region-skip,
html.has-overlay #universe-nav {
  opacity: 0;
  pointer-events: none;
}

/* While a record is open the world itself steps back: the stars stay, but the
   words of the place behind must not read through the text in front.
   Opacity, not visibility — a visible child would override the latter. */
html.has-overlay .world {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--speed) ease;
}

/* A fullscreen photograph quietens the scene without erasing it: the viewer
   should still feel attached to the place the photograph came from. */
html.has-lightbox .world {
  opacity: 0.3;
  pointer-events: none;
  transition: opacity var(--speed) ease;
}
