/**
 * RTMMotion — frontend base styles.
 *
 * Only job: pre-hide entrance elements so they don't flash before GSAP runs.
 * GSAP writes inline styles (which beat this stylesheet) to reveal/animate.
 * The frontend script also reveals everything if GSAP fails to load, and the
 * reduced-motion rule below reveals without waiting for JS at all.
 */
html.rtm-smooth-scroll-enabled,
html.rtm-smooth-scroll-enabled body {
	scroll-behavior: smooth;
}

html.rtm-smooth-scroll-enabled {
	scroll-padding-top: 90px;
}

html.rtm-smooth-scroll-enabled [id],
html.rtm-smooth-scroll-enabled [name] {
	scroll-margin-top: 90px;
}

html.rtm-page-smooth-active,
html.rtm-page-smooth-active body {
	scroll-behavior: auto !important;
}

[data-rtm-mode="element"][data-rtm-animate="1"],
[data-rtm-mode="layout"][data-rtm-animate="1"] {
	opacity: 0;
}

/* Text Motion entrances also start hidden, otherwise the un-animated text
   paints first and only fades/splits in once JS runs (the "text shows first,
   then the animation plays late" flash). Scoped to the fade/split family and
   EXCLUDING the self-managed presets: typewriter (starts empty), scramble
   (starts scrambled) and gradient_text (always visible) never play the
   entrance fromTo, so opacity:0 here would leave them invisible forever. The
   split/fade paths reveal the wrapper themselves (reveal()/playEntrance both
   set opacity:1 and drop data-rtm-animate), so they clear this safely. */
[data-rtm-mode="text"][data-rtm-animate="1"]:not([data-rtm-text-preset="typewriter"]):not([data-rtm-text-preset="scramble"]):not([data-rtm-text-preset="gradient_text"]) {
	opacity: 0;
}

[data-rtm-mode="element"][data-rtm-animate="1"][data-rtm-preset="blur"],
[data-rtm-mode="layout"][data-rtm-animate="1"][data-rtm-preset="blur"] {
	filter: blur(10px);
}

/* Horizontal Scroll layout effect */
[data-rtm-layout-effect="horizontal"] {
	overflow: hidden !important;
}

[data-rtm-layout-effect="horizontal"],
[data-rtm-layout-effect="horizontal"] > .e-con-inner {
	flex-direction: row !important;
	flex-wrap: nowrap !important;
}

/* Panels must keep an EXPLICIT width and never shrink, or the row can't exceed
   the viewport. Two Elementor behaviours fight this and are overridden with
   !important (Elementor's own rules win on source order otherwise):
     1. `flex-shrink:1` collapses items to fit — force 0.
     2. A FULL-WIDTH container (`e-con-full`) ignores its Width control, so the
        user's `--width` never reaches `width`. Re-apply it here: honour the
        panel's own `--width` if set, else a sensible 480px so the effect still
        overflows out-of-the-box. A Boxed panel's `--width` flows through the
        same way.
   Full-width: direct children are the panels. Boxed: panels sit in .e-con-inner
   (excluded from the width rule so the wrapper itself isn't resized). */
[data-rtm-layout-effect="horizontal"] > *:not(.e-con-inner),
[data-rtm-layout-effect="horizontal"] > .e-con-inner > * {
	flex: 0 0 auto !important;
	width: var(--width, 480px) !important;
}

/* Vertical Scroll — now a NATIVE-SCROLL fade+rise reveal (no pin, no sticky viewport),
   so it needs NO layout overrides at all: the section keeps its normal Elementor flow
   and the JS only fades each panel in as it enters view. (The old sticky-HOLD/track
   rules were removed with the pin-scrub mechanic that stuttered.) */

/* Vertical Scroll (Up & Down) — the DiviMotion COUNTER-SCROLL, still built on a native
   position:sticky HOLD (NOT a ScrollTrigger pin, whose revert-time start measurement
   drifts when the section sits below other tall/pinned sections and snaps at the pin
   edge — the "lompatan"). The JS wraps the panels in a `.rtm-vview` viewport and grows
   the SECTION into a TRACK (inline height = 100vh + scroll distance). */
