/* eZephyr v2 — journey engine layout.
 *
 * Two layouts share one DOM:
 *   - Stacked (default, no JS, reduced motion, narrow screens): scenes flow
 *     vertically, each with its own strip of ground.
 *   - Journey (html.is-journey, set by js/journey.js): one pinned viewport;
 *     vertical scroll moves a single horizontal track of scenes.
 *
 * All artwork is placed in "world units": the legacy 645px stage, ground line
 * at y=618, underground strip 645–795. One world unit = var(--a) CSS px.
 */

.journey, .scene { --a: calc(var(--s) * 1px); }
.scene { --u: 1px; } /* copy unit: real px in stacked mode */

/* ---------- Generic art placement (both layouts) ---------- */
.art {
  position: absolute;
  left: calc(var(--x, 0) * var(--a));
  bottom: calc(var(--b, 27) * var(--a));
  width: calc(var(--w) * var(--a));
  height: auto;
  margin: 0;
}
.art--top { bottom: auto; top: calc(var(--y, 0) * var(--a)); }

.z-landmark { z-index: 1; }
.bird { z-index: 2; }
.z-vehicle-back { z-index: 2; }
.z-tree { z-index: 3; }
.z-vehicle { z-index: 4; }
.z-bench, .z-person { z-index: 6; }

/* Ground pieces (used by the shared .ground and the per-scene .scene__ground) */
.land, .wave, .underground { position: absolute; left: 0; display: block; }
.land {
  top: 0;
  width: 100%;
  height: calc(28 * var(--a));
  background: url('../assets/environment/land.png') repeat-x 0 0 / auto calc(28 * var(--a));
  z-index: 5;
}
.wave {
  left: calc(-50 * var(--a));
  width: calc(100% + 100 * var(--a));
  height: calc(27 * var(--a));
}
.wave--light {
  top: calc(15 * var(--a));
  background: url('../assets/environment/wave-light.png') repeat-x 0 0 / auto calc(27 * var(--a));
  z-index: 6;
}
.wave--dark {
  top: calc(18 * var(--a));
  background: url('../assets/environment/wave-dark.png') repeat-x 0 0 / auto calc(27 * var(--a));
  z-index: 7;
}

/* ================= Stacked layout (default) ================= */
.journey__sky,
.journey__clouds,
.ground,
[data-journey-only] { display: none; }

.scene {
  position: relative;
  overflow: hidden;
  padding-bottom: calc(18 * var(--a)); /* room for the waves below the stage */
  scroll-margin-top: var(--header-h);
  background: var(--sky-bg);
}
/* Stacked scale without JS (js/journey.js sets it from the screen width): readable on phones. */
html:not(.is-journey) .scene { --s: 0.6; }
@media (max-width: 599px) { html:not(.is-journey) .scene { --s: 0.48; } }
@media (min-width: 1000px) { html:not(.is-journey) .scene { --s: 1; } }
/* The stage is centred on the scene's landmark (--scene-focus, in world units); the scene
 * crops the rest. With motion allowed, js/journey.js pans the street past it. */
.scene__stage {
  position: relative;
  width: calc(var(--stage-w) * var(--a));
  height: calc(645 * var(--a));
  margin-left: calc(50% - var(--scene-focus, 0) * var(--a));
}
/* The top of the stage is open sky (clouds, birds): tuck it under the copy. */
html:not(.is-journey) .scene__stage { margin-top: calc(-190 * var(--a)); }
/* The scene's own strip of street runs well past both screen edges (the scene
 * crops it), so the street never runs out while the stage pans. */
.scene__ground {
  position: absolute;
  top: calc(618 * var(--a));
  left: calc(var(--scene-focus, 0) * var(--a) - 100vw);
  width: 200vw;
  height: calc(45 * var(--a));
}

/* ================= Journey layout ================= */
/* The header floats over the pinned stage as a solid band of the sky's own
 * colour (--sky is sampled from the sky artwork's edge). Artwork near the top
 * of the stage passes beneath it instead of showing through the navigation.
 * The band slims on short windows (it was sized to clear the client logos, which
 * left the journey in Milestone 5B; kept so the composition does not move). */
.is-journey { --journey-header-h: min(var(--header-h), calc(51px * var(--s))); }
.is-journey .site-header {
  position: fixed;
  left: 0;
  right: 0;
  height: var(--journey-header-h);
  background: var(--sky);
  box-shadow: 0 1px 0 rgba(49, 49, 50, 0.12);
}
.is-journey .site-nav a { padding-block: 0; }
.is-journey .explore-link { min-height: min(36px, calc(var(--journey-header-h) - 4px)); padding-block: 0; }

.is-journey .journey {
  position: relative;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  overflow: clip; /* stops focus/anchor scrolling from shifting the stage */
}

