/**
 * Zezuru Elements — Motion
 *
 * Styles for the "Zezuru: Motion" panel available on every block.
 * Loaded only on pages that use motion (see Zezel_Assets).
 *
 * Design notes
 * - Entrance animations use `transform`, parallax uses the independent
 *   `translate` property and ambient loops use `translate` / `scale` /
 *   `rotate`, so effects can be combined without overwriting each other.
 * - Hidden "before" states only apply when <html> has .zezel-js (added by a
 *   tiny inline script), so content is never hidden without JavaScript.
 * - Everything is switched off under prefers-reduced-motion.
 *
 * @package Zezuru_Elements
 * @since   2.6.0
 */

/* ---------------------------------------------------------------------
 * Defaults
 * ------------------------------------------------------------------ */
.zezel-motion {
	--zezel-dur: 800ms;
	--zezel-delay: 0ms;
	--zezel-dist: 40px;
	--zezel-ease: cubic-bezier(.16, 1, .3, 1);
	--zezel-step: 90ms;
	--zezel-hl: #6c5ce7;
	--zezel-hl2: #00b894;
}

/* ---------------------------------------------------------------------
 * Entrance: "from" state per type, expressed as custom properties so the
 * same values drive the block itself or (with stagger) its children.
 * ------------------------------------------------------------------ */
[data-zezel-in="fade"]        { --zezel-t: none; }
[data-zezel-in="fade-up"]     { --zezel-t: translate3d(0, var(--zezel-dist), 0); }
[data-zezel-in="fade-down"]   { --zezel-t: translate3d(0, calc(var(--zezel-dist) * -1), 0); }
[data-zezel-in="fade-left"]   { --zezel-t: translate3d(var(--zezel-dist), 0, 0); }
[data-zezel-in="fade-right"]  { --zezel-t: translate3d(calc(var(--zezel-dist) * -1), 0, 0); }
[data-zezel-in="zoom-in"]     { --zezel-t: scale(.86); }
[data-zezel-in="zoom-out"]    { --zezel-t: scale(1.14); }
[data-zezel-in="blur-in"]     { --zezel-t: scale(1.04); --zezel-f: blur(14px); }
[data-zezel-in="flip-up"]     { --zezel-t: perspective(900px) rotateX(28deg) translate3d(0, calc(var(--zezel-dist) * .5), 0); }
[data-zezel-in="flip-left"]   { --zezel-t: perspective(900px) rotateY(-28deg); }
[data-zezel-in="rotate-in"]   { --zezel-t: rotate(-6deg) translate3d(0, var(--zezel-dist), 0); }
[data-zezel-in="skew-up"]     { --zezel-t: skewY(5deg) translate3d(0, var(--zezel-dist), 0); }
[data-zezel-in="pop"]         { --zezel-t: scale(.7); --zezel-ease: cubic-bezier(.34, 1.56, .64, 1); }
[data-zezel-in="reveal-up"]   { --zezel-t: translate3d(0, 14px, 0); --zezel-o: 1; --zezel-c: inset(100% 0 0 0); --zezel-c-to: inset(0 0 0 0); }
[data-zezel-in="reveal-left"] { --zezel-t: none; --zezel-o: 1; --zezel-c: inset(0 100% 0 0); --zezel-c-to: inset(0 0 0 0); }

/* Animated properties while entering (removed once .is-done so hover
 * effects get their own snappy timing). */
[data-zezel-in]:not([data-zezel-stagger]):not(.is-done),
[data-zezel-stagger]:not(.is-done) > * {
	transition-property: opacity, transform, filter, clip-path;
	transition-duration: var(--zezel-dur);
	transition-timing-function: var(--zezel-ease);
	transition-delay: var(--zezel-delay);
}
[data-zezel-stagger]:not(.is-done) > * {
	transition-delay: calc(var(--zezel-delay) + var(--zezel-i, 0) * var(--zezel-step));
}