[data-rtm-layout-effect="vertical-updown"],
[data-rtm-layout-effect="vertical-updown"] > .e-con-inner {
	overflow: visible !important;
	display: block !important;
}

/* The sticky viewport: HOLDS full-screen (100vh) at the top while the track scrolls
   under it, and crops its content (overflow hidden) so the panels scrub inside it. */
[data-rtm-layout-effect="vertical-updown"] > .rtm-vview,
[data-rtm-layout-effect="vertical-updown"] > .e-con-inner > .rtm-vview {
	position: sticky !important;
	top: 0 !important;
	width: 100% !important;
	height: 100vh !important;
	overflow: hidden !important;
}

/* Up & Down: the two lanes are a 2-col grid inside the sticky viewport. The default
   grid row flow fills col-1 with the even-index children (0,2,4…) and col-2 with the
   odd ones (1,3,5…) — exactly the two lanes the JS translates apart. */
[data-rtm-layout-effect="vertical-updown"] > .rtm-vview,
[data-rtm-layout-effect="vertical-updown"] > .e-con-inner > .rtm-vview {
	display: grid !important;
	grid-template-columns: 1fr 1fr !important;
	align-content: center !important;
	justify-items: center !important;
}
[data-rtm-layout-effect="vertical-updown"] .rtm-vview > * {
	min-height: 0 !important;
	align-self: start !important;
}

/* Accessibility: honour the OS "reduce motion" setting — show final state,
   never hide, never animate. Highest-priority reveal. */
@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto !important;
	}

	[data-rtm-mode][data-rtm-animate="1"] {
		opacity: 1 !important;
		filter: none !important;
		transform: none !important;
	}
}

/* ==================================================================
   Element Motion v2 — Spotlight (Mouse Effect) + Hover Effects stack.

   Fully declarative: the effects key off the data-rtm-* markers PHP emits and
   read their colours/sizes from inline custom properties PHP also emits, so
   Elementor's in-place editor re-render updates everything live with no JS
   value-bridge. Spotlight's --mx/--my are the only values JS writes (cursor
   position); without JS it simply falls back to a centred glow.

   Reduced motion is handled by the media query at the end (these rules are not
   gated behind a JS class, so the query is what silences them).
   ================================================================== */

/* ---- Spotlight glow (Mouse Effects section) ----
   The ::after is expanded one glow-radius beyond the widget on every side
   (negative inset) so the light SPILLS past the widget bounds instead of being
   clipped to its box. --mx/--my are the cursor position in px relative to the
   widget's top-left; the gradient centre is offset by one radius to compensate
   for the expanded box origin. It still gets clipped by any ancestor that sets
   overflow:hidden (e.g. a section), which is the expected boundary. */