.is-journey .journey__sky { display: block; position: absolute; inset: 0; }
.sky { position: absolute; inset: 0; background: var(--sky-bg); }

.is-journey .journey__world {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: calc(795 * var(--a));
}

.is-journey .journey__clouds {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: calc(2700 * var(--a));
  height: calc(645 * var(--a));
  will-change: transform;
}

.is-journey .journey__track {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: flex-start;
  width: calc(var(--track-w, 2890) * var(--a));
  height: 100%;
  will-change: transform;
}

.is-journey .scene {
  --u: var(--a);
  flex: none;
  width: calc(var(--scene-w, var(--stage-w)) * var(--a));
  height: calc(645 * var(--a));
  padding: 0;
  overflow: visible;
  background: none;
}
.is-journey .scene__stage {
  position: absolute;
  top: 0;
  left: calc((var(--scene-w, var(--stage-w)) - var(--stage-w)) / 2 * var(--a));
  width: calc(var(--stage-w) * var(--a));
  height: 100%;
  margin: 0;
}
.is-journey .scene__ground { display: none; }
.is-journey [data-journey-only] { display: block; }

/* Shared, continuous ground under the whole track. */
.is-journey .ground {
  display: block;
  position: absolute;
  top: calc(618 * var(--a));
  left: 0;
  width: 100%;
  height: calc(177 * var(--a));
}
.underground {
  top: calc(27 * var(--a));
  width: 100%;
  height: calc(150 * var(--a));
  background: url('../assets/environment/underground.webp') repeat-x 0 0 / auto calc(150 * var(--a));
  z-index: 4;
  overflow: hidden;
}
.train {
  position: absolute;
  top: calc(72 * var(--a));
  left: 0;
  width: calc(792 * var(--a));
  height: auto;
}

/* ================= Lighting: time of day =================
 * Each preset sets the sky (--sky-bg), a tint over the street's artwork (--shade)
 * and cloud opacity (--clouds). The visitor's device clock picks one preset for the
 * whole journey (js/daypart.js sets html[data-daylight]); it overrides every scene's own
 * data-time, so all scenes share one light and scrolling never changes it. A scene's
 * data-time only lights it when js/daypart.js has not run (no JS). */
