/* =====================================================================
   CADENCE · atmosphere
   ---------------------------------------------------------------------
   The layer the content sits on, and the pieces of the front page that
   replaced the old control panel.

   Three plates, all inert:
     .amb__field  WebGL, derived from the same hue the palette is
     .amb__glow   CSS mesh — carries the room on its own if WebGL fails
     .amb__grain  a turbulence plate, the difference between "gradient"
                  and "photographed"

   Everything above them is translucent rather than opaque, which is the
   only reason any of it is visible once the page is full of content.
   ===================================================================== */

/* ---------------------------------------------------------------------
   The ambient plates
   ------------------------------------------------------------------ */

.amb {
	position: fixed;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	overflow: hidden;
	contain: strict;
}

.amb__field {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
	opacity: 1;
	transition: opacity 600ms var(--ease);
}
.amb__field.is-off { opacity: 0; }

/* The CSS half. Four soft plumes on the accent and its neighbour, drifting
   on long, unequal periods so the loop never announces itself. This is
   also the whole atmosphere on a machine with no WebGL, which is why the
   opacities are set to stand alone rather than to top up the canvas. */
.amb__glow {
	position: absolute;
	inset: -20%;
	background:
		radial-gradient(38% 34% at 18% 12%, color-mix(in oklab, var(--acc) 30%, transparent), transparent 68%),
		radial-gradient(32% 30% at 82% 8%,  color-mix(in oklab, var(--acc-2) 26%, transparent), transparent 66%),
		radial-gradient(46% 40% at 66% 62%, color-mix(in oklab, var(--acc) 16%, transparent), transparent 70%),
		radial-gradient(40% 36% at 12% 78%, color-mix(in oklab, var(--acc-2) 14%, transparent), transparent 72%);
	filter: blur(54px) saturate(1.18);
	opacity: calc(0.72 + var(--veil) * 0.6);
	will-change: transform;
}
@media (prefers-reduced-motion: no-preference) {
	.amb__glow { animation: drift 46s var(--ease) infinite alternate; }
	@keyframes drift {
		0%   { transform: translate3d(-2%, -1%, 0) scale(1.00) rotate(0deg); }
		50%  { transform: translate3d(3%, 2%, 0)  scale(1.06) rotate(1.6deg); }
		100% { transform: translate3d(-1%, 3%, 0) scale(1.02) rotate(-1.2deg); }
	}
}

/* Grain. Fractal noise at a coarse base frequency, overlaid — it breaks
   the eight-bit banding a wide, low-chroma gradient always shows, and it
   is what stops the whole thing reading as a CSS gradient. */
.amb__grain {
	position: absolute;
	inset: 0;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
	background-size: 220px 220px;
	mix-blend-mode: overlay;
	opacity: 0.055;
}
:root[data-theme="dark"] .amb__grain { opacity: 0.085; mix-blend-mode: soft-light; }
@media (prefers-color-scheme: dark) {
	:root:not([data-theme]) .amb__grain { opacity: 0.085; mix-blend-mode: soft-light; }
}

/* Everything real sits above the plates. Only the two elements that
   already participate in normal flow get a stacking context here —
   .skip is absolute and .drawer is fixed, and giving either of them
   position:relative drops them into the flow and blows a hole in the
   layout. */
main,
.site-foot { position: relative; z-index: 2; }

/* ---------------------------------------------------------------------
   Letting the field through
   The bands were opaque, which made the ambient layer pointless past the
   first screen. They are now translucent by degree: plain bands almost
   fully, tinted bands enough to still read as a change of key.
   ------------------------------------------------------------------ */

body { background: var(--bg); }

.band--sub { background: color-mix(in oklab, var(--sub) 76%, transparent); }
.strip { background: color-mix(in oklab, var(--bg) 55%, transparent); }
.cta { background: color-mix(in oklab, var(--sub) 66%, transparent); }

.caps { background: color-mix(in oklab, var(--hair) 90%, transparent); }
.cap { background: color-mix(in oklab, var(--bg) 74%, transparent); }
.cap:hover { background: color-mix(in oklab, var(--sub) 88%, transparent); }
.say,
.tier { background: color-mix(in oklab, var(--bg) 66%, transparent); }

