/* AP Floating Profile Showcase — transparent-background profile hero with
   floating animated cards. Loaded only on pages that use the widget. */

.ap-fps-wrap {
	position: relative;
	width: 100%;
	background: transparent;
	box-sizing: border-box;
}

.ap-fps-wrap * {
	box-sizing: border-box;
}

.ap-fps-stage {
	position: relative;
	width: 100%;
	max-width: 620px;
	margin: 0 auto;
	aspect-ratio: 1 / 1;
	display: flex;
	align-items: center;
	justify-content: flex-start;
}

/* Left-aligned box that holds the circle + headshot together, sized by the
   "Width" style control; floating cards are positioned as percentages of
   the full .ap-fps-stage so they can dock along the right edge, outside
   this box, matching the reference layout (person left, cards right). */
.ap-fps-visual {
	position: relative;
	width: 74%;
	aspect-ratio: 1 / 1;
	flex-shrink: 0;
	--ap-fps-img-x: 0px;
	--ap-fps-img-y: 0px;
	transform: translate3d(var(--ap-fps-img-x), var(--ap-fps-img-y), 0);
}

/* ---------------- Gradient circle & decorative glows ---------------- */
.ap-fps-circle {
	--ap-fps-c1: #9666ff;
	--ap-fps-c2: #1e1440;
	--ap-fps-circle-x: 0px;
	--ap-fps-circle-y: 0px;
	position: absolute;
	inset: 0;
	margin: auto;
	border-radius: 50%;
	background: radial-gradient(circle at 40% 35%, var(--ap-fps-c1) 0%, var(--ap-fps-c2) 72%);
	z-index: 0;
	pointer-events: none;
	will-change: transform;
	transform: translate(var(--ap-fps-circle-x), var(--ap-fps-circle-y));
}

.ap-fps-glow {
	position: absolute;
	border-radius: 50%;
	pointer-events: none;
	z-index: 0;
	background: radial-gradient(circle, rgba(255, 255, 255, .9) 0%, rgba(255, 255, 255, 0) 70%);
}

.ap-fps-glow-1 {
	width: 10px;
	height: 10px;
	top: 8%;
	left: 12%;
	opacity: .8;
	animation: ap-fps-twinkle 3s ease-in-out infinite;
}

.ap-fps-glow-2 {
	width: 6px;
	height: 6px;
	top: 20%;
	left: 82%;
	opacity: .6;
	animation: ap-fps-twinkle 4s ease-in-out infinite .8s;
}

.ap-fps-glow-3 {
	width: 8px;
	height: 8px;
	top: 78%;
	left: 8%;
	opacity: .7;
	animation: ap-fps-twinkle 3.6s ease-in-out infinite 1.4s;
}

span.ap-fps-rating-text {
	color: #ffffffc9;
}

@keyframes ap-fps-twinkle {

	0%,
	100% {
		opacity: .25;
		transform: scale(.8);
	}

	50% {
		opacity: .9;
		transform: scale(1.2);
	}
}

/* ---------------- Profile image ---------------- */
.ap-fps-image-wrap {
	position: relative;
	z-index: 1;
	width: 100%;
	height: 100%;
	overflow: hidden;
	will-change: transform;
	transform: translate3d(0, 0, 0);
}

.ap-fps-shape-circle {
	border-radius: 50%;
}

.ap-fps-shape-rounded {
	border-radius: 28px;
}

.ap-fps-image {
	width: 100%;
	height: 100%;
	display: block;
	object-fit: cover;
}

.ap-fps-tilt .ap-fps-image-wrap {
	transform: perspective(900px) rotateX(var(--ap-fps-tilt-x, 0deg)) rotateY(var(--ap-fps-tilt-y, 0deg));
	transition: transform .25s cubic-bezier(.22, .61, .36, 1);
}

/* ---------------- Floating cards ---------------- */
.ap-fps-card {
	position: absolute;
	z-index: 2;
	max-width: 90%;
	--ap-fps-rotate: 0deg;
	--ap-fps-scale: 1;
	--ap-fps-duration: 4s;
	--ap-fps-delay: 0s;
	--ap-fps-distance: 14px;
	transform: translate3d(0, 0, 0) rotate(var(--ap-fps-rotate)) scale(var(--ap-fps-scale));
	will-change: transform, opacity;
}

.ap-fps-card-inner {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 6px;
	background: rgba(20, 18, 45, .55);
	border: 1px solid rgba(255, 255, 255, .12);
	border-radius: 16px;
	padding: 12px 16px 12px 14px;
	backdrop-filter: blur(14px);
	-webkit-backdrop-filter: blur(14px);
	transition: transform .25s ease, box-shadow .25s ease, filter .25s ease;
}

.ap-fps-card-row {
	display: flex;
	align-items: center;
	gap: 10px;
}

.ap-fps-card-media {
	width: 32px;
	height: 32px;
	border-radius: 50%;
	object-fit: cover;
	flex-shrink: 0;
}

.ap-fps-card-icon {
	width: 32px;
	height: 32px;
	border-radius: 50%;
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 14px;
}