[data-rtm-spotlight="1"] {
	position: relative;
}
/* Overlay glow (default) — suppressed in clip-to-text mode. */
[data-rtm-spotlight="1"]:not([data-rtm-spotlight-clip="1"])::after {
	content: "";
	position: absolute;
	inset: calc(-1 * var(--rtm-sp-size, 220px));
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.3s ease;
	background: radial-gradient(
		var(--rtm-sp-size, 220px) circle at
			calc(var(--mx, 50%) + var(--rtm-sp-size, 220px))
			calc(var(--my, 50%) + var(--rtm-sp-size, 220px)),
		var(--rtm-sp-color, #7c5cff),
		transparent 70%
	);
	mix-blend-mode: screen;
	z-index: 2;
}
[data-rtm-spotlight="1"]:not([data-rtm-spotlight-clip="1"]):hover::after {
	opacity: 0.55;
}

/* Clip-to-text spotlight — the radial gradient becomes the text fill (clipped to
   the glyphs), so only the letters under the cursor light up. The glyphs OUTSIDE
   the light pool keep their own original colour (--rtm-sp-base, which JS seeds
   from the text's computed colour) instead of darkening. Applied on the text
   element JS marks with .rtm-sp-cliptext (wrapper or descendant), only while
   hovered so idle text keeps its normal colour.

   Three stacked background layers compose the "smoke" light (all clipped to the
   glyphs). Bottom to top:
     • a solid base = the text's own colour, so unlit glyphs never darken;
     • a wide, diffuse trail centred on --mx2/--my2 (a slow, wobbling position JS
       eases behind the cursor) — this is the drifting smoke body;
     • a tighter, brighter core centred on --mx/--my (eases fast toward the
       cursor) — the leading edge of the light.
   Both light layers fade to transparent so the base colour shows through.

   While a split-text entrance is mid-flight the text element carries
   .rtm-split-active (live split parts with inline transforms — each its own
   paint layer the clipped background can't cover). Engaging the clip then
   renders the glyphs doubled/stacked, so hover stays dormant until JS reverts
   the split and drops the class: hovering during the animation simply shows
   the normal animating text. */
[data-rtm-spotlight-clip="1"]:hover .rtm-sp-cliptext:not(.rtm-split-active),
[data-rtm-spotlight-clip="1"].rtm-sp-cliptext:not(.rtm-split-active):hover {
	background-image:
		radial-gradient(
			calc(var(--rtm-sp-size, 220px) * 0.6) circle at var(--mx, 50%) var(--my, 50%),
			var(--rtm-sp-color, #7c5cff) 0%,
			transparent 60%
		),
		radial-gradient(
			var(--rtm-sp-size, 220px) circle at var(--mx2, 50%) var(--my2, 50%),
			var(--rtm-sp-color, #7c5cff) 0%,
			transparent 72%
		),
		linear-gradient(var(--rtm-sp-base, currentColor), var(--rtm-sp-base, currentColor));
	background-repeat: no-repeat;
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
}

/* ---- Content Reveal — a hover-triggered wipe. The resting state stays fully
   visible (no permanent clip), so the widget never disappears when idle; the
   reveal animation re-draws it from one side on each hover-in. ---- */
[data-rtm-hfx-reveal="bottom"].rtm-hfx-play { animation: rtm-hfx-reveal-b 0.55s ease; }
[data-rtm-hfx-reveal="top"].rtm-hfx-play    { animation: rtm-hfx-reveal-t 0.55s ease; }
[data-rtm-hfx-reveal="left"].rtm-hfx-play   { animation: rtm-hfx-reveal-l 0.55s ease; }
[data-rtm-hfx-reveal="right"].rtm-hfx-play  { animation: rtm-hfx-reveal-r 0.55s ease; }
@keyframes rtm-hfx-reveal-b {
	from { clip-path: inset(0 0 100% 0); transform: scale(var(--rtm-reveal-scale, 1)); }
	to   { clip-path: inset(0 0 0 0);    transform: scale(1); }
}
@keyframes rtm-hfx-reveal-t {
	from { clip-path: inset(100% 0 0 0); transform: scale(var(--rtm-reveal-scale, 1)); }
	to   { clip-path: inset(0 0 0 0);    transform: scale(1); }
}
@keyframes rtm-hfx-reveal-l {
	from { clip-path: inset(0 100% 0 0); transform: scale(var(--rtm-reveal-scale, 1)); }
	to   { clip-path: inset(0 0 0 0);    transform: scale(1); }
}
@keyframes rtm-hfx-reveal-r {
	from { clip-path: inset(0 0 0 100%); transform: scale(var(--rtm-reveal-scale, 1)); }
	to   { clip-path: inset(0 0 0 0);    transform: scale(1); }
}

/* ---- Drop-shadow Glow ---- */
[data-rtm-hfx-glow] {
	transition: filter 0.35s ease;
}
[data-rtm-hfx-glow]:hover {
	filter: drop-shadow(0 0 var(--rtm-glow-size, 18px) var(--rtm-glow-color, #7c5cff));
}

/* ---- Underline Draw (::after line grows from one side) ---- */
[data-rtm-hfx-underline] {
	position: relative;
}
[data-rtm-hfx-underline]::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: var(--rtm-ul-size, 2px);
	background: var(--rtm-ul-color, #7c5cff);
	transform: scaleX(0);
	transition: transform 0.35s ease;
	pointer-events: none;
}
[data-rtm-hfx-underline="left"]::after   { transform-origin: left; }
[data-rtm-hfx-underline="center"]::after { transform-origin: center; }
[data-rtm-hfx-underline="right"]::after  { transform-origin: right; }
[data-rtm-hfx-underline]:hover::after {
	transform: scaleX(1);
}

/* ---- Fill / Swipe Background (::before sweeps in behind content) ----
   The fill rides on ::before at z-index:-1 so it sits behind the element's own
   content. On an element with its own opaque background the fill is hidden — use
   this on transparent-background elements, or set the element background to
   transparent and let the fill provide it. ---- */
[data-rtm-hfx-fill] {
	position: relative;
	z-index: 0;
	transition: color 0.35s ease;
}
[data-rtm-hfx-fill]::before {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--rtm-fill-color, #7c5cff);
	transition: transform 0.4s ease;
	z-index: -1;
	pointer-events: none;
	border-radius: inherit;
}
[data-rtm-hfx-fill="left"]::before   { transform: scaleX(0); transform-origin: left; }
[data-rtm-hfx-fill="right"]::before  { transform: scaleX(0); transform-origin: right; }
[data-rtm-hfx-fill="top"]::before    { transform: scaleY(0); transform-origin: top; }
[data-rtm-hfx-fill="bottom"]::before { transform: scaleY(0); transform-origin: bottom; }
[data-rtm-hfx-fill]:hover::before {
	transform: scale(1);
}
[data-rtm-hfx-fill]:hover {
	color: var(--rtm-fill-text, inherit);
}

/* ---- Bounce / Wiggle (one-shot on enter; intensity via unitless var) ---- */
[data-rtm-hfx-bounce="bounce"]:hover {
	animation: rtm-hfx-bounce 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
[data-rtm-hfx-bounce="wiggle"]:hover {
	animation: rtm-hfx-wiggle 0.5s ease-in-out;
}
@keyframes rtm-hfx-bounce {
	0%   { transform: scale(1); }
	40%  { transform: scale(calc(1 + var(--rtm-bounce-int, 8) * 0.01)); }
	70%  { transform: scale(calc(1 - var(--rtm-bounce-int, 8) * 0.005)); }
	100% { transform: scale(1); }
}
@keyframes rtm-hfx-wiggle {
	0%, 100% { transform: rotate(0); }
	25%      { transform: rotate(calc(var(--rtm-bounce-int, 8) * 1deg)); }
	75%      { transform: rotate(calc(var(--rtm-bounce-int, 8) * -1deg)); }
}

/* ---- 3D Flip (single flip peek — no back-face DOM, no mirroring).
   The element turns edge-on to 90deg and returns to front in one pass. It never
   rotates past 90deg, so the mirrored (backwards) back-face is never shown, and
   the one-shot .rtm-hfx-play class makes it flip exactly once per hover-in. ---- */
[data-rtm-hfx-flip="y"].rtm-hfx-play { animation: rtm-hfx-flip-y 0.6s ease; }
[data-rtm-hfx-flip="x"].rtm-hfx-play { animation: rtm-hfx-flip-x 0.6s ease; }
@keyframes rtm-hfx-flip-y {
	0%   { transform: perspective(var(--rtm-flip-persp, 800px)) rotateY(0); }
	50%  { transform: perspective(var(--rtm-flip-persp, 800px)) rotateY(90deg); }
	100% { transform: perspective(var(--rtm-flip-persp, 800px)) rotateY(0); }
}
@keyframes rtm-hfx-flip-x {
	0%   { transform: perspective(var(--rtm-flip-persp, 800px)) rotateX(0); }
	50%  { transform: perspective(var(--rtm-flip-persp, 800px)) rotateX(90deg); }
	100% { transform: perspective(var(--rtm-flip-persp, 800px)) rotateX(0); }
}

/* ---- Pulse Glow (loops while hovered, stops + resets on leave) ---- */
[data-rtm-hfx-pulse]:hover {
	animation: rtm-hfx-pulse var(--rtm-pulse-speed, 1.2s) ease-in-out infinite alternate;
}
@keyframes rtm-hfx-pulse {
	from { filter: drop-shadow(0 0 0 transparent); }
	to   { filter: drop-shadow(0 0 16px var(--rtm-pulse-color, #7c5cff)); }
}

/* ---- Accessibility: silence every hover/spotlight effect under reduced
   motion (these rules aren't gated behind a JS class, so the query does it). ---- */
@media (prefers-reduced-motion: reduce) {
	[data-rtm-spotlight="1"]::after,
	[data-rtm-hfx-glow],
	[data-rtm-hfx-underline]::after,
	[data-rtm-hfx-fill],
	[data-rtm-hfx-fill]::before {
		transition: none !important;
	}
	[data-rtm-hfx-reveal].rtm-hfx-play,
	[data-rtm-hfx-bounce]:hover,
	[data-rtm-hfx-flip].rtm-hfx-play,
	[data-rtm-hfx-pulse]:hover {
		animation: none !important;
	}
}

/* ==================================================================
   Dynamic Cursor
   A single fixed overlay that follows the pointer (position driven by
   JS via transform) and morphs into the hovered target's state. Only
   opacity/colour transition here — the transform is rAF-driven, so a
   CSS transition on it would fight the follow loop and lag.
   ================================================================== */
.rtm-dyn-cursor {
	position: fixed;
	top: 0;
	left: 0;
	z-index: 2147483000;
	pointer-events: none;
	box-sizing: border-box;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.4em;
	height: var(--rtm-cur-size, 44px);
	min-width: var(--rtm-cur-size, 44px);
	padding: 0 0.7em;
	border-radius: var(--rtm-cur-radius, 999px);
	background: var(--rtm-cur-bg, #0b0b10);
	color: var(--rtm-cur-fg, #ffffff);
	font-size: 13px;
	font-weight: 600;
	line-height: 1;
	white-space: nowrap;
	opacity: 0;
	transform: translate3d(-100px, -100px, 0) translate(-50%, -50%);
	transition: opacity 0.2s ease, background-color 0.25s ease, color 0.25s ease,
		height 0.25s ease, min-width 0.25s ease, border-radius 0.25s ease;
	will-change: transform, opacity;
}

.rtm-dyn-cursor.rtm-dyn-cursor--on {
	opacity: 1;
}

/* Icon-only: keep it a tight circle (no side padding). */
.rtm-dyn-cursor.rtm-dyn-cursor--icon {
	padding: 0;
}

.rtm-dyn-cursor__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
}

.rtm-dyn-cursor__icon i {
	font-size: var(--rtm-cur-icon-size, 1.15em);
	line-height: 1;
}

/* Server-rendered icons arrive as inline <svg> when Elementor is in
   inline-font-icons mode — size them to the font box and inherit colour. */
.rtm-dyn-cursor__icon svg {
	display: block;
	width: var(--rtm-cur-icon-size, 1.15em);
	height: var(--rtm-cur-icon-size, 1.15em);
	fill: currentColor;
}

.rtm-dyn-cursor__text {
	font-size: 0.95em;
	letter-spacing: 0.02em;
}

/* Clickable cursor targets: show a pointer whenever the custom overlay isn't
   covering the native cursor (JS sets inline cursor:none only while hovered on
   hover-capable devices, so this is the resting/touch state). */
[data-rtm-cur-url] {
	cursor: pointer;
}

/* Coarse pointers (touch) never get the overlay. */
@media (hover: none), (pointer: coarse) {
	.rtm-dyn-cursor {
		display: none !important;
	}
}

@media (prefers-reduced-motion: reduce) {
	.rtm-dyn-cursor {
		transition: opacity 0.2s ease;
	}
}