/* ---------------------------------------------------------------------
   Hero — content only
   ------------------------------------------------------------------ */

/* No width cap here: the hero grid column is the constraint, and the
   headline is line-broken by hand in the template. */
.hero__in { align-items: center; }
@media (max-width: 1040px) { .hero__in { align-items: start; } }

/* Three facts, set as a definition list because that is what they are. */
.hero__facts {
	display: flex;
	flex-wrap: wrap;
	gap: calc(var(--sp) * 1.6);
	margin: calc(var(--sp) * 2.2) 0 0;
	padding-top: calc(var(--sp) * 1.3);
	border-top: 1px solid var(--hair);
}
.hero__facts div { display: grid; gap: 3px; }
.hero__facts dt {
	font-family: var(--ff-mono);
	font-size: 0.63rem;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--dim);
}
.hero__facts dd { margin: 0; font-size: var(--s-1); font-weight: 600; }

/* The featured case study. This is the slot the control panel used to
   occupy; it now shows the client's own most recent work. */
.feat {
	display: grid;
	align-content: start;
	border: 1px solid var(--line);
	border-radius: calc(var(--rad) * 2.4);
	overflow: hidden;
	background: color-mix(in oklab, var(--bg) 72%, transparent);
	backdrop-filter: blur(18px) saturate(1.4);
	-webkit-backdrop-filter: blur(18px) saturate(1.4);
	box-shadow: var(--shadow-2);
	transition: transform 420ms var(--ease), box-shadow 420ms var(--ease), border-color 420ms var(--ease);
}
.feat:hover { transform: translateY(-4px); border-color: var(--acc-line); }

.feat__media { position: relative; aspect-ratio: 16 / 11; overflow: hidden; background: var(--sub); }
.feat__media img {
	width: 100%; height: 100%;
	object-fit: cover;
	filter: grayscale(1) contrast(1.04);
	transform: scale(1.02);
	transition: transform 1200ms var(--ease-out), filter 700ms var(--ease);
}
.feat__media::after {
	content: "";
	position: absolute; inset: 0;
	background: linear-gradient(148deg,
		color-mix(in oklab, var(--acc) 66%, transparent),
		color-mix(in oklab, var(--acc-2) 38%, transparent));
	mix-blend-mode: color;
	opacity: 0.86;
	transition: opacity 700ms var(--ease);
}
.feat:hover .feat__media img { transform: scale(1.06); filter: grayscale(0.42) contrast(1.02); }
.feat:hover .feat__media::after { opacity: 0.4; }

.feat__flag {
	position: absolute; left: 14px; top: 14px; z-index: 2;
	font-family: var(--ff-mono);
	font-size: 0.6rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	padding: 5px 10px;
	border-radius: calc(var(--rad) * 1.3);
	background: color-mix(in oklab, var(--bg) 82%, transparent);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	border: 1px solid var(--hair);
	color: var(--ink);
}

.feat__body { padding: calc(var(--sp) * 1.5); display: grid; gap: calc(var(--sp) * 0.6); }
.feat__eyebrow {
	font-family: var(--ff-mono);
	font-size: 0.64rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--dim);
	display: flex;
	gap: 0.5em;
	align-items: center;
}
.feat__eyebrow i { font-style: normal; opacity: 0.6; }
.feat__body h2 { font-size: var(--s1); line-height: 1.2; letter-spacing: -0.022em; }
.feat__res { font-size: var(--s-1); color: var(--ink-70); margin: 0; }
.feat__go {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	font-size: var(--s-1);
	font-weight: 600;
	color: var(--acc-ink);
	margin-top: calc(var(--sp) * 0.3);
}
.feat__go i { font-style: normal; transition: transform 320ms var(--ease); }
.feat:hover .feat__go i { transform: translateX(4px); }

/* ---------------------------------------------------------------------
   Sectors
   ------------------------------------------------------------------ */

.secs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: calc(var(--sp) * 1.1); }
@media (max-width: 900px) { .secs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 540px) { .secs { grid-template-columns: minmax(0, 1fr); } }

