/* ==========================================================================
   PHOTO STORY → 02 · EXPLORATION
   One pinned stage: documentary stills are placed onto a dark canvas while the navigation
   arrow from the documentary's opening travels on past them; the last one takes over, the view
   pushes into it and it fades around the arrow, which comes to rest and becomes the globe.
   All motion is set from scroll position by initExplore() in js/main.js.
   ========================================================================== */

/* Scroll length of each phase, in viewport heights:
   --p  the stills arrive one by one
   --a  the last still fills the screen, the view pushes into it, it fades; the arrow comes to rest
        and becomes the globe; intro
   --b  the globe turns region by region, visited places fill white
   --c  the globe settles into its final composition, the count appears, short hold
   --d  the Earth collapses into a point and becomes the navigation arrow (css/journey.css continues) */
.explore {
  --p: 220;
  --a: 130;
  --b: 160;
  --c: 55;
  --d: 70;
  position: relative;
  height: calc((100 + var(--p) + var(--a) + var(--b) + var(--c) + var(--d)) * 1vh);
  height: calc((100 + var(--p) + var(--a) + var(--b) + var(--c) + var(--d)) * 1svh);
  background: var(--bg);
}

.explore__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
}

/* ---------- Photo story ---------- */

/* Where the final still sits before it takes over: centre (as a fraction of the screen)
   and size (fraction of the full screen; it keeps the screen's shape). Centred: the last
   photograph is the story's last big moment. */
.story {
  --final-x: 0.5;
  --final-y: 0.52;
  --final-scale: 0.5;
  position: absolute;
  inset: 0;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}

/* Each still: position (--x, --y from the top-left of the screen), width (--w, in vw),
   shape (--ar), and a height cap (--hmax, in vh) so it also fits wide/short screens. */
.story__photo {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: min(calc(var(--w) * 1vw), calc(var(--hmax) * 1svh * var(--ar)));
  aspect-ratio: var(--ar);
  overflow: hidden;
  background: var(--bg-frame);
  box-shadow: 0 28px 60px -34px rgba(0, 0, 0, 0.75);
  opacity: 0;
  will-change: transform, opacity;
}

.story__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Darkens older stills a little as newer ones land on top */
.story__dim {
  position: absolute;
  inset: 0;
  background: var(--bg);
  opacity: 0;
  pointer-events: none;
}

/* Desktop composition: a loose frame of stills around an open centre,
   which the final still fills. */
.story__photo--1 { --x: 6%;  --y: 18%; --w: 40; --hmax: 52; --ar: 3 / 2;  z-index: 1; }
.story__photo--2 { --x: 40%; --y: 11%; --w: 17; --hmax: 40; --ar: 4 / 5;  z-index: 2; }
.story__photo--3 { --x: 63%; --y: 14%; --w: 30; --hmax: 32; --ar: 16 / 9; z-index: 3; }
.story__photo--4 { --x: 14%; --y: 56%; --w: 15; --hmax: 36; --ar: 3 / 4;  z-index: 4; }
.story__photo--5 { --x: 70%; --y: 57%; --w: 24; --hmax: 30; --ar: 3 / 2;  z-index: 5; }

/* The final still is a full-screen layer, scaled down into the composition by JS
   (and by the static rule further down). */
.story__photo--final {
  inset: 0;
  left: 0;
  top: 0;
  width: auto;
  aspect-ratio: auto;
  z-index: 6;
  box-shadow: none;
  transform-origin: 50% 50%;
}

/* Pre-blurred copy that fades in: far cheaper than animating a blur filter */
.story__soft {
  position: absolute;
  inset: 0;
  opacity: 0;
  will-change: opacity;
}

.story__soft img {
  filter: blur(18px) saturate(0.7);
  transform: scale(1.08);           /* hides the soft edges the blur creates */
}

.story__soft.is-missing::before { content: none; }

.story__shade {
  position: absolute;
  inset: 0;
  z-index: 7;
  background: var(--bg);
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
}

.story__label {
  position: absolute;
  left: var(--gutter);
  bottom: clamp(22px, 4.5vh, 44px);
  z-index: 8;
  max-width: none;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--fg-dim);
  opacity: 0;
}

.story__label span { margin-inline: 0.9em; }

/* ---------- The arrow from the documentary's opening ----------
   It walked to the monument in Kyiv; here it travels on through the photographs, a faint trail
   behind it, until it becomes the globe. Fixed to the screen (it carries on while the page moves
   from the opening's stage to this one); shown and placed by initExplore() in js/main.js. */
.thread {
  position: fixed;
  inset: 0;
  z-index: 40;                  /* over the photographs, under the header (50) */
  pointer-events: none;
  visibility: hidden;
}

.thread.is-on { visibility: visible; }