/* Hidden "before" state (JS on, or an editor preview). */
:is(.zezel-js, .zezel-preview-root) [data-zezel-in]:not([data-zezel-stagger]):not(.is-in),
:is(.zezel-js, .zezel-preview-root) [data-zezel-stagger]:not(.is-in) > *,
.zezel-preview[data-zezel-in]:not([data-zezel-stagger]):not(.is-in),
.zezel-preview[data-zezel-stagger]:not(.is-in) > * {
	opacity: var(--zezel-o, 0);
	transform: var(--zezel-t, none);
	filter: var(--zezel-f, none);
	clip-path: var(--zezel-c, none);
}

/* Visible state. */
[data-zezel-in].is-in:not([data-zezel-stagger]),
[data-zezel-stagger].is-in > * {
	opacity: 1;
	transform: none;
	filter: none;
	clip-path: var(--zezel-c-to, none);
}

[data-zezel-in]:not(.is-in) { will-change: opacity, transform; }

/* ---------------------------------------------------------------------
 * Text effects
 * ------------------------------------------------------------------ */

/* Keep split/typed text invisible until motion.js has prepared it. */
.zezel-js [data-zezel-text="typing"]:not(.zezel-ready),
.zezel-js [data-zezel-text="words"]:not(.zezel-ready),
.zezel-js [data-zezel-text="letters"]:not(.zezel-ready),
.zezel-js [data-zezel-text="scramble"]:not(.zezel-ready) {
	visibility: hidden;
}

/* Typing caret */
.zezel-caret {
	display: inline-block;
	width: .08em;
	min-width: 2px;
	height: 1em;
	margin-left: .06em;
	vertical-align: -.12em;
	background: currentColor;
	animation: zezel-blink 1s steps(1) infinite;
}
.zezel-rotator { color: var(--zezel-hl); }

/* Word / letter reveal */
.zezel-split { display: inline-block; white-space: nowrap; }
.zezel-w,
.zezel-l {
	display: inline-block;
	opacity: 0;
	transform: translate3d(0, .6em, 0) rotate(2deg);
	filter: blur(6px);
	transition: opacity calc(var(--zezel-dur) * .7) var(--zezel-ease), transform calc(var(--zezel-dur) * .7) var(--zezel-ease), filter calc(var(--zezel-dur) * .7) var(--zezel-ease);
	transition-delay: calc(var(--zezel-delay) + var(--zezel-i, 0) * 45ms);
}
[data-zezel-text="letters"] .zezel-l { transition-delay: calc(var(--zezel-delay) + var(--zezel-i, 0) * 22ms); }
.zezel-text-in .zezel-w,
.zezel-text-in .zezel-l { opacity: 1; transform: none; filter: none; }

/* Marker highlight that sweeps in behind the text */
.zezel-hl {
	background-image: linear-gradient(transparent 58%, color-mix(in srgb, var(--zezel-hl) 42%, transparent) 58%);
	background-repeat: no-repeat;
	background-size: 0% 100%;
	-webkit-box-decoration-break: clone;
	box-decoration-break: clone;
	transition: background-size calc(var(--zezel-dur) * 1.4) var(--zezel-ease) calc(var(--zezel-delay) + 150ms);
}
.zezel-text-in .zezel-hl { background-size: 100% 100%; }

/* Flowing gradient text (pure CSS) */
[data-zezel-text="gradient"] {
	background-image: linear-gradient(100deg, var(--zezel-hl), var(--zezel-hl2), var(--zezel-hl));
	background-size: 220% 100%;
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	animation: zezel-flow 6s linear infinite;
}

