/* ==========================================================================
   Environment: one landscape, many times of day.

   Stack (back to front)                 element
   0  sky gradient (6 crossfaded stops)  .dusk-sky--0 ... --5
   1  stars                              img[data-env=stars]
   2  upper haze                         img[data-env=haze]
   3  clouds                             img[data-env=clouds]
   4  sun (CSS)                          .dusk-sun
   5  distant mountains                  img[data-env=distant]
   6  mountain haze                      img[data-env=mountainHaze]
   7  midground mountains                img[data-env=midground]
   8  lake valley                        img[data-env=valley]
   9  foreground trees                   img[data-env=trees]
   10 foreground rocks                   img[data-env=rocks]
   11 night tint (CSS)                   .dusk-env__night
   12 city lights                        img[data-env=lights]  (above the tree ridge, see environment.php)
   13 horizon glow (CSS)                 .dusk-glow
   14 readability veils (CSS)            .environment-readability

   Image layers sit inside .dusk-env__scene, a 1672 x 941 box scaled to cover the
   screen (like object-fit: cover) so the sun, glow and lights stay registered to
   the mountains at every size. Framing per breakpoint: --horizon, --scene-x, --scene-scale.

   Performance: only opacity and transform change, and they change on the <img> itself,
   so browsers composite the decoded image directly (small GPU textures) instead of
   painting full-screen layers. Nothing here has a CSS transition: the environment
   engine is the only thing that animates these elements.
   ========================================================================== */

.dusk-env {
	--scene-ratio: 1.7768;
	--scene-scale: 1.02;
	--scene-x: 0.62;
	--scene-horizon: 0.5; /* where the ridge line sits inside the artwork */
	--horizon: 0.56; /* where that ridge should land on screen (0 top, 1 bottom) */
	z-index: var(--z-env);
	width: 100%;
	height: var(--vh-full);
	overflow: hidden;
	pointer-events: none;
	background: var(--color-night);
	contain: strict;
}

/* Homepage: a sticky stage that holds for the whole story, then releases with the
   final CTA so the footer starts below the landscape. The content is pulled up over
   it with a negative top margin (a negative margin on the stage itself would extend
   its sticky range and keep it stuck under the footer). */
.environment-stage {
	position: sticky;
	top: 0;
}

.home-experience > .home-content {
	margin-top: calc(-1 * var(--vh-full));
}

/* Inner pages: a fixed blue-hour frame behind everything. */
.environment-fixed {
	position: fixed;
	top: 0;
	left: 0;
}

/* The land fades up once decoded (main.js removes dw-env-pending). */
.dusk-env__scene {
	transition: opacity 1.1s var(--ease-out);
}

.dw-env-pending .dusk-env__scene {
	opacity: 0;
	/* Failsafe: if scripts never run, show the land anyway. */
	animation: dusk-env-failsafe 0.01s linear 3.2s forwards;
}

@keyframes dusk-env-failsafe {
	to {
		opacity: 1;
	}
}

/* Sky ------------------------------------------------------------------- */

.dusk-env__sky,
.dusk-sky {
	position: absolute;
	inset: 0;
}

.dusk-sky {
	opacity: 0;
}

