.rds-ariana-mojave-quote {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: 100svh;
	padding: clamp(3rem, 8vh, 6rem) clamp(1.5rem, 6vw, 6rem);
	box-sizing: border-box;
	background: #111419;
}

.rds-ariana-mojave-quote__inner {
	display: flex;
	align-items: center;
	gap: clamp(1.25rem, 2.5vw, 2rem);
	width: 100%;
	max-width: 50rem;
	scale: 1.4;
}

.rds-ariana-mojave-quote__media {
	flex: 0 0 clamp(7rem, 13vw, 9rem);
	width: clamp(7rem, 13vw, 9rem);
	margin: 0;
	aspect-ratio: 1 / 1;
	border-radius: clamp(1rem, 2vw, 1.5rem);
	overflow: hidden;
	background: linear-gradient(180deg, #0578ff 0%, #d759ca 100%);
}

.rds-ariana-mojave-quote__media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: top center;
}

/* Rotating gradient ring (2026-08-16, "can we have linear gradient animate
   360 one loop. simple lite animation"). First attempt rotated an oversized
   `::before` pseudo-element behind the bubble via `transform: rotate()`,
   clipped to the pill shape by the bubble's own `overflow: hidden`/
   `clip-path` — confirmed via screenshot + git-stash A/B comparison that
   the gradient still visibly escaped the pill's rounded boundary during
   rotation regardless, most likely an interaction with this block's own
   `.rds-ariana-mojave-quote__inner { scale: 1.4; }` ancestor transform.
   Switched to animating the *gradient's own angle* instead of rotating a
   layer: `@property` registers the angle as a real animatable value, so
   `conic-gradient(from <angle>, ...)` can be keyframed directly. Nothing
   ever needs to be larger than its own box, so there's no oversized layer
   to escape in the first place — the escaping-bounds failure mode is
   structurally impossible here, not just clipped away. */
@property --rds-ariana-mojave-gradient-angle {
	syntax: '<angle>';
	inherits: false;
	initial-value: 257deg;
}

.rds-ariana-mojave-quote__bubble {
	position: relative;
	flex: 1 1 auto;
    padding: 12px;
    box-sizing: border-box;
    border-radius: 50px;
    overflow: hidden;
    background: conic-gradient(from var(--rds-ariana-mojave-gradient-angle), #0578FF, #D96AD4, #0578FF);
}

@media (prefers-reduced-motion: no-preference) {
	/* Gated on `.is-in-view` (2026-08-16, "what happened to gradient
	   animation. add back") instead of applying unconditionally — this
	   section sits at ~96% of the page's own height, so an animation that
	   starts the instant the page loads always finishes (a fixed 12s, 2 * 6s)
	   long before a real visitor scrolls this far down; nobody could ever
	   actually see it play. `assets/js/blocks/ariana-mojave-quote.js` now
	   adds this class via `IntersectionObserver` once the bubble reaches the
	   viewport's exact center. */

	/* Opacity 0 from the start (2026-08-16, "remove 1sec delay. have opacity
	   0 from start") — previously the bubble stayed at its normal, fully
	   visible default state until `.is-in-view` landed (deliberately, so a
	   JS failure degraded to "always visible" rather than "stuck invisible").
	   Explicitly requested the opposite now: hidden before the reveal, not
	   just during it. Scoped to this same `no-preference` query (not a bare
	   unconditional rule) so `prefers-reduced-motion: reduce` visitors — who
	   never get `.is-in-view`'s animation at all — still see the bubble
	   normally instead of a permanently invisible one. The JS module's own
	   `IntersectionObserver`-unsupported fallback was updated alongside this
	   to add `.is-in-view` immediately rather than bailing out, so that
	   specific edge case still reveals the content instead of leaving it
	   hidden forever. */
	.rds-ariana-mojave-quote__bubble {
		opacity: 0;
	}

	.rds-ariana-mojave-quote__bubble.is-in-view {
		/* 2 (not infinite, 2026-08-16, "update infinite to 2x loop") — each
		   iteration restarts cleanly at the same 257deg starting angle the
		   previous one ended on (see the keyframe's own comment), so 2 full
		   rotations then holding still reads as a deliberate, finite flourish
		   rather than a distracting always-on spin.
		   `-slam` runs alongside it (2026-08-16, "can we slam text container
		   in? similar to ios text slam animation") — an iOS Messages-style
		   "Slam" entrance: starts oversized and invisible, rockets down past
		   its resting size, overshoots slightly, settles with one more tiny
		   bounce. Both animations target different properties (spin only
		   touches the custom gradient-angle property, slam only touches
		   `transform`/`opacity`), so they run independently with no conflict
		   — no extra wrapper needed. `0.5s animation-delay` on both
		   (2026-08-16, first "remove 1sec delay" then "add half sec delay")
		   — `.is-in-view` still lands the instant the bubble crosses the
		   viewport's center; only the animations' own play heads wait half a
		   beat. Slam's `both` fill-mode keeps it pinned at its 0%-keyframe
		   hidden/oversized state through that delay, same as the base
		   `opacity: 0` rule above already covers before `.is-in-view` even
		   lands — no gap where the bubble could flash into an unintended
		   state. */
		animation:
			rds-ariana-mojave-quote-spin 6s linear 0.5s 2,
			rds-ariana-mojave-quote-slam 0.6s cubic-bezier(0.2, 0.85, 0.35, 1) 0.5s both;
	}
}

@keyframes rds-ariana-mojave-quote-slam {
	0% {
		transform: scale(2.4);
		opacity: 0;
	}

	55% {
		transform: scale(0.94);
		opacity: 1;
	}

	75% {
		transform: scale(1.05);
		opacity: 1;
	}

	90% {
		transform: scale(0.98);
		opacity: 1;
	}

	100% {
		/* `opacity: 1` explicit here, not just at 55% (2026-08-16, found
		   while verifying "opacity 0 from start" — with the base rule above
		   now setting `opacity: 0`, a 100%-keyframe that never re-states
		   opacity falls back to that *underlying* value per spec ("if a
		   property isn't set at 100%, the non-animated value is used"), so
		   the bubble was silently fading back out to invisible by the time
		   the animation finished — confirmed live, sampled every 50ms,
		   opacity rose to ~1 by 300ms then declined straight back to 0 by
		   600ms. Every keyframe from 55% onward now pins `opacity: 1`
		   explicitly so there's no implicit fallback to fade toward. */
		transform: scale(1);
		opacity: 1;
	}
}

@keyframes rds-ariana-mojave-quote-spin {
	/* 257deg -> 617deg (257 + 360, one full loop) so the animation ends on
	   the exact same rendered angle it started on (617deg mod 360 = 257deg)
	   — the loop restarts with no visible jump. */
	to {
		--rds-ariana-mojave-gradient-angle: 617deg;
	}
}

.rds-ariana-mojave-quote .rds-ariana-mojave-quote__quote.body-copy {
position: relative;
z-index: 1;
margin: 0;
    color: #ffffff;
    font-family: "Ember Modern Text", sans-serif;
    font-weight: 700;
    font-size: clamp(1.5rem, 1.9vw, 1.75rem);
    line-height: 1.4;
    background: #000;
    border-radius: 50px;
    padding: 20px;
}

@media (max-width: 767px) {
	.rds-ariana-mojave-quote {
		min-height: 0;
		padding: 3rem 1.5rem;
	}

	.rds-ariana-mojave-quote__inner {
		flex-direction: column;
		align-items: flex-start;
	}
}
