/* ===========================================================================
 * rush-fx.css — REDESIGN r2 Part B: the ambient and micro layers.
 *
 * Cold open (M25), grain (M29), progress rule + slash index (M21), cursor
 * (M20), ambient light sweep + particles (M23). Every layer here is
 * aria-hidden and pointer-events: none (the intro takes pointer events only
 * while it is up, so a click skips it). Everything hidden-at-rest is scoped
 * to html.rush-motion / html.rush-intro; without those classes nothing here
 * paints. Colours are roles (--t-*); the gold surfaces are fixed brand gold.
 * ======================================================================== */

/* ── M25 the cold open ─────────────────────────────────────────────────── */
[data-rush-intro] {
	position: fixed;
	inset: 0;
	z-index: 9500;
	display: none;
	pointer-events: none;
	overflow: hidden;
}
html.rush-intro [data-rush-intro] { display: grid; place-items: center; pointer-events: auto; cursor: pointer; }
html.rush-intro { overflow: hidden; }
.rush-intro-field { position: absolute; inset: 0; background: var(--t-bg); }
.rush-intro-blade {
	position: absolute;
	top: -20vh; bottom: -20vh;
	width: 22vw;
	left: 0;
	/* r2 fix (P1): parked FULLY off-screen — the skew of a 140vh-tall band
	 * pushes its top corner ~0.4·vh to the right, so -60vw showed a gold wedge
	 * on phones before the timeline ran. */
	transform: translateX(calc(-100vw - 60vh)) skewX(-30deg);
}
.rush-intro-blade--gold { background: #ffaa00 var(--rush-foil, none) center / cover; } /* fixed: the gold blade */
.rush-intro-blade--ink { width: 6vw; background: var(--t-fg); opacity: 0.92; }
.rush-intro-mark { position: relative; width: 60vw; max-width: 440px; z-index: 2; }
.rush-intro-mark img {
	width: 100%; height: auto;
	clip-path: polygon(0 0, 0 0, -57.7% 100%, -57.7% 100%);
}
/* Light: the real asset, inked, on a gold slab (gold on paper is 2:1). */
:root:not([data-theme="dark"]) .rush-intro-mark::before {
	content: "";
	position: absolute;
	left: -18%; right: -18%; top: -22%; bottom: -22%;
	background: #ffaa00 var(--rush-foil, none) center / cover; /* fixed */
	transform: skewX(-30deg) scaleX(var(--slab-s, 0));
	transform-origin: left center;
	z-index: -1;
}
:root:not([data-theme="dark"]) .rush-intro-mark img { filter: brightness(0); }
:root[data-theme="dark"] .rush-intro-mark::before { content: none; }
:root[data-theme="dark"] .rush-intro-mark img { filter: none; }
/* r2 fix (P2): the type beat is a real beat — display size, full ink/paper,
 * held 400 ms before the ride-out (rush-intro.js). */
.rush-intro-line {
	position: absolute;
	left: 50%; top: calc(50% + min(16vw, 150px));
	transform: translateX(-50%);
	margin: 0;
	width: max-content;
	max-width: calc(100vw - 32px);
	font-weight: 900;
	font-size: clamp(1.125rem, 2.6vw, 2.25rem);
	line-height: 1.05;
	letter-spacing: -0.01em;
	text-transform: uppercase;
	text-align: center;
	color: var(--t-fg);
	white-space: normal;
	text-wrap: balance;
	z-index: 2;
}
.rush-intro-line .rk-line { overflow: hidden; display: block; }
.rush-intro-line .rk-line-in { display: block; transform: translateY(110%); }
/* GSAP drives this rise frame by frame: the M3b CSS transition on .rk-line-in
 * must not re-tween every frame (it kept the line below its mask). */
html.rush-motion .rush-intro-line .rk-line-in { transition: none; }
@media (min-width: 768px) {
	.rush-intro-mark { width: 26vw; max-width: 520px; }
}
@media (prefers-reduced-motion: reduce) {
	[data-rush-intro] { display: none !important; }
}

/* ── M29 grain: a fixed 300vw × 300vh tile; living jitter on desktop ──── */
.rush-grain {
	position: fixed;
	inset: -50%;
	z-index: 9000;
	pointer-events: none;
	background: url("../img/rush-black-grain.webp?v=1.23.2") repeat;
	background-size: 420px 420px;
	opacity: 0;
	mix-blend-mode: var(--t-grain-blend);
	transition: opacity 600ms ease;
}
html.rush-loaded .rush-grain { opacity: var(--t-grain-alpha); }
html.rush-entry .rush-grain,
html.rush-intro .rush-grain { display: none; }
@media (min-width: 768px) and (prefers-reduced-motion: no-preference) {
	html.rush-motion.rush-loaded .rush-grain { animation: rushGrain 640ms steps(8) infinite; }
	html.rush-hidden .rush-grain { animation-play-state: paused; }
}
@keyframes rushGrain {
	0% { transform: translate(0, 0); }
	12.5% { transform: translate(-4%, -6%); }
	25% { transform: translate(6%, -2%); }
	37.5% { transform: translate(-2%, 5%); }
	50% { transform: translate(5%, 7%); }
	62.5% { transform: translate(-7%, 3%); }
	75% { transform: translate(3%, -4%); }
	87.5% { transform: translate(-5%, -1%); }
	100% { transform: translate(0, 0); }
}
/* Dark theme: multiply the grain into itself less (soft-light at 1 is the r1
 * value); the token owns the numbers. */

/* ── M21 progress rule + slash index ───────────────────────────────────── */
.rush-progress {
	position: fixed;
	top: 0; left: 0; right: 0;
	height: 2px;
	z-index: 850;
	pointer-events: none;
	--p: 0;
	background: transparent;
}
.rush-progress::before {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--t-gold);
	transform: scaleX(var(--p));
	transform-origin: left center;
}
.rush-progress i {
	position: absolute;
	top: -2px;
	left: 0;
	width: 10px; height: 6px;
	background: var(--t-gold);
	transform: translateX(calc(var(--p) * 100vw - 100%)) skewX(-30deg);
	box-shadow: 0 0 12px var(--t-glow);
}
html.rush-motion .rush-progress::before,
html.rush-motion .rush-progress i { transition: transform 80ms linear; }
.rush-index {
	position: fixed;
	right: 14px;
	top: 50%;
	transform: translateY(-50%);
	z-index: 820;
	display: none;
	flex-direction: column;
	gap: 10px;
	padding: 6px 0;
}
html.rush-entry .rush-index,
html.rush-intro .rush-index { display: none !important; }
@media (min-width: 1024px) {
	html.rush-motion .rush-index { display: flex; }
}
/* r2 fix (P2): 32×24 targets (WCAG 2.5.8), Work Sans labels at 12px. */
.rush-index button {
	position: relative;
	display: block;
	width: 32px; height: 24px;
	padding: 0;
	margin: 0;
	border: 0;
	background: transparent;
	cursor: pointer;
	color: var(--t-fg-3);
	font: inherit;
}
.rush-index button::before {
	content: "";
	position: absolute;
	right: 0; top: 10px;
	width: 22px; height: 3px;
	background: currentColor;
	transform: skewX(-30deg) scaleX(0.55);
	transform-origin: right center;
	transition: transform 300ms var(--ease-mark), background-color 200ms;
}
.rush-index button.is-active::before,
.rush-index button:hover::before,
.rush-index button:focus-visible::before { transform: skewX(-30deg) scaleX(1); background: var(--t-gold); }
.rush-index button span {
	position: absolute;
	right: 36px; top: 50%;
	transform: translate(6px, -50%);
	opacity: 0;
	white-space: nowrap;
	font-family: "Work Sans", "Helvetica Neue", sans-serif;
	font-weight: 800;
	font-size: 12px;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--t-bg);
	background: var(--t-fg);
	padding: 5px 9px;
	border-radius: 3px;
	transition: opacity 180ms ease, transform 240ms var(--ease-out-cine);
	pointer-events: none;
}
.rush-index button:hover span,
.rush-index button:focus-visible span { opacity: 1; transform: translate(0, -50%); }