.journey,
[data-time="morning"],
[data-time="late-morning"],
html[data-daylight="morning"] .journey,
html[data-daylight="morning"] .journey [data-time],
html[data-daylight="late-morning"] .journey,
html[data-daylight="late-morning"] .journey [data-time] {
  --sky-bg: var(--sky-light) url('../assets/environment/sky-day.webp') center bottom / cover no-repeat;
  --shade: rgba(0, 0, 0, 0);
  --clouds: 1;
}
[data-time="afternoon"],
html[data-daylight="afternoon"] .journey,
html[data-daylight="afternoon"] .journey [data-time] {
  --sky-bg: linear-gradient(rgba(255, 222, 150, 0.22), rgba(255, 222, 150, 0.22)), var(--sky-light) url('../assets/environment/sky-day.webp') center bottom / cover no-repeat;
  --shade: rgba(255, 214, 140, 0.06);
  --clouds: 1;
}
[data-time="golden"],
html[data-daylight="golden"] .journey,
html[data-daylight="golden"] .journey [data-time] {
  --sky-bg: linear-gradient(to bottom, #8fd3ea 0%, #ffe3a1 58%, #ffbe6a 100%);
  --shade: rgba(255, 166, 64, 0.14);
  --clouds: 0.9;
}
[data-time="sunset"],
html[data-daylight="sunset"] .journey,
html[data-daylight="sunset"] .journey [data-time] {
  --sky-bg: linear-gradient(to bottom, #8e94c8 0%, #f2a98f 60%, #ffd28a 100%);
  --shade: rgba(198, 86, 96, 0.18);
  --clouds: 0.75;
}
[data-time="dusk"],
html[data-daylight="dusk"] .journey,
html[data-daylight="dusk"] .journey [data-time] {
  --sky-bg: linear-gradient(to bottom, #262f6b 0%, #5f5597 52%, #d98d84 100%);
  --shade: rgba(38, 40, 108, 0.34);
  --clouds: 0.5;
}
[data-time="night"],
html[data-daylight="night"] .journey,
html[data-daylight="night"] .journey [data-time] {
  --sky-bg:
    radial-gradient(circle at 80% 16%, #fffaf0 0 26px, rgba(255, 250, 240, 0.14) 27px 46px, transparent 47px),
    radial-gradient(circle, #fff 0 1.2px, transparent 1.6px) 0 0 / 190px 150px repeat,
    radial-gradient(circle, rgba(255, 255, 255, 0.7) 0 1px, transparent 1.4px) 70px 60px / 230px 170px repeat,
    linear-gradient(to bottom, #050b26 0%, #101b45 65%, #22306a 100%);
  --shade: rgba(6, 12, 44, 0.52);
  --clouds: 0.25;
}
/* First light: a sunrise — night blue overhead, violet, then coral and gold at the horizon
 * (about two thirds down the screen in the journey). Deep enough overhead for white type. */
[data-time="first-light"],
html[data-daylight="first-light"] .journey,
html[data-daylight="first-light"] .journey [data-time] {
  --sky-bg: linear-gradient(to bottom, #0f1844 0%, #232c6c 30%, #54468c 48%, #b8708f 58%, #f39a7a 64%, #ffcf91 72%, #ffe0a8 100%);
  --shade: rgba(40, 30, 90, 0.26);
  --clouds: 0.3;
}

/* The tint sits over the artwork (z 1–7) and under lit things (9) and copy (10).
 * One flat tint per scene; with the device-time light every scene has the same one,
 * so the street is evenly lit from end to end. */
.scene__stage::after,
.is-journey .scene::after {
  content: '';
  position: absolute;
  left: calc(var(--scene-focus, 0) * var(--a) - 100vw);
  top: 0;
  width: 200vw;
  height: calc(618 * var(--a));
  z-index: 7;
  pointer-events: none;
  background: var(--shade);
  /* Full strength on the street, fading out into the upper sky (the sky has its own light). */
  -webkit-mask-image: linear-gradient(to bottom, transparent 10%, #000 45%);
  mask-image: linear-gradient(to bottom, transparent 10%, #000 45%);
}
.is-journey .scene__stage::after { content: none; }
.is-journey .scene::after {
  left: 0;
  width: 100%;
}
/* The shared ground (land, sea wall, underground) under the same light. */
.is-journey .ground::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 8;
  pointer-events: none;
  background: var(--shade);
}
.is-journey .journey__clouds { opacity: var(--clouds); }
/* Clouds drawn in a scene (the opening's) thin out with the light too: the tint fades out
 * towards the top of the sky, so it does not reach them. */
html[data-daylight] .scene .cloud { opacity: var(--clouds); }

/* Lights: lamps, headlights, lit windows (data-light="night") come on at dusk;
 * birds and other daytime-only life (data-light="day") go home. */
[data-light="night"] { display: none; z-index: 9; }
[data-time="dusk"] [data-light="night"],
[data-time="night"] [data-light="night"] { display: block; }
[data-time="dusk"] [data-light="day"],
[data-time="night"] [data-light="day"] { display: none; }
/* data-light="evening": floodlights and the like, on from golden hour. */
[data-light="evening"] { display: none; }
[data-time="golden"] [data-light="evening"],
[data-time="sunset"] [data-light="evening"],
[data-time="dusk"] [data-light="evening"],
[data-time="night"] [data-light="evening"] { display: block; }
/* Device-time light (js/daypart.js): the lights are on or off in every scene at once. */
html[data-lights="on"] [data-light="night"],
html[data-lights="on"] [data-light="evening"],
html[data-lights="off"] [data-light="day"] { display: block; }
html[data-lights="off"] [data-light="night"],
html[data-lights="off"] [data-light="evening"],
html[data-lights="on"] [data-light="day"] { display: none; }

/* Stacked dusk and night scenes: copy sits on a paper card so it stays legible on the dark sky.
 * (The finale's copy has its own night-blue band.) */
html:not(.is-journey):not([data-lights]) [data-time="dusk"] > .scene__copy,
html:not(.is-journey):not([data-lights]) [data-time="night"] > .scene__copy,
html:not(.is-journey)[data-lights="on"] .scene > .scene__copy:not(.finale-copy) {
  margin-top: 16px;
  border-radius: 8px;
  background: rgba(255, 250, 240, 0.94);
}

/* Pause animation: GIF birds cannot be paused, so they rest out of sight. */
.is-motion-paused .bird { visibility: hidden; }

/* The travelling bus's headlights (Milestone 5D): drawn over the bus in the journey, on
 * for the whole ride when the device-time light has the lights on (the drawing is loaded
 * by js/lighting.js). Never shown when stacked. */
.bus-lights { display: none; opacity: 0; }
.is-journey .bus-lights { display: block; }
html.is-journey[data-lights="on"] .bus-lights { opacity: 1; }

/* Evening and night: the header's band is paper, like the route's, rather than a day-sky
 * blue over the dark sky. */
html[data-lights="on"] .site-header { background: rgba(255, 250, 240, 0.96); }

/* The bus and its headlights ride in one layer (it was lifted onto the flyover's deck until 2026-10-23). */
.bus-ride { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