/* Counter / scramble keep width stable while digits change */
[data-zezel-text="counter"],
[data-zezel-text="scramble"] { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------
 * Hover effects
 * ------------------------------------------------------------------ */
.zezel-hover-lift,
.zezel-hover-grow,
.zezel-hover-shrink,
.zezel-hover-glow,
.zezel-hover-tilt {
	transition: transform .45s cubic-bezier(.16, 1, .3, 1), box-shadow .45s cubic-bezier(.16, 1, .3, 1), filter .45s ease;
}
.zezel-hover-lift:hover   { transform: translate3d(0, -8px, 0); box-shadow: 0 22px 44px -18px rgba(15, 16, 32, .35); }
.zezel-hover-grow:hover   { transform: scale(1.04); }
.zezel-hover-shrink:hover { transform: scale(.97); }
.zezel-hover-glow:hover   { box-shadow: 0 0 0 1px color-mix(in srgb, var(--zezel-hl) 50%, transparent), 0 14px 46px -8px color-mix(in srgb, var(--zezel-hl) 55%, transparent); }
.zezel-hover-tilt         { transform-style: preserve-3d; }
.zezel-hover-tilt.is-tilting { transition-duration: .12s; }

.zezel-hover-shine { position: relative; overflow: hidden; isolation: isolate; }
.zezel-hover-shine::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background: linear-gradient(115deg, transparent 30%, rgba(255, 255, 255, .45) 50%, transparent 70%);
	transform: translate3d(-120%, 0, 0);
	transition: transform .9s cubic-bezier(.16, 1, .3, 1);
}
.zezel-hover-shine:hover::before { transform: translate3d(120%, 0, 0); }

/* ---------------------------------------------------------------------
 * Ambient loops (independent transform properties; start once visible)
 * ------------------------------------------------------------------ */
:is(.zezel-loop-float, .zezel-loop-pulse, .zezel-loop-breathe, .zezel-loop-swing, .zezel-loop-spin, .zezel-loop-bounce):is(.is-in, .zezel-in-editor, :not([data-zezel-in])) {
	animation-duration: 6s;
	animation-timing-function: ease-in-out;
	animation-iteration-count: infinite;
}
.zezel-loop-float:is(.is-in, .zezel-in-editor, :not([data-zezel-in]))   { animation-name: zezel-float; }
.zezel-loop-pulse:is(.is-in, .zezel-in-editor, :not([data-zezel-in]))   { animation-name: zezel-pulse; animation-duration: 2.6s; }
.zezel-loop-breathe:is(.is-in, .zezel-in-editor, :not([data-zezel-in])) { animation-name: zezel-breathe; animation-duration: 4s; }
.zezel-loop-swing:is(.is-in, .zezel-in-editor, :not([data-zezel-in]))   { animation-name: zezel-swing; animation-duration: 4.5s; transform-origin: top center; }
.zezel-loop-spin:is(.is-in, .zezel-in-editor, :not([data-zezel-in]))    { animation-name: zezel-spin; animation-duration: 24s; animation-timing-function: linear; }
.zezel-loop-bounce:is(.is-in, .zezel-in-editor, :not([data-zezel-in]))  { animation-name: zezel-bounce; animation-duration: 2.2s; }

/* ---------------------------------------------------------------------
 * Scroll-linked effects — CSS scroll-driven animations, zero JavaScript.
 * Browsers without support simply show the block normally.
 * ------------------------------------------------------------------ */
@supports (animation-timeline: view()) {
	[class*="zezel-scroll-"] {
		animation-timing-function: linear;
		animation-fill-mode: both;
		animation-timeline: view();
	}
	.zezel-scroll-fade-in  { animation-name: zezel-s-fade;  animation-range: entry 0% cover 35%; }
	.zezel-scroll-scale-up { animation-name: zezel-s-scale; animation-range: entry 0% cover 40%; }
	.zezel-scroll-rise     { animation-name: zezel-s-rise;  animation-range: entry 0% cover 40%; }
	.zezel-scroll-fade-out { animation-name: zezel-s-out;   animation-range: exit 0% exit 100%; }
	.zezel-scroll-blur-out { animation-name: zezel-s-blur;  animation-range: exit 0% exit 100%; }
}

/* ---------------------------------------------------------------------
 * Keyframes
 * ------------------------------------------------------------------ */