/* ── M20 cursor: gold dot (difference) + ring; over interactive targets the
 * ring collapses and a 30° slash takes its place. The OUTER nodes are moved
 * by JS (translate only, on the shared ticker); the inner <i> carries the
 * shape and its transform/opacity transitions. Native cursor stays. ──── */
.rush-cursor,
.rush-cursor-ring,
.rush-cursor-slash,
.rush-cursor-lbl {
	position: fixed;
	left: 0; top: 0;
	z-index: 9600;
	pointer-events: none;
	will-change: transform;
}
.rush-cursor > i,
.rush-cursor-ring > i,
.rush-cursor-slash > i {
	display: block;
	opacity: 0;
	transition: opacity 200ms ease, transform 260ms var(--ease-out-cine);
}
.rush-cursor > i {
	width: 10px; height: 10px;
	margin: -5px 0 0 -5px;
	border-radius: 50%;
	background: #ffaa00; /* fixed: brand gold, difference-blended */
	mix-blend-mode: difference;
}
.rush-cursor-ring > i {
	width: 36px; height: 36px;
	margin: -18px 0 0 -18px;
	border: 1px solid #ffaa00; /* fixed */
	border-radius: 50%;
	box-sizing: border-box;
	transform: scale(0.6);
}
.rush-cursor-slash > i {
	width: 28px; height: 4px;
	margin: -2px 0 0 -14px;
	background: #ffaa00; /* fixed */
	transform-origin: center;
	transform: skewX(-30deg) scaleX(0.2);
}
html.rush-cursor-on .rush-cursor > i,
html.rush-cursor-on .rush-cursor-ring > i { opacity: 1; }
html.rush-cursor-on .rush-cursor-ring > i { transform: scale(1); }
html.rush-cursor-on.rush-cursor-link .rush-cursor-ring > i { opacity: 0; transform: scale(0.4); }
html.rush-cursor-on.rush-cursor-link .rush-cursor-slash > i { opacity: 1; transform: skewX(-30deg) scaleX(1); }
html.rush-cursor-on.rush-cursor-link .rush-cursor > i { opacity: 0; }
html.rush-cursor-on.rush-cursor-text .rush-cursor-ring > i { opacity: 0; transform: scale(0.4); }
html.rush-cursor-on.rush-cursor-text .rush-cursor-slash > i { opacity: 1; transform: rotate(90deg) skewX(-30deg) scaleX(0.9) scaleY(0.6); }
html.rush-cursor-on.rush-cursor-text .rush-cursor > i { opacity: 0; }
html.rush-entry .rush-cursor > i,
html.rush-entry .rush-cursor-ring > i,
html.rush-entry .rush-cursor-slash > i,
html.rush-intro .rush-cursor > i,
html.rush-intro .rush-cursor-ring > i,
html.rush-intro .rush-cursor-slash > i { opacity: 0 !important; }
.rush-cursor-lbl { z-index: 9601; }
.rush-cursor-lbl > i {
	display: block;
	margin: 18px 0 0 18px;
	padding: 6px 10px;
	border-radius: 3px;
	background: #ffaa00; /* fixed */
	color: #10100e; /* fixed: ink on gold */
	font-family: "Work Sans", "Helvetica Neue", sans-serif;
	font-style: normal;
	font-weight: 800;
	font-size: 12px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	opacity: 0;
	transform: translateY(4px) skewX(-8deg);
	transition: opacity 180ms ease, transform 240ms var(--ease-out-cine);
	white-space: nowrap;
}
/* r2 fix (P1): the label only shows while the cursor itself is on — it was
 * left sitting on the hero after the entry match cut. */
