/**
 * 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);
}

/* ================= Editor canvas: never hide anything =================
   Nothing animates on the canvas — motion runs on the real page and in Preview.
   So on the canvas NO mechanism of ours may leave content invisible: not the
   pre-hide above, not an entrance from-state, not a scrub sitting at progress 0.

   `!important` here deliberately outranks inline styles, which is what makes
   this hold even when the JS that wrote them is a stale cached copy, ran before
   Elementor stamped the body, or failed altogether. Three surfaces are covered:
   the motion wrapper, the inner container an entrance is retargeted to when
   Scrolling Effects share the element (see entranceHost in the JS), and the live
   split-text parts.

   transform is deliberately NOT reset: it is what positions sticky/layout
   effects, and an offset element is still visible — a hidden one is not. */
body.elementor-editor-active [data-rtm-mode],
body.elementor-editor-active [data-rtm-mode] > .elementor-widget-container,
body.elementor-editor-active [data-rtm-mode] > .e-con-inner,
body.elementor-editor-active [data-rtm-mode] .rtm-split-active,
body.elementor-editor-active [data-rtm-animate="1"] {
	opacity: 1 !important;
	filter: none !important;
	clip-path: none !important;
	visibility: visible !important;
}

/* 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;
	/* Safari: keep every panel on its own GPU compositor layer for the whole
	   scroll. Without this Safari repaints the row on the main thread each
	   frame while GSAP translates the panels — the choppy
	   horizontal scroll. Chrome promotes the layer on its own; Safari needs
	   the explicit hint. Pairs with the force3D seed in trackFollower(). */
	will-change: transform;
	backface-visibility: hidden;
	-webkit-backface-visibility: hidden;
}

/* Same GPU-layer hint for the two counter-scrolling lanes of Up & Down. */
[data-rtm-layout-effect="vertical-updown"] .rtm-vview > * {
	will-change: transform;
	backface-visibility: hidden;
	-webkit-backface-visibility: hidden;
}

/* Vertical Scroll — a NATIVE-SCROLL fade+rise reveal (no pin, no sticky viewport): the
   page scrolls normally and the JS fades each panel in as it enters view. (The old
   sticky-HOLD/track rules were removed with the pin-scrub mechanic that stuttered.)
   What it DOES need is the right flow direction. Sections are very often built as a
   ROW (or a multi-column Grid), so the panels sat side by side and ran off to the
   RIGHT — a "vertical" scroll with nothing to scroll through, and every panel crossing
   the reveal line at the same moment so they all fired at once. Force a single COLUMN,
   the mirror of the horizontal block above: whatever the container's own Direction /
   Layout is set to, the panels stack DOWNWARD. `display:flex` must be forced too, or a
   Grid container ignores flex-direction and keeps its columns. */
[data-rtm-layout-effect="vertical"],
[data-rtm-layout-effect="vertical"] > .e-con-inner {
	display: flex !important;
	flex-direction: column !important;
	flex-wrap: nowrap !important;
}

/* Panels: span the column, keep their natural height, never shrink. `flex:0 0 auto`
   stops a section with a fixed height from squashing them, and a panel that carries its
   own Width control still wins (`--width`) — otherwise it fills the width, so a row
   built for the horizontal effect doesn't stay pinched at 480px once stacked.
   Full-width container: the panels are direct children. Boxed: they sit in .e-con-inner
   (excluded so the wrapper itself isn't resized). Elementor's background overlay /
   slideshow layers are absolutely-positioned decoration, not panels — sizing them here
   would crop the section background. */
[data-rtm-layout-effect="vertical"] > *:not(.e-con-inner):not(.elementor-background-overlay):not(.elementor-background-slideshow),
[data-rtm-layout-effect="vertical"] > .e-con-inner > *:not(.elementor-background-overlay):not(.elementor-background-slideshow) {
	flex: 0 0 auto !important;
	width: var(--width, 100%) !important;
	max-width: 100% !important;
}

/* 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 "jump"). 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;
	inset-inline-start: 0;
	inset-inline-end: 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;
	/* Cross-axis alignment of icon/image vs. text — "Icon / Text Alignment".
	   The panel offers Top / Center / Bottom and the renderer maps those to the
	   flex keywords. In the Top/Bottom (column) layouts the same value reads as
	   left / centre / right, which is why one var drives both. */
	align-items: var(--rtm-cur-align, center);
	justify-content: center;
	gap: var(--rtm-cur-gap, 0.4em);
	height: var(--rtm-cur-size, 44px);
	min-width: var(--rtm-cur-size, 44px);
	padding: var(--rtm-cur-pad, 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) unless the user set one. */
.rtm-dyn-cursor.rtm-dyn-cursor--icon {
	padding: var(--rtm-cur-pad, 0);
}

/* ---- Icon / image position relative to the text ----
   JS mirrors the widget's data-rtm-cur-pos onto the overlay. Left/Right lay the
   two children out in a row, Top/Bottom in a column — and the column variants
   un-pin the bubble's fixed height, otherwise the second line would overflow. */
.rtm-dyn-cursor[data-rtm-cur-pos='left']   { flex-direction: row; }
.rtm-dyn-cursor[data-rtm-cur-pos='right']  { flex-direction: row-reverse; }
.rtm-dyn-cursor[data-rtm-cur-pos='top']    { flex-direction: column; }
.rtm-dyn-cursor[data-rtm-cur-pos='bottom'] { flex-direction: column-reverse; }

.rtm-dyn-cursor[data-rtm-cur-pos='top'],
.rtm-dyn-cursor[data-rtm-cur-pos='bottom'] {
	height: auto;
	min-height: var(--rtm-cur-size, 44px);
}

/* Image cursor. The bubble grows with the picture (its Image Size slider can
   exceed the base cursor size), and the image is cropped by the cursor's own
   border radius — a round cursor shows a round image. Image-only drops the
   side padding so the picture IS the cursor; Image + Text keeps the pill. */
.rtm-dyn-cursor.rtm-dyn-cursor--image,
.rtm-dyn-cursor.rtm-dyn-cursor--image-text {
	height: auto;
	min-height: var(--rtm-cur-size, 44px);
}
.rtm-dyn-cursor.rtm-dyn-cursor--image {
	padding: var(--rtm-cur-pad, 0);
	min-width: 0;
	overflow: hidden;
}
.rtm-dyn-cursor__img {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 1;
}
.rtm-dyn-cursor__img img {
	display: block;
	width: var(--rtm-cur-img-size, 40px);
	height: var(--rtm-cur-img-size, 40px);
	object-fit: cover;
	border-radius: var(--rtm-cur-radius, 999px);
}

.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;
	}
}
