/* ==========================================================================
   Motion Engine — tokens + reusable motion primitives (ARCHITECTURE.md §19
   sibling system: Theme Engine controls color, Motion Engine controls
   movement). Every effect below only ever animates `transform`, `opacity`,
   and (where unavoidable) `filter`/`background-position` — never
   `top/left/width/height/margin` — so the compositor can run these off the
   main thread. All durations route through `--motion-scale` so a single
   media query at the bottom disables/instantizes everything at once.

   Hooks reused as-is from the existing JS modules (parallax.js sets inline
   translate3d on [data-parallax-layer]; magnetic.js sets --mx/--my on
   [data-magnetic]) — this file adds the CSS side for those plus every
   other listed effect. Color values fall back to the Luxury Gold defaults
   via var(--token, #hex) so this file works even if theme.css loads after
   it, but always prefers the live theme token.
   ========================================================================== */

/* ---- Motion Tokens ----------------------------------------------------- */
:root {
	--motion-scale: 1; /* 0 under prefers-reduced-motion; multiplies every duration */

	--ease-luxury: cubic-bezier(0.22, 1, 0.36, 1);
	--ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
	--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
	--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);

	--dur-instant: 0.15s;
	--dur-fast: 0.25s;
	--dur-mid: 0.5s;
	--dur-slow: 0.9s;
	--dur-epic: 1.6s;

	--dist-xs: 8px;
	--dist-sm: 16px;
	--dist-md: 28px;
	--dist-lg: 48px;

	--tilt-max: 6deg;
	--blur-reveal: 14px;
	--cursor-glow-size: 320px;

	--z-mesh: 0;
	--z-aurora: 0;
	--z-particles: 1;
	--z-parallax: 2;
	--z-content: 10;
	--z-nav: 100;
	--z-modal: 200;
	--z-loader: 300;
	--z-cursor-glow: 400;
}