.thread__trail {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.thread .route-arrow { opacity: 1; }

.explore.is-static .thread,
html:not(.js) .thread { display: none; }

/* ---------- Globe layer ---------- */

.explore__world {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.explore__globe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* ---------- Text ---------- */

.explore__intro,
.explore__count {
  position: absolute;
  left: var(--gutter);
  top: 50%;
  z-index: 1;
  max-width: min(30rem, 34vw);
  opacity: 0;
  will-change: opacity, transform;
}

.explore__intro { transform: translateY(-50%); }

.explore__title {
  margin-top: 22px;
  font-size: clamp(2.5rem, 5.2vw, 5.5rem);
  font-weight: 300;
  letter-spacing: -0.035em;
  line-height: 0.98;
  color: var(--fg);
}

.explore__lede {
  margin-top: clamp(20px, 2vw, 30px);
  max-width: 34ch;
  font-size: clamp(1rem, 1.2vw, 1.125rem);
  font-weight: 300;
  color: var(--fg-muted);
}

.explore__count { transform: translateY(-50%); }

/* The number rises out of a mask, like the hero title */
.explore__number {
  display: block;
  overflow: hidden;
  padding-bottom: 0.02em;
  font-size: clamp(7rem, 16vw, 15.5rem);
  font-weight: 200;
  letter-spacing: -0.055em;
  line-height: 0.86;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}

.explore__number > span {
  display: inline-block;
  transform: translateY(100%);
  will-change: transform;
}

.explore__count-label {
  display: block;
  margin-top: clamp(18px, 2vw, 28px);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--fg);
}

.explore__coda {
  margin-top: 14px;
  max-width: 30ch;
  font-size: 0.9375rem;
  font-weight: 300;
  color: var(--fg-muted);
}

/* ---------- Phones (and tall portrait screens) ---------- */

@media (max-width: 760px), (max-aspect-ratio: 4/5) {
  .explore {
    --p: 200;
    --a: 120;
    --b: 130;
    --c: 48;
    --d: 64;
  }

  /* Phone composition: stills cascade down the screen, overlapping more,
     each still wide enough to read; the final one lands tall in the middle. */
  .story {
    --final-x: 0.5;
    --final-y: 0.53;
    --final-scale: 0.62;
  }

  .story__photo--1 { --x: 6%;  --y: 12%; --w: 80; --hmax: 30; --ar: 3 / 2; }
  .story__photo--2 { --x: 48%; --y: 27%; --w: 46; --hmax: 30; --ar: 4 / 5; }
  .story__photo--3 { --x: 4%;  --y: 45%; --w: 70; --hmax: 22; --ar: 16 / 9; }
  .story__photo--4 { --x: 55%; --y: 57%; --w: 40; --hmax: 28; --ar: 3 / 4; }
  .story__photo--5 { --x: 7%;  --y: 69%; --w: 60; --hmax: 22; --ar: 3 / 2; }

  .story__label span { margin-inline: 0.6em; }

  .explore__intro,
  .explore__count {
    left: var(--gutter);
    right: var(--gutter);
    max-width: none;
    transform: none;
  }

  .explore__intro { top: calc(var(--header-h) + 20px); }
  .explore__title { font-size: clamp(2.4rem, 11vw, 4rem); margin-top: 16px; }
  .explore__lede { margin-top: 14px; }

  .explore__count { top: auto; bottom: max(40px, 6svh); }
  .explore__number { font-size: clamp(5.5rem, 30vw, 9rem); }
  .explore__count-label { margin-top: 14px; }
}

/* ---------- Static version: reduced motion, no JS, or globe unavailable ----------
   No pinning and no long scroll: the finished photo composition, then one screen
   with the finished globe, intro and count. */

.explore.is-static,
html:not(.js) .explore { height: auto; }

.explore.is-static .explore__stage,
html:not(.js) .explore__stage {
  position: relative;
  height: auto;
  overflow: visible;
}

.explore.is-static .story,
html:not(.js) .story {
  position: relative;
  height: 100vh;
  height: 100svh;
  min-height: 560px;
  overflow: hidden;
}

.explore.is-static .story__photo,
html:not(.js) .story__photo { opacity: 1; }

.explore.is-static .story__photo--final,
html:not(.js) .story__photo--final {
  transform:
    translate(calc((var(--final-x) - 0.5) * 100%), calc((var(--final-y) - 0.5) * 100%))
    scale(var(--final-scale));
}

.explore.is-static .story__label,
html:not(.js) .story__label { opacity: 1; }

.explore.is-static .explore__world,
html:not(.js) .explore__world {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
}

.explore.is-static .explore__intro,
.explore.is-static .explore__count,
html:not(.js) .explore__intro,
html:not(.js) .explore__count { opacity: 1; }

.explore.is-static .explore__number > span,
html:not(.js) .explore__number > span { transform: none; }

.explore.is-static .explore__intro,
html:not(.js) .explore__intro { top: 16%; transform: none; }

.explore.is-static .explore__count,
html:not(.js) .explore__count { top: auto; bottom: 12%; transform: none; }

/* No globe at all (no JS, or it couldn't load): stack the text in normal flow */
.explore.is-fallback .explore__globe,
html:not(.js) .explore__globe { display: none; }

.explore.is-fallback .explore__world,
html:not(.js) .explore__world {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(64px, 10vw, 140px);
  padding: var(--section-y) var(--gutter);
}

.explore.is-fallback .explore__intro,
.explore.is-fallback .explore__count,
html:not(.js) .explore__intro,
html:not(.js) .explore__count { position: static; max-width: 40rem; }

@media (max-width: 760px), (max-aspect-ratio: 4/5) {
  .explore.is-static:not(.is-fallback) .explore__world { min-height: max(100svh, 960px); }
  .explore.is-static .explore__intro { top: calc(var(--header-h) + 20px); }
  .explore.is-static .explore__count { bottom: 40px; }
}