.sec {
	position: relative;
	display: grid;
	gap: calc(var(--sp) * 0.55);
	align-content: start;
	padding: calc(var(--sp) * 1.5);
	border: 1px solid var(--line);
	border-radius: calc(var(--rad) * 1.9);
	background: color-mix(in oklab, var(--bg) 62%, transparent);
	overflow: hidden;
	isolation: isolate;
	transition: transform 320ms var(--ease), border-color 320ms var(--ease), box-shadow 320ms var(--ease);
}
/* A wash that only arrives on hover, wiped in from the corner the arrow
   points to. Cheap, and it gives the grid somewhere to go. */
.sec::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: radial-gradient(120% 100% at 100% 0%, var(--acc-soft), transparent 62%);
	opacity: 0;
	transition: opacity 380ms var(--ease);
}
.sec:hover { transform: translateY(-4px); border-color: var(--acc-line); box-shadow: var(--shadow-1); }
.sec:hover::before { opacity: 1; }
.sec__n { font-family: var(--ff-mono); font-size: 0.66rem; letter-spacing: 0.12em; color: var(--acc); }
.sec h3 { font-size: var(--s1); letter-spacing: -0.025em; }
.sec p { font-size: var(--s-1); color: var(--ink-70); margin: 0; }
.sec__go {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	margin-top: calc(var(--sp) * 0.5);
	font-family: var(--ff-mono);
	font-size: 0.64rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--dim);
	transition: color 300ms var(--ease);
}
.sec__go i { font-style: normal; transition: transform 320ms var(--ease); }
.sec:hover .sec__go { color: var(--acc-ink); }
.sec:hover .sec__go i { transform: translateX(4px); }

/* ---------------------------------------------------------------------
   Archive filters
   Was borrowed from the old preset chips; these are navigation.
   ------------------------------------------------------------------ */

.filters {
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
	align-items: center;
	margin-top: calc(var(--sp) * 1.8);
	padding-top: calc(var(--sp) * 1.4);
	border-top: 1px solid var(--hair);
}
.filters > .lab { margin-right: auto; }
.filter {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	padding: 7px 14px;
	border: 1px solid var(--line);
	border-radius: calc(var(--rad) * 1.7);
	background: color-mix(in oklab, var(--bg) 55%, transparent);
	color: var(--ink-70);
	font-size: var(--s-1);
	font-weight: 500;
	transition: border-color 220ms var(--ease), color 220ms var(--ease), background 220ms var(--ease);
}
.filter:hover { border-color: var(--acc); color: var(--ink); }
.filter[aria-current="page"] { border-color: var(--acc); background: var(--acc-soft); color: var(--acc-ink); }

/* ---------------------------------------------------------------------
   Closing band — a slow sheen across the panel
   ------------------------------------------------------------------ */

.cta__in { isolation: isolate; }
.cta::after {
	content: "";
	position: absolute;
	inset: -40% -10%;
	background: conic-gradient(from 210deg at 70% 30%,
		transparent 0deg,
		color-mix(in oklab, var(--acc) 24%, transparent) 60deg,
		transparent 150deg,
		color-mix(in oklab, var(--acc-2) 18%, transparent) 250deg,
		transparent 360deg);
	filter: blur(60px);
	opacity: 0.7;
	pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
	.cta::after { animation: sheen 34s linear infinite; }
	@keyframes sheen { to { transform: rotate(360deg); } }
}

/* ---------------------------------------------------------------------
   Depth on scroll
   Where scroll-driven animations exist the hero's plume recedes as the
   reader leaves it, which hands the page over to the content instead of
   competing with it. Compositor-only: transform and opacity.
   ------------------------------------------------------------------ */

@supports (animation-timeline: scroll()) {
	@media (prefers-reduced-motion: no-preference) {
		.hero::before {
			animation: hero-recede linear both;
			animation-timeline: scroll();
			animation-range: 0 92vh;
		}
		@keyframes hero-recede {
			to { transform: translateX(-50%) translateY(-12%) scale(0.94); opacity: 0.1; }
		}
	}
}