.ap-fps-card-icon svg {
	width: 1em;
	height: 1em;
	fill: currentColor;
}

.ap-fps-card-text {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

.ap-fps-card-title {
	font-size: 14px;
	line-height: 1.3;
	white-space: nowrap;
}

.ap-fps-card-subtitle {
	font-size: 11px;
	line-height: 1.3;
	white-space: nowrap;
}

.ap-fps-card-badge {
	position: absolute;
	top: -8px;
	right: -8px;
	font-size: 10px;
	font-weight: 700;
	line-height: 1.6;
	background: #f5b400;
	color: #1e1440;
	border-radius: 20px;
	padding: 2px 10px;
}

/* Avatars + rating combined into one row so a card can show either, or
   both side by side (avatars left, "5.0 (120+ Reviews)" + stars right),
   without repeating the title/subtitle row above it. */
.ap-fps-proof {
	display: flex;
	align-items: center;
	gap: 10px;
}

.ap-fps-rating {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.ap-fps-rating-top {
	display: flex;
	align-items: baseline;
	gap: 6px;
	font-size: 13px;
}

.ap-fps-rating-stars {
	font-size: 11px;
	letter-spacing: 1px;
	color: #f5b400;
}

.ap-fps-avatars {
	display: flex;
}

.ap-fps-avatars img {
	width: 26px;
	height: 26px;
	border-radius: 50%;
	object-fit: cover;
	border: 2px solid rgba(20, 18, 45, .9);
	margin-left: -8px;
}

.ap-fps-avatars img:first-child {
	margin-left: 0;
}

.ap-fps-card-button {
	align-self: flex-start;
	font-size: 12px;
	font-weight: 700;
	text-decoration: none;
	color: #fff;
	background: rgba(255, 255, 255, .15);
	border-radius: 20px;
	padding: 4px 14px;
	transition: background .2s ease, transform .2s ease;
}

.ap-fps-card-button:hover {
	background: rgba(255, 255, 255, .28);
}

/* ---------------- Hover micro-interactions ---------------- */
.ap-fps-hover-lift:hover .ap-fps-card-inner {
	transform: translateY(-4px);
}

.ap-fps-hover-glow:hover .ap-fps-card-inner {
	box-shadow: 0 0 24px rgba(150, 102, 255, .55);
}

/* ---------------- Continuous animations ---------------- */
.ap-fps-anim-float-y {
	animation: ap-fps-float-y var(--ap-fps-duration) ease-in-out var(--ap-fps-delay) infinite;
}

.ap-fps-anim-float-x {
	animation: ap-fps-float-x var(--ap-fps-duration) ease-in-out var(--ap-fps-delay) infinite;
}

.ap-fps-anim-rotate-slow {
	animation: ap-fps-rotate-slow calc(var(--ap-fps-duration) * 3) linear var(--ap-fps-delay) infinite;
}

.ap-fps-anim-pulse {
	animation: ap-fps-pulse var(--ap-fps-duration) ease-in-out var(--ap-fps-delay) infinite;
}

.ap-fps-anim-scale {
	animation: ap-fps-scale var(--ap-fps-duration) ease-in-out var(--ap-fps-delay) infinite;
}

.ap-fps-anim-fade {
	animation: ap-fps-fade var(--ap-fps-duration) ease-in-out var(--ap-fps-delay) infinite;
}

.ap-fps-anim-once {
	animation-iteration-count: 1;
}

/* Hover-only: JS toggles this class to start/stop the animation on demand. */
.ap-fps-anim-hover-only {
	animation-play-state: paused;
}

.ap-fps-anim-hover-only:hover,
.ap-fps-anim-hover-only.ap-fps-anim-playing {
	animation-play-state: running;
}

@keyframes ap-fps-float-y {

	0%,
	100% {
		transform: translate3d(0, 0, 0) rotate(var(--ap-fps-rotate)) scale(var(--ap-fps-scale));
	}

	50% {
		transform: translate3d(0, calc(var(--ap-fps-distance) * -1), 0) rotate(var(--ap-fps-rotate)) scale(var(--ap-fps-scale));
	}
}

@keyframes ap-fps-float-x {

	0%,
	100% {
		transform: translate3d(0, 0, 0) rotate(var(--ap-fps-rotate)) scale(var(--ap-fps-scale));
	}

	50% {
		transform: translate3d(var(--ap-fps-distance), 0, 0) rotate(var(--ap-fps-rotate)) scale(var(--ap-fps-scale));
	}
}

@keyframes ap-fps-rotate-slow {
	from {
		transform: translate3d(0, 0, 0) rotate(var(--ap-fps-rotate)) scale(var(--ap-fps-scale));
	}

	to {
		transform: translate3d(0, 0, 0) rotate(calc(var(--ap-fps-rotate) + 360deg)) scale(var(--ap-fps-scale));
	}
}

@keyframes ap-fps-pulse {

	0%,
	100% {
		transform: translate3d(0, 0, 0) rotate(var(--ap-fps-rotate)) scale(var(--ap-fps-scale));
	}

	50% {
		transform: translate3d(0, 0, 0) rotate(var(--ap-fps-rotate)) scale(calc(var(--ap-fps-scale) * 1.08));
	}
}

@keyframes ap-fps-scale {

	0%,
	100% {
		transform: translate3d(0, 0, 0) rotate(var(--ap-fps-rotate)) scale(calc(var(--ap-fps-scale) * 0.94));
	}

	50% {
		transform: translate3d(0, 0, 0) rotate(var(--ap-fps-rotate)) scale(calc(var(--ap-fps-scale) * 1.06));
	}
}

@keyframes ap-fps-fade {

	0%,
	100% {
		opacity: 1;
	}

	50% {
		opacity: .55;
	}
}

/* ---------------- Entrance animation ---------------- */
.ap-fps-entrance .ap-fps-card {
	opacity: 0;
	transform: translate3d(0, 16px, 0) rotate(var(--ap-fps-rotate)) scale(calc(var(--ap-fps-scale) * 0.92));
	transition: opacity var(--ap-fps-entrance-duration, .6s) ease, transform var(--ap-fps-entrance-duration, .6s) ease;
	transition-delay: var(--ap-fps-delay, 0s);
}

.ap-fps-entrance .ap-fps-card.ap-fps-inview {
	opacity: 1;
	transform: translate3d(0, 0, 0) rotate(var(--ap-fps-rotate)) scale(var(--ap-fps-scale));
}

/* Parallax drift applied by JS via translate custom properties, layered on
   top of the base transform through a wrapping translate. */
.ap-fps-parallax .ap-fps-card {
	transform: translate3d(var(--ap-fps-px, 0px), var(--ap-fps-py, 0px), 0) rotate(var(--ap-fps-rotate)) scale(var(--ap-fps-scale));
}

.ap-fps-parallax .ap-fps-anim-float-y,
.ap-fps-parallax .ap-fps-anim-float-x,
.ap-fps-parallax .ap-fps-anim-pulse,
.ap-fps-parallax .ap-fps-anim-scale,
.ap-fps-parallax .ap-fps-anim-rotate-slow {
	/* Keyframes already own transform while animating; parallax offset is
	   folded in by JS updating --ap-fps-px/py which the keyframes read via
	   translate3d(), so no extra rule needed here. */
}

@media (prefers-reduced-motion: reduce) {

	.ap-fps-card,
	.ap-fps-circle,
	.ap-fps-glow {
		animation: none !important;
		transition: none !important;
	}
}

@media (max-width: 1024px) {
	.ap-fps-stage {
		max-width: 460px;
	}
}

@media (max-width: 767px) {
	.ap-fps-stage {
		max-width: 340px;
	}

	.ap-fps-card-title {
		font-size: 12px;
	}

	.ap-fps-card-subtitle {
		font-size: 10px;
	}
}

/* Phones (up to 480px, safe down to 320px): free percentage-based
   positioning (Top/Left, arbitrary Width/Height/Rotation) cannot be made
   reliably non-overflowing on a ~300px-wide stage — any text length past a
   couple of words breaks it. Below this width the widget stops floating
   the cards over the photo and instead stacks the image and every card
   in normal document flow, full width, top to bottom. This is a hard
   layout change (not a tuning of the same absolute-position system), so:
   - `position: static` makes Elementor's per-card Top/Left output a no-op
     (top/left/z-index only affect positioned elements per the CSS spec),
     no !important fight needed for those.
   - `width`/`height`/`transform` (rotate, scale) and the continuous
     float/pulse/rotate animations DO still apply to static elements, so
     those are explicitly reset with !important, including neutralizing
     the animation itself first (a running animation's computed value
     always wins over a plain transform override, !important or not).
   - This block is plain CSS, so it applies identically on the real
     frontend and inside the Elementor editor canvas when its device
     toolbar is switched to Mobile (the canvas iframe is resized to the
     breakpoint width, which simply re-triggers this media query). */
@media (max-width: 480px) {
	.ap-fps-stage {
		display: flex;
		flex-direction: column;
		align-items: center;
		width: 100%;
		max-width: 320px;
		aspect-ratio: auto;
		gap: 10px;
	}

	.ap-fps-visual {
		width: 78%;
		max-width: 260px;
	}

	.ap-fps-card {
		position: static !important;
		animation: none !important;
		transform: none !important;
		width: 100% !important;
		max-width: 100% !important;
		height: auto !important;
		margin: 0 !important;
	}

	.ap-fps-card-inner {
		padding: 10px 14px;
		border-radius: 14px;
	}

	.ap-fps-card-title,
	.ap-fps-card-subtitle {
		white-space: normal;
	}

	.ap-fps-card-title { font-size: 13px; }
	.ap-fps-card-subtitle { font-size: 11px; }

	.ap-fps-proof { flex-wrap: wrap; row-gap: 6px; }

	/* Entrance reveal still works (opacity-only fade, no slide, since
	   transform is neutralized above) instead of being skipped entirely. */
	.ap-fps-entrance .ap-fps-card {
		transition: opacity var( --ap-fps-entrance-duration, .6s ) ease;
	}
}