html.rush-cursor-on .rush-cursor-lbl.is-on > i { opacity: 1; transform: translateY(0) skewX(0); }

/* ── M23 ambient light sweep (dark, desktop): a fixed 30° band crossing
 * the viewport every 7 s. ────────────────────────────────────────────── */
.rush-lightsweep {
	position: fixed;
	top: -30vh; bottom: -30vh;
	left: 0;
	width: 34vw;
	z-index: 8990;
	pointer-events: none;
	background: linear-gradient(90deg, transparent 0%, var(--t-sweep) 50%, transparent 100%);
	mix-blend-mode: var(--t-sweep-blend);
	transform: translateX(-60vw) skewX(-30deg);
	opacity: 0;
}
html.rush-loaded.rush-motion[data-theme="dark"] .rush-lightsweep { opacity: 0.8; animation: rushLightSweep 7s linear 3s infinite; }
html.rush-hidden .rush-lightsweep,
html.rush-entry .rush-lightsweep,
html.rush-intro .rush-lightsweep { animation-play-state: paused; opacity: 0; }
@keyframes rushLightSweep {
	0% { transform: translateX(-60vw) skewX(-30deg); }
	40% { transform: translateX(140vw) skewX(-30deg); }
	100% { transform: translateX(140vw) skewX(-30deg); }
}

/* ── M17 magnetic: the label counter-moves; JS drives transforms (gsap
 * promotes while tweening — no permanent will-change). ─────────────────── */
[data-magnetic] > span:first-child { display: inline-block; }
/* The grain pauses under the theme cut (a cheap frame for the VT snapshot). */
html.rush-theme-cutting .rush-grain,
html.rush-theme-cutting .rush-lightsweep { animation-play-state: paused; }

/* ── M23b gold dust canvas ─────────────────────────────────────────────── */
.rush-dust { display: block; }

@media (prefers-reduced-motion: reduce) {
	.rush-grain,
	.rush-lightsweep,
	.rush-cursor,
	.rush-cursor-ring,
	.rush-cursor-slash,
	.rush-cursor-lbl,
	.rush-dust { animation: none !important; display: none !important; }
	.rush-progress::before,
	.rush-progress i { transition: none; }
}