.dusk-sky--0 {
	opacity: 1;
	background: linear-gradient(180deg, #3b3150 0%, #6d4560 18%, #b85f5c 32%, #e8834f 44%, #f5a35c 52%, #e98852 62%, #7a4250 100%);
}

.dusk-sky--1 {
	background: linear-gradient(180deg, #2c2442 0%, #5e3a5a 18%, #a95059 32%, #e2704a 44%, #f08f50 52%, #d06b46 62%, #5e3346 100%);
}

.dusk-sky--2 {
	background: linear-gradient(180deg, #261f3d 0%, #4f2f52 18%, #924356 32%, #d65b45 44%, #ea7440 52%, #b9513e 62%, #4a2840 100%);
}

.dusk-sky--3 {
	background: linear-gradient(180deg, #1b1733 0%, #35234a 18%, #6c2f4b 32%, #b8423b 44%, #e05a31 50%, #93382f 60%, #2c1a30 100%);
}

.dusk-sky--4 {
	background: linear-gradient(180deg, #121433 0%, #1f2147 22%, #3a2c5c 36%, #6b3a66 46%, #b44f5c 53%, #e06b4a 58%, #6a3245 70%, #1d1630 100%);
}

.dusk-sky--5 {
	background: linear-gradient(180deg, #04061a 0%, #080c26 30%, #0f1433 48%, #22193d 56%, #3b2343 61%, #1a1430 74%, #090a1c 100%);
}

/* Desktop skies stay brighter up top through the sunset, as in the desktop compositions. */
@media (min-width: 1024px) {
	.dusk-sky--0 {
		background: linear-gradient(180deg, #cbbcc8 0%, #e6cfc9 22%, #f5d0b3 38%, #f7b98c 50%, #f29d6c 60%, #e88a62 72%, #c97865 100%);
	}

	.dusk-sky--1 {
		background: linear-gradient(180deg, #f3e3d8 0%, #f5d4bd 20%, #f6bc95 35%, #f5a272 47%, #f08758 57%, #e3734f 68%, #b9604f 100%);
	}

	.dusk-sky--2 {
		background: linear-gradient(180deg, #f6e6dc 0%, #f3d4c6 20%, #efb9a6 35%, #eb9880 47%, #e9785a 57%, #d9603f 65%, #9c4744 100%);
	}

	.dusk-sky--3 {
		background: linear-gradient(180deg, #f3e0d3 0%, #e8c0ae 15%, #cf9492 29%, #a25f77 41%, #b44f58 51%, #e2593a 58%, #c2442f 66%, #5d2b3a 100%);
	}
}

/* Scene box -------------------------------------------------------------- */

.dusk-env__scene {
	--scene-w: calc(max(100vw, var(--vh-full) * var(--scene-ratio)) * var(--scene-scale));
	--scene-h: calc(var(--scene-w) / var(--scene-ratio));
	position: absolute;
	width: var(--scene-w);
	height: var(--scene-h);
	left: calc((100vw - var(--scene-w)) * var(--scene-x));
	/* Put the ridge at --horizon, but never lift the artwork off the bottom edge. */
	top: max(calc(var(--vh-full) - var(--scene-h)), calc(var(--vh-full) * var(--horizon) - var(--scene-h) * var(--scene-horizon)));
}

@media (min-width: 1024px) {
	.dusk-env {
		--scene-scale: 1.04;
		--scene-x: 0.5;
		--horizon: 0.6;
	}
}

.dusk-pic {
	display: contents;
}

.dusk-img {
	position: absolute;
	left: 0;
	top: 0;
	display: block;
	width: 100%;
	height: 100%;
	max-width: none;
	object-fit: fill;
	user-select: none;
	transform: translate3d(0, 0, 0);
}

/* Stars reach above the artwork so a lowered horizon never leaves a starless band. */
.dusk-img--stars {
	left: -3%;
	top: -22%;
	width: 106%;
	height: 122%;
}

/* The upper haze asset is wider than the scene ratio: pin it to the top. */
.dusk-img--haze {
	height: auto;
}

/* Slow cloud drift uses the individual translate/scale properties, so it composes
   with the engine's parallax transform on the same element instead of fighting it. */
.dusk-img--clouds,
.dusk-img--haze {
	transform-origin: 50% 30%;
	scale: 1.08;
	animation: dusk-drift 140s var(--ease-in-out) infinite alternate;
}

.dusk-img--haze {
	animation-duration: 200s;
	animation-direction: alternate-reverse;
}

@keyframes dusk-drift {
	from {
		translate: -2.6% 0;
	}

	to {
		translate: 2.6% 0;
	}
}

/* Initial (no-JS) frame: golden hour on the homepage. */
[data-env="sky1"] {
	opacity: 1;
}

[data-env="stars"],
[data-env="lights"] {
	opacity: 0;
}

[data-env="haze"] {
	opacity: 0.4;
}

[data-env="mountainHaze"] {
	opacity: 0.9;
}

/* Sun --------------------------------------------------------------------
   A solid warm-white core with a tight gold glow and a wide amber atmosphere.
   It sits below the mountains in the stack, so it sets behind them. */

.dusk-sun {
	position: absolute;
	left: 0;
	top: 0;
	width: 0;
	height: 0;
	transform: translate3d(calc(var(--scene-w) * 0.765), calc(var(--scene-h) * 0.36), 0);
}

.dusk-sun__body {
	position: absolute;
	left: 0;
	top: 0;
	width: 0;
	height: 0;
}

.dusk-sun__core,
.dusk-sun__halo {
	position: absolute;
	left: 0;
	top: 0;
	aspect-ratio: 1;
	border-radius: 50%;
	translate: -50% -50%;
}

.dusk-sun__core {
	width: calc(var(--scene-w) * 0.034);
	background: radial-gradient(circle at 50% 48%, #fffefa 0%, #fff9ea 46%, #fff0cc 78%, #ffe3a8 100%);
	box-shadow:
		0 0 calc(var(--scene-w) * 0.004) calc(var(--scene-w) * 0.002) rgba(255, 246, 214, 0.95),
		0 0 calc(var(--scene-w) * 0.014) calc(var(--scene-w) * 0.004) rgba(255, 214, 120, 0.6);
}

.dusk-sun__core--warm {
	opacity: 0;
	background: radial-gradient(circle at 50% 46%, #fffbea 0%, #ffecb8 40%, #ffcd72 74%, #ffa952 100%);
	box-shadow:
		0 0 calc(var(--scene-w) * 0.004) calc(var(--scene-w) * 0.002) rgba(255, 232, 170, 0.95),
		0 0 calc(var(--scene-w) * 0.016) calc(var(--scene-w) * 0.006) rgba(255, 150, 70, 0.6);
}

.dusk-sun__halo {
	width: calc(var(--scene-w) * 0.34);
	background: radial-gradient(circle, rgba(255, 230, 172, 0.62) 0%, rgba(255, 196, 120, 0.36) 8%, rgba(255, 162, 96, 0.16) 22%, rgba(255, 140, 90, 0.05) 38%, rgba(255, 140, 90, 0) 56%);
}

/* Night tint and glow ---------------------------------------------------- */

.dusk-env__night {
	position: absolute;
	inset: 0;
	opacity: 0.04;
	background: linear-gradient(180deg, rgba(5, 7, 24, 0.12) 0%, rgba(5, 7, 24, 0.28) 40%, rgba(5, 7, 24, 0.72) 56%, rgba(4, 5, 18, 0.9) 100%);
}

.dusk-glow {
	position: absolute;
	left: 0;
	right: 0;
	top: 30%;
	height: 42%;
	opacity: 0.4;
	background:
		radial-gradient(42% 46% at 77% 50%, rgba(255, 170, 110, 0.78) 0%, rgba(255, 128, 104, 0.34) 42%, rgba(255, 120, 110, 0) 74%),
		linear-gradient(180deg, rgba(255, 140, 100, 0) 18%, rgba(255, 132, 104, 0.26) 48%, rgba(255, 120, 110, 0) 82%);
}

.dusk-env__scrim {
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: linear-gradient(180deg, rgba(14, 11, 30, 0.42) 0%, rgba(14, 11, 30, 0.14) 32%, rgba(14, 11, 30, 0) 52%, rgba(10, 8, 24, 0.22) 100%);
}

@media (min-width: 1024px) {
	.dusk-env--live .dusk-env__scrim {
		display: none;
	}
}

/* The very bottom of the landscape settles into the footer color, so the release
   into the footer reads as one night. */
.environment-stage::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 12%;
	background: linear-gradient(180deg, rgba(8, 10, 21, 0) 0%, rgba(8, 10, 21, 0.78) 100%);
}

/* Readability veils -------------------------------------------------------
   Atmospheric haze (day, desktop) or dusk shade (phones) behind each section's text.
   Soft radial and linear falloffs only: no edges, no boxes. The environment engine
   sets each veil's opacity from the same time of day as everything else. */

.environment-readability {
	position: absolute;
	inset: 0;
	pointer-events: none;
}

.readability {
	position: absolute;
	inset: 0;
	opacity: 0;
	visibility: hidden;
}

/* Phones and tablets: darker dusk-toned shade, broad because text fills more of the screen. */
.readability--projects {
	background:
		radial-gradient(120% 58% at 30% 24%, rgba(18, 11, 32, 0.64) 0%, rgba(18, 11, 32, 0.4) 44%, rgba(18, 11, 32, 0) 78%),
		linear-gradient(180deg, rgba(14, 9, 26, 0.32) 0%, rgba(14, 9, 26, 0) 66%);
}

.readability--services {
	background: radial-gradient(140% 76% at 40% 46%, rgba(20, 11, 34, 0.68) 0%, rgba(20, 11, 34, 0.44) 50%, rgba(20, 11, 34, 0) 86%);
}

.readability--process {
	background: radial-gradient(140% 76% at 40% 44%, rgba(16, 10, 30, 0.62) 0%, rgba(16, 10, 30, 0.38) 52%, rgba(16, 10, 30, 0) 86%);
}

.readability--about {
	background: radial-gradient(70% 34% at 70% 84%, rgba(8, 8, 24, 0.5) 0%, rgba(8, 8, 24, 0) 75%);
}

/* Desktop: warm ivory haze behind the dark type of the sunset sections.

   Past Projects and Services share one recipe (.readability--ivory): a broad pool
   behind the heading and copy on the left, a smaller pool behind the text on the
   right, and an optional long, low pool that follows a line of supporting copy.
   Same color and falloff everywhere; each section only says where its pools sit,
   so the sections read as one readability system. Positions are measured with the
   section centered on screen at 1366 x 656, 1440 x 900 and 1920 x 1080. */
@media (min-width: 1024px) {
	.readability--ivory {
		--haze: 250, 238, 226;
		background:
			radial-gradient(var(--haze-copy-size, 10% 10%) at var(--haze-copy-at, 50% 50%), rgba(var(--haze), var(--haze-copy-a, 0)) 0%, rgba(var(--haze), calc(var(--haze-copy-a, 0) * 0.57)) 50%, rgba(var(--haze), 0) 82%),
			radial-gradient(var(--haze-main-size) at var(--haze-main-at), rgba(var(--haze), 0.74) 0%, rgba(var(--haze), 0.42) 50%, rgba(var(--haze), 0) 82%),
			radial-gradient(var(--haze-side-size) at var(--haze-side-at), rgba(var(--haze), 0.66) 0%, rgba(var(--haze), 0.3) 52%, rgba(var(--haze), 0) 84%);
	}

	/* Heading, intro and "view all" link sit high; the haze is strongest there and
	   clears before the project images, the lake and the ridge. The copy pool runs
	   the full length of the intro line (5 to 50% across, 44 to 56% down) and reaches
	   the left edge, where the clouds are darkest. */
	.readability--projects {
		--haze-main-size: 50% 40%;
		--haze-main-at: 24% 30%;
		--haze-side-size: 22% 12%;
		--haze-side-at: 85% 52%;
		--haze-copy-size: 44% 14%;
		--haze-copy-at: 25% 50%;
		--haze-copy-a: 0.8;
	}

	/* The copy pool sits on the right, behind the description and the deliverables,
	   which run down into the brightest, most saturated clouds beside the sun. */
	.readability--services {
		--haze-main-size: 50% 46%;
		--haze-main-at: 27% 44%;
		--haze-side-size: 28% 34%;
		--haze-side-at: 79% 36%;
		--haze-copy-size: 30% 32%;
		--haze-copy-at: 81% 47%;
		--haze-copy-a: 0.68;
	}

	/* Process: light haze behind the headline and a long, low pool behind the intro
	   line, then the approved dark band behind the timeline. The band now starts
	   below the intro (it used to reach up into it and dim the dark type). */
	.readability--process {
		background:
			radial-gradient(34% 10% at 26% 46%, rgba(250, 238, 226, 0.66) 0%, rgba(250, 238, 226, 0.36) 50%, rgba(250, 238, 226, 0) 82%),
			radial-gradient(46% 30% at 24% 22%, rgba(250, 238, 226, 0.62) 0%, rgba(250, 238, 226, 0.3) 52%, rgba(250, 238, 226, 0) 82%),
			linear-gradient(0deg, rgba(14, 8, 24, 0.6) 0%, rgba(14, 8, 24, 0.36) 26%, rgba(14, 8, 24, 0) 44%);
	}

	.readability--about {
		background: radial-gradient(40% 30% at 74% 80%, rgba(8, 8, 24, 0.45) 0%, rgba(8, 8, 24, 0) 75%);
	}
}

/* Compositing hints only where layers actually change --------------------- */

.dusk-env--live .dusk-sun,
.dusk-env--live [data-env="valley"],
.dusk-env--live [data-env="trees"],
.dusk-env--live [data-env="rocks"],
.dusk-env--live [data-env="lights"] {
	will-change: transform;
}

.dusk-env--live .dusk-sky,
.dusk-env--live .dusk-env__night,
.dusk-env--live .dusk-glow,
.dusk-env--live .readability {
	will-change: opacity;
}

@media (min-width: 1024px) {
	.dusk-env--live .dusk-img {
		will-change: transform, opacity;
	}
}

/* Static mode: every page that is not the homepage holds a blue-hour frame. */
.dusk-env--static {
	--horizon: 0.62;
}

.dusk-env--static [data-env="sky1"],
.dusk-env--static [data-env="sky2"],
.dusk-env--static [data-env="sky3"],
.dusk-env--static [data-env="sky4"] {
	opacity: 1;
}

.dusk-env--static [data-env="sky5"] {
	opacity: 0.72;
}

.dusk-env--static [data-env="stars"] {
	opacity: 0.85;
}

.dusk-env--static [data-env="lights"] {
	opacity: 1;
}

.dusk-env--static [data-env="clouds"] {
	opacity: 0.22;
}

.dusk-env--static [data-env="haze"] {
	opacity: 0.1;
}

.dusk-env--static [data-env="mountainHaze"] {
	opacity: 0.3;
}

.dusk-env--static .dusk-sun {
	display: none;
}

.dusk-env--static .dusk-env__night {
	opacity: 0.74;
}

.dusk-env--static .dusk-glow {
	opacity: 0.45;
}

.dusk-env--static .dusk-img {
	animation: none;
}

.dusk-env--static .dusk-env__scrim {
	display: block;
	background: linear-gradient(180deg, rgba(6, 8, 22, 0.35) 0%, rgba(6, 8, 22, 0.15) 30%, rgba(6, 8, 22, 0.2) 60%, rgba(6, 8, 22, 0.55) 100%);
}