@keyframes zezel-blink   { 50% { opacity: 0; } }
@keyframes zezel-flow    { to { background-position: -220% 0; } }
@keyframes zezel-float   { 0%, 100% { translate: 0 0; } 50% { translate: 0 -12px; } }
@keyframes zezel-pulse   { 0%, 100% { scale: 1; } 50% { scale: 1.045; } }
@keyframes zezel-breathe { 0%, 100% { opacity: 1; } 50% { opacity: .6; } }
@keyframes zezel-swing   { 0%, 100% { rotate: -2.5deg; } 50% { rotate: 2.5deg; } }
@keyframes zezel-spin    { to { rotate: 360deg; } }
@keyframes zezel-bounce  { 0%, 100% { translate: 0 0; } 30% { translate: 0 -14px; } 50% { translate: 0 0; } 65% { translate: 0 -5px; } }
@keyframes zezel-s-fade  { from { opacity: 0; } to { opacity: 1; } }
@keyframes zezel-s-scale { from { opacity: .3; scale: .88; } to { opacity: 1; scale: 1; } }
@keyframes zezel-s-rise  { from { opacity: 0; translate: 0 80px; } to { opacity: 1; translate: 0 0; } }
@keyframes zezel-s-out   { from { opacity: 1; } to { opacity: 0; } }
@keyframes zezel-s-blur  { from { opacity: 1; filter: blur(0); } to { opacity: .2; filter: blur(10px); } }

/* ---------------------------------------------------------------------
 * Accessibility: honour reduced-motion preferences completely.
 * ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
	.zezel-motion,
	[data-zezel-stagger] > *,
	.zezel-motion .zezel-w,
	.zezel-motion .zezel-l,
	.zezel-motion .zezel-hl {
		opacity: 1 !important;
		transform: none !important;
		translate: none !important;
		scale: none !important;
		rotate: none !important;
		filter: none !important;
		clip-path: none !important;
		animation: none !important;
		transition: none !important;
		visibility: visible !important;
	}
	.zezel-motion .zezel-hl { background-size: 100% 100% !important; }
	.zezel-caret { display: none; }
}


/* ---------------------------------------------------------------------
 * Background parallax (since 2.8.0)
 *
 * The block's own background picture or video drifts slower than the
 * page. Where the browser supports scroll-driven animations the browser
 * runs it on the compositor with no JavaScript; elsewhere motion.js
 * writes the same `translate` in one requestAnimationFrame. The layer is
 * scaled just enough that its edges never show.
 * ------------------------------------------------------------------ */
[data-zezel-bgpx] { --zezel-bgpx: 40; overflow: hidden; }
[data-zezel-bgpx] > :is(.wp-block-cover__image-background, .wp-block-cover__video-background, img, a > img, .wp-block-media-text__media > img, .wp-block-media-text__media > video),
.zezel-hero[data-zezel-bgpx] .zezel-hero__media {
	scale: calc(1 + var(--zezel-bgpx) * .0026);
	will-change: translate;
}
.wp-block-media-text[data-zezel-bgpx] > .wp-block-media-text__media { overflow: hidden; }

@supports (animation-timeline: view()) {
	[data-zezel-bgpx] { view-timeline: --zezel-bgpx block; }
	[data-zezel-bgpx] > :is(.wp-block-cover__image-background, .wp-block-cover__video-background, img, a > img, .wp-block-media-text__media > img, .wp-block-media-text__media > video),
	.zezel-hero[data-zezel-bgpx] .zezel-hero__media {
		animation: zezel-bgpx linear both;
		animation-timeline: --zezel-bgpx;
		animation-range: cover 0% cover 100%;
	}
}
@keyframes zezel-bgpx {
	from { translate: 0 calc(var(--zezel-bgpx) * -.12%); }
	to { translate: 0 calc(var(--zezel-bgpx) * .12%); }
}

@media (max-width: 781.98px) {
	[data-zezel-bgpx-mobile="0"] > :is(.wp-block-cover__image-background, .wp-block-cover__video-background, img, a > img, .wp-block-media-text__media > img, .wp-block-media-text__media > video),
	.zezel-hero[data-zezel-bgpx-mobile="0"] .zezel-hero__media { animation: none; translate: none; scale: none; }
}
@media (prefers-reduced-motion: reduce) {
	[data-zezel-bgpx] > :is(.wp-block-cover__image-background, .wp-block-cover__video-background, img, a > img, .wp-block-media-text__media > img, .wp-block-media-text__media > video),
	.zezel-hero[data-zezel-bgpx] .zezel-hero__media { animation: none !important; translate: none !important; scale: none !important; }
}