/* ---- Page Transition ---------------------------------------------------- */
.page-transition {
	position: fixed;
	inset: 0;
	z-index: var(--z-loader);
	background: var(--color-bg, #0D0D0D);
	opacity: 0;
	pointer-events: none;
	transform: translateZ(0);
	transition: opacity calc(var(--dur-mid) * var(--motion-scale)) var(--ease-luxury);
	will-change: opacity;
}

.page-transition.is-active {
	opacity: 1;
	pointer-events: all;
}

/* ---- Card Hover ----------------------------------------------------------- */
.card-hover {
	transform: translate3d(0, 0, 0) scale(1);
	transition: transform calc(var(--dur-fast) * var(--motion-scale)) var(--ease-out-expo),
		box-shadow calc(var(--dur-fast) * var(--motion-scale)) var(--ease-soft);
}

.card-hover:hover,
.card-hover:focus-visible {
	transform: translate3d(0, calc(-1 * var(--dist-xs)), 0) scale(1.02);
	box-shadow: var(--shadow-soft, 0 20px 60px -20px rgba(0, 0, 0, 0.6));
	will-change: transform;
}

/* Optional pointer-driven 3D tilt: JS sets --tilt-x/--tilt-y (-1..1) */
.card-hover.is-tiltable {
	transform: translate3d(0, 0, 0)
		rotateX(calc(var(--tilt-y, 0) * var(--tilt-max) * -1))
		rotateY(calc(var(--tilt-x, 0) * var(--tilt-max)));
	transition: transform calc(var(--dur-instant) * var(--motion-scale)) var(--ease-soft);
}

/* ---- Glass Reflection ------------------------------------------------------- */
.glass-reflect {
	position: relative;
	overflow: hidden;
}

.glass-reflect::before {
	content: '';
	position: absolute;
	inset: -50%;
	background: linear-gradient(75deg, transparent 40%, var(--glass-bg-strong, rgba(247, 247, 247, 0.06)) 50%, transparent 60%);
	transform: translate3d(-60%, 0, 0);
	transition: transform calc(var(--dur-slow) * var(--motion-scale)) var(--ease-soft);
	pointer-events: none;
	will-change: transform;
}

.glass-reflect:hover::before,
.glass-reflect.is-active::before {
	transform: translate3d(60%, 0, 0);
}

/* ---- Parallax ----------------------------------------------------------- */
/* Transform itself is set inline by parallax.js each frame (translate3d) —
   this only declares the compositor hint and starting position. */
[data-parallax-layer] {
	position: relative;
	z-index: var(--z-parallax);
	transform: translate3d(0, 0, 0);
	will-change: transform;
}

/* ---- Aurora --------------------------------------------------------------- */
.aurora {
	position: absolute;
	inset: -20%;
	z-index: var(--z-aurora);
	pointer-events: none;
	filter: blur(60px);
	opacity: 0.25;
	background:
		radial-gradient(circle at 30% 30%, var(--color-gold, #C6A46C) 0%, transparent 60%),
		radial-gradient(circle at 70% 60%, var(--color-gold-light, #E7CE9F) 0%, transparent 55%);
	transform: translate3d(0, 0, 0) scale(1) rotate(0deg);
	animation: aurora-drift calc(18s / max(var(--motion-scale), 0.001)) var(--ease-soft) infinite;
	will-change: transform;
}

@keyframes aurora-drift {
	0%, 100% { transform: translate3d(0, 0, 0) scale(1) rotate(0deg); }
	50% { transform: translate3d(3%, -4%, 0) scale(1.08) rotate(6deg); }
}

/* ---- Mesh Gradient ---------------------------------------------------------- */
/* Uses background-position (not compositor-only) by nature of a multi-point
   mesh — kept intentionally slow and low-opacity to bound paint cost. */
.mesh-gradient {
	position: absolute;
	inset: 0;
	z-index: var(--z-mesh);
	pointer-events: none;
	opacity: 0.35;
	background-size: 200% 200%;
	background-image:
		radial-gradient(at 20% 20%, var(--color-gold, #C6A46C) 0px, transparent 50%),
		radial-gradient(at 80% 0%, var(--color-gold-light, #E7CE9F) 0px, transparent 50%),
		radial-gradient(at 0% 100%, var(--color-bg-elevated, #141414) 0px, transparent 50%),
		radial-gradient(at 80% 80%, var(--color-gold-dark, #8F7141) 0px, transparent 50%);
	animation: mesh-shift calc(24s / max(var(--motion-scale), 0.001)) var(--ease-soft) infinite;
}

@keyframes mesh-shift {
	0%, 100% { background-position: 0% 0%, 100% 0%, 0% 100%, 100% 100%; }
	50% { background-position: 20% 30%, 80% 20%, 10% 80%, 90% 70%; }
}

/* ---- Ripple ----------------------------------------------------------------- */
/* JS sets --ripple-x/--ripple-y (click offset) and toggles .is-rippling */
[data-ripple] {
	position: relative;
	overflow: hidden;
}

[data-ripple]::after {
	content: '';
	position: absolute;
	left: var(--ripple-x, 50%);
	top: var(--ripple-y, 50%);
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--glass-bg-strong, rgba(247, 247, 247, 0.06));
	transform: translate3d(-50%, -50%, 0) scale(0);
	opacity: 0;
	pointer-events: none;
}

[data-ripple].is-rippling::after {
	animation: ripple-expand calc(var(--dur-mid) * var(--motion-scale)) var(--ease-out-expo);
}

@keyframes ripple-expand {
	0% { transform: translate3d(-50%, -50%, 0) scale(0); opacity: 0.6; }
	100% { transform: translate3d(-50%, -50%, 0) scale(40); opacity: 0; }
}

/* ---- Hero Reveal -------------------------------------------------------------- */
.hero-reveal {
	display: block;
	overflow: hidden;
}

.hero-reveal__inner {
	display: block;
	transform: translate3d(0, 115%, 0);
	opacity: 0;
	transition: transform calc(var(--dur-epic) * var(--motion-scale)) var(--ease-luxury),
		opacity calc(var(--dur-epic) * var(--motion-scale)) var(--ease-luxury);
	transition-delay: calc(var(--delay, 0) * 0.15s * var(--motion-scale));
}

.hero-reveal.is-visible .hero-reveal__inner {
	transform: translate3d(0, 0, 0);
	opacity: 1;
}

/* ---- Text Reveal (line-by-line) ------------------------------------------------- */
.text-reveal {
	display: inline-block;
	overflow: hidden;
}

.text-reveal__line {
	display: block;
	transform: translate3d(0, 100%, 0);
	opacity: 0;
	transition: transform calc(var(--dur-slow) * var(--motion-scale)) var(--ease-luxury),
		opacity calc(var(--dur-slow) * var(--motion-scale)) var(--ease-luxury);
	transition-delay: calc(var(--delay, 0) * 0.09s * var(--motion-scale));
}

.text-reveal.is-visible .text-reveal__line {
	transform: translate3d(0, 0, 0);
	opacity: 1;
}

/* ---- Magnetic Button --------------------------------------------------------- */
/* JS sets --mx/--my (pointer offset) on [data-magnetic]; this smooths it. */
[data-magnetic] {
	display: inline-flex;
	transform: translate3d(var(--mx, 0px), var(--my, 0px), 0);
	transition: transform calc(var(--dur-fast) * var(--motion-scale)) var(--ease-out-expo);
	will-change: transform;
}

/* ---- Cursor Glow -------------------------------------------------------------- */
/* JS sets --cursor-x/--cursor-y (viewport px) on <body> or a dedicated node */
.cursor-glow {
	position: fixed;
	top: 0;
	left: 0;
	z-index: var(--z-cursor-glow);
	width: var(--cursor-glow-size);
	height: var(--cursor-glow-size);
	border-radius: 50%;
	pointer-events: none;
	opacity: 0;
	background: radial-gradient(circle, var(--glass-bg-strong, rgba(247, 247, 247, 0.08)) 0%, transparent 70%);
	transform: translate3d(calc(var(--cursor-x, 50vw) - 50%), calc(var(--cursor-y, 50vh) - 50%), 0);
	transition: opacity calc(var(--dur-fast) * var(--motion-scale)) var(--ease-soft);
	will-change: transform;
}

body.has-cursor-glow .cursor-glow {
	opacity: 1;
}

/* ---- Floating Objects ------------------------------------------------------------ */
[data-float] {
	transform: translate3d(0, 0, 0) rotate(0deg);
	animation: float-object calc(6s / max(var(--motion-scale), 0.001)) var(--ease-soft) infinite;
	animation-delay: calc(var(--delay, 0) * 0.4s);
	will-change: transform;
}

@keyframes float-object {
	0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
	50% { transform: translate3d(0, calc(-1 * var(--dist-md)), 0) rotate(3deg); }
}

/* ---- Morph Animation --------------------------------------------------------------- */
.morph-shape {
	border-radius: 42% 58% 65% 35% / 45% 40% 60% 55%;
	transform: translate3d(0, 0, 0) rotate(0deg);
	animation: morph-blob calc(12s / max(var(--motion-scale), 0.001)) var(--ease-soft) infinite;
	will-change: border-radius, transform;
}

@keyframes morph-blob {
	0%, 100% { border-radius: 42% 58% 65% 35% / 45% 40% 60% 55%; transform: translate3d(0, 0, 0) rotate(0deg); }
	50% { border-radius: 58% 42% 35% 65% / 55% 60% 40% 45%; transform: translate3d(0, 0, 0) rotate(8deg); }
}

/* ---- Blur Reveal ------------------------------------------------------------------ */
.blur-reveal {
	opacity: 0;
	filter: blur(var(--blur-reveal));
	transform: translate3d(0, var(--dist-sm), 0) scale(1.02);
	transition: opacity calc(var(--dur-slow) * var(--motion-scale)) var(--ease-out-expo),
		filter calc(var(--dur-slow) * var(--motion-scale)) var(--ease-out-expo),
		transform calc(var(--dur-slow) * var(--motion-scale)) var(--ease-out-expo);
}

.blur-reveal.is-visible {
	opacity: 1;
	filter: blur(0);
	transform: translate3d(0, 0, 0) scale(1);
	will-change: opacity, filter, transform;
}

/* ---- Split Text (char/word stagger) ------------------------------------------------- */
/* JS wraps each character/word in its own span and sets --i (its index) */
.split-text span {
	display: inline-block;
	transform: translate3d(0, 60%, 0);
	opacity: 0;
	transition: transform calc(var(--dur-mid) * var(--motion-scale)) var(--ease-spring),
		opacity calc(var(--dur-mid) * var(--motion-scale)) var(--ease-soft);
	transition-delay: calc(var(--i, 0) * 0.025s * var(--motion-scale));
}

.split-text.is-visible span {
	transform: translate3d(0, 0, 0);
	opacity: 1;
}

/* ---- GPU Optimized ------------------------------------------------------------------- */
/* Opt-in layer promotion for anything animated frequently (drag, rAF-driven
   parallax, continuous keyframe loops). Not applied globally on purpose —
   permanent `will-change` on static elements wastes compositor memory; the
   hover-scoped rules above already add/imply it only while animating. */
.gpu {
	transform: translateZ(0);
	backface-visibility: hidden;
	will-change: transform;
}

/* Belt-and-suspenders: every keyframe/transition-driven class above commits
   to transform/opacity/filter only — never triggers layout (no width,
   height, top, left, margin animation anywhere in this file). */

/* ---- Respect prefers-reduced-motion --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	:root {
		--motion-scale: 0;
	}

	/* --motion-scale collapses every transition above to 0s (end state shows
	   immediately, nothing animates) — but continuous/vestibular-triggering
	   loops need an explicit stop, since `animation-duration: 0s infinite`
	   is not a reliable no-op across browsers. */
	.aurora,
	.mesh-gradient,
	[data-float],
	.morph-shape,
	.cursor-glow,
	.gallery__track {
		animation: none !important;
	}

	.cursor-glow {
		display: none;
	}

	[data-parallax-layer] {
		transform: none !important;
	}
}
