/* ============================================================
   RocketX Market Ticker
   ============================================================ */

.rx-ticker {
	border-radius: var(--rx-r-lg);
	border: 1px solid var(--rx-line);
	background: var(--rx-navy-700);
	overflow: hidden;
	font-variant-numeric: tabular-nums;
	font-feature-settings: 'tnum';
}

/* ---------- Header bar ---------- */
.rx-ticker__header {
	display: flex;
	align-items: center;
	padding: 0 16px;
	border-bottom: 1px solid var(--rx-line);
	gap: 12px;
	min-height: 52px;
}

/* ---------- Tab bar — underline indicator style ---------- */
.rx-ticker__tabs {
	display: flex;
	align-items: stretch;
	align-self: stretch;
	gap: 0;
	flex: 1;
}

.rx-ticker__tab {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 0 16px;
	color: rgba(255, 255, 255, 0.58);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	cursor: pointer;
	-webkit-user-select: none;
	user-select: none;
	position: relative;
	white-space: nowrap;
	transition: color 180ms ease;
}

/* The sliding underline indicator */
.rx-ticker__tab::after {
	content: '';
	position: absolute;
	bottom: 0;
	left: 0;
	right: 0;
	height: 2px;
	background: var(--rx-orange);
	border-radius: 2px 2px 0 0;
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform 240ms cubic-bezier(0.34, 1.2, 0.64, 1);
}

.rx-ticker__tab:hover:not(.is-active) {
	color: rgba(255, 255, 255, 0.6);
}

.rx-ticker__tab.is-active {
	color: #fff;
}

.rx-ticker__tab.is-active::after {
	transform: scaleX(1);
}

.rx-ticker__tab:focus-visible {
	outline: 2px solid var(--rx-orange);
	outline-offset: -2px;
}

/* Count badge */
.rx-ticker__tab-count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 15px;
	height: 15px;
	padding: 0 3px;
	border-radius: 3px;
	background: rgba(255, 255, 255, 0.05);
	color: rgba(255, 255, 255, 0.25);
	font-size: 9px;
	font-weight: 700;
	letter-spacing: 0;
	transition: background 180ms ease, color 180ms ease;
}

.rx-ticker__tab.is-active .rx-ticker__tab-count {
	background: rgba(220, 79, 44, 0.18);
	color: var(--rx-orange-300);
}

/* ---------- Connection badge ---------- */
.rx-ticker__badge {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	flex-shrink: 0;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	padding: 5px 12px;
	border-radius: var(--rx-r-pill);
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.08);
	white-space: nowrap;
	transition: color var(--rx-dur-base), border-color var(--rx-dur-base);
}

.rx-ticker__badge::before {
	content: '';
	display: block;
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: currentColor;
	flex-shrink: 0;
}

.rx-ticker__badge[data-status='live'] {
	color: #4ADE80;
	border-color: rgba(74, 222, 128, 0.22);
}

.rx-ticker__badge[data-status='live']::before {
	animation: rx-dot-pulse 2.2s ease-in-out infinite;
}

.rx-ticker__badge[data-status='connecting'] {
	color: var(--rx-orange-300);
	border-color: rgba(220, 79, 44, 0.22);
}

.rx-ticker__badge[data-status='offline'] {
	color: #FF8C8C;
	border-color: rgba(255, 140, 140, 0.22);
}

.rx-ticker__badge[data-status='closed'] {
	color: #FFC56E;
	border-color: rgba(255, 197, 110, 0.22);
}

/* Instrument-count label in the header (e.g. "270+ instruments") */
.rx-ticker__instruments {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.04em;
	color: var(--rx-orange-300);
	white-space: nowrap;
}

@media (max-width: 600px) {
	.rx-ticker__instruments { display: none; }
}

/* "as of HH:MM" stamp shown beside the badge when prices aren't live */
.rx-ticker__updated {
	flex-shrink: 0;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.58);
	white-space: nowrap;
}
.rx-ticker__updated:empty { display: none; }

/* Indicative (seed) marker on a symbol awaiting its first live tick */
.rx-ticker__seed {
	margin-left: 5px;
	color: var(--rx-orange-300);
	opacity: 0.7;
	font-weight: 700;
}

@keyframes rx-dot-pulse {
	0%, 100% { opacity: 1; transform: scale(1); }
	50%       { opacity: 0.3; transform: scale(0.7); }
}

/* ---------- Table body ---------- */
.rx-ticker__body {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

.rx-ticker__table {
	width: 100%;
	border-collapse: collapse;
	font-size: 13px;
}

/* ---------- Column headers ---------- */
.rx-ticker__th {
	padding: 8px 16px;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.55);
	border-bottom: 1px solid var(--rx-line);
	white-space: nowrap;
	text-align: left;
}

/* Symbol col shrinks to content; number cols share the remaining space */
.rx-ticker__th--symbol { width: 1%; }

.rx-ticker__th--bid,
.rx-ticker__th--ask,
.rx-ticker__th--mid,
.rx-ticker__th--spread { text-align: right; }

.rx-ticker__th--change { text-align: center; width: 60px; }

/* ---------- Data rows ---------- */
.rx-ticker__row {
	border-bottom: 1px solid rgba(255, 255, 255, 0.035);
	transition: background 120ms ease;
}

.rx-ticker__row:last-child { border-bottom: none; }

.rx-ticker__row:nth-child(even) {
	background: rgba(255, 255, 255, 0.012);
}

.rx-ticker__row:hover {
	background: rgba(255, 255, 255, 0.045) !important;
}

/* ── Directional flash — green for up, red for down ── */
.rx-ticker__row--flash {
	animation: rx-ticker-flash 1.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.rx-ticker__row--flash[data-dir='up'] {
	--rx-flash-start: rgba(74, 222, 128, 0.18);
}

.rx-ticker__row--flash[data-dir='down'] {
	--rx-flash-start: rgba(255, 140, 140, 0.18);
}

.rx-ticker__row--flash[data-dir='neutral'],
.rx-ticker__row--flash:not([data-dir]) {
	--rx-flash-start: rgba(220, 79, 44, 0.1);
}

@keyframes rx-ticker-flash {
	0%   { background: var(--rx-flash-start); }
	22%  { background: var(--rx-flash-start); } /* hold at peak */
	100% { background: transparent; }
}

/* ---------- Cells ---------- */
.rx-ticker__td {
	padding: 11px 16px;
	color: rgba(255, 255, 255, 0.78);
	white-space: nowrap;
}

.rx-ticker__td--symbol {
	width: 1%;
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.04em;
	color: #fff;
	padding-right: 28px;
	white-space: nowrap;
}

.rx-ticker__td--num {
	text-align: right;
	color: rgba(255, 255, 255, 0.88);
}

.rx-ticker__td--change {
	text-align: center;
	width: 60px;
}

/* ---------- Change direction pill ---------- */
.rx-ticker__dir {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 20px;
	border-radius: 5px;
	font-size: 9px;
	font-weight: 900;
	line-height: 1;
	letter-spacing: 0;
}

.rx-ticker__dir--up {
	color: #4ADE80;
	background: rgba(74, 222, 128, 0.12);
}

.rx-ticker__dir--down {
	color: #FF8C8C;
	background: rgba(255, 140, 140, 0.12);
}

.rx-ticker__dir--neutral {
	color: rgba(255, 255, 255, 0.2);
	background: rgba(255, 255, 255, 0.04);
}

/* ---------- Trend sparkline column ---------- */
/* Metric columns hug their content; the symbol column absorbs the leftover so
   the trend column can stay a fixed, moderate width (about half its old size). */
.rx-ticker__th--bid,
.rx-ticker__td--bid,
.rx-ticker__th--ask,
.rx-ticker__td--ask,
.rx-ticker__th--spread,
.rx-ticker__td--spread { width: 1%; }
.rx-ticker__th--symbol,
.rx-ticker__td--symbol { width: auto; }

.rx-ticker__th--spark { text-align: center; width: 300px; }
.rx-ticker__td--spark {
	width: 300px;
	padding-top: 6px;
	padding-bottom: 6px;
	vertical-align: middle;
}
.rx-ticker__spark-svg { display: block; width: 100%; height: 24px; overflow: visible; }
.rx-ticker__spark {
	fill: none;
	stroke-width: 1.8;
	stroke-linecap: round;
	stroke-linejoin: round;
	vector-effect: non-scaling-stroke;   /* crisp, even line despite the non-uniform stretch */
}
.rx-ticker__spark-area { stroke: none; }
.rx-ticker__spark-svg[data-dir='up']   .rx-ticker__spark      { stroke: #4ADE80; filter: drop-shadow(0 0 2px rgba(74, 222, 128, 0.45)); }
.rx-ticker__spark-svg[data-dir='down'] .rx-ticker__spark      { stroke: #FF8C8C; filter: drop-shadow(0 0 2px rgba(255, 140, 140, 0.45)); }
.rx-ticker__spark-svg[data-dir='up']   .rx-ticker__spark-area { fill: url(#rx-spark-grad-up); }
.rx-ticker__spark-svg[data-dir='down'] .rx-ticker__spark-area { fill: url(#rx-spark-grad-down); }

/* Keep the table tidy on small screens */
@media (max-width: 640px) {
	.rx-ticker__th--spark,
	.rx-ticker__td--spark { display: none; }

	/* Drop the up/down trend arrow — it's redundant with the per-row flash
	   colour, and reclaiming its fixed column lets the price data fit the
	   phone width without horizontal scroll. */
	.rx-ticker__th--change,
	.rx-ticker__td--change { display: none; }

	/* Let the "Spread (pips)" header wrap to two lines ("Spread" / "(pips)")
	   instead of forcing the column as wide as the whole label on one line. */
	.rx-ticker__th--spread {
		white-space: normal;
		line-height: 1.15;
	}
	/* Bottom-align headers so the single-line ones sit level with the second
	   line of the wrapped Spread header. */
	.rx-ticker__th { vertical-align: bottom; }

	/* Tighten horizontal padding so the columns fit ~360px screens. */
	.rx-ticker__th,
	.rx-ticker__td { padding-left: 10px; padding-right: 10px; }
	.rx-ticker__td--symbol { padding-right: 12px; }
}

/* ---------- Empty / loading ---------- */
.rx-ticker__empty {
	padding: 40px 16px;
	text-align: center;
	font-size: 12px;
	letter-spacing: 0.08em;
	color: rgba(255, 255, 255, 0.22);
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
	.rx-ticker__row--flash                     { animation: none; }
	.rx-ticker__badge[data-status]::before     { animation: none; }
}

/* ============================================================
   MT5-style Buy / Sell quote card  (.rx-quote-card)
   ============================================================ */
.rx-quote-card {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding: 14px 14px 12px;
	border-radius: var(--rx-r-lg);
	border: 1px solid var(--rx-line);
	background:
		linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0) 60%),
		var(--rx-navy-700, #11182b);
	-webkit-backdrop-filter: blur(14px);
	backdrop-filter: blur(14px);
	box-shadow: 0 18px 50px -22px rgba(0, 0, 0, 0.6);
	font-variant-numeric: tabular-nums;
	font-feature-settings: 'tnum';
	min-width: 210px;
	overflow: hidden;
}

.rx-quote-card__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 8px;
}

.rx-quote-card__sym {
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.04em;
	color: #fff;
}

.rx-quote-card__chg {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.02em;
}
.rx-quote-card__chg[data-dir='up']   { color: #4ADE80; }
.rx-quote-card__chg[data-dir='down'] { color: #FF8C8C; }
.rx-quote-card__chg[data-dir='flat'] { color: rgba(255, 255, 255, 0.35); }

/* ---- Buy / Sell faces ---- */
.rx-quote-card__quotes {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: stretch;
	gap: 6px;
}

/* Display-only price faces (not interactive) */
.rx-quote-card__side {
	display: flex;
	flex-direction: column;
	gap: 2px;
	padding: 8px 10px;
	border-radius: var(--rx-r-md, 10px);
	border: 1px solid transparent;
}

.rx-quote-card__side--sell {
	background: rgba(255, 140, 140, 0.07);
	border-color: rgba(255, 140, 140, 0.16);
	align-items: flex-start;
}

.rx-quote-card__side--buy {
	background: rgba(74, 222, 128, 0.07);
	border-color: rgba(74, 222, 128, 0.16);
	align-items: flex-end;
	text-align: right;
}

.rx-quote-card__side-label {
	font-size: 9px;
	font-weight: 800;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}
.rx-quote-card__side--sell .rx-quote-card__side-label { color: #FF8C8C; }
.rx-quote-card__side--buy  .rx-quote-card__side-label { color: #4ADE80; }

.rx-quote-card__price {
	font-size: 19px;
	font-weight: 700;
	line-height: 1.05;
	color: #fff;
	letter-spacing: -0.01em;
}

/* Spread chip between the two faces */
.rx-quote-card__spread {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	min-width: 42px;
	padding: 0 4px;
	color: rgba(255, 255, 255, 0.5);
}
.rx-quote-card__spread b {
	font-size: 13px;
	font-weight: 700;
	color: rgba(255, 255, 255, 0.82);
}
.rx-quote-card__spread small {
	font-size: 8px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	opacity: 0.6;
}

/* Sparkline */
.rx-quote-card__spark-wrap {
	height: 30px;
	margin: -2px 0;
}
.rx-quote-card__spark-wrap svg { display: block; width: 100%; height: 100%; }
.rx-quote-card__spark { fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.rx-quote-card__spark-wrap[data-dir='up']   .rx-quote-card__spark { stroke: #4ADE80; }
.rx-quote-card__spark-wrap[data-dir='down'] .rx-quote-card__spark { stroke: #FF8C8C; }

/* Footer: live status + last-updated time */
.rx-quote-card__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	font-size: 9.5px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}
.rx-quote-card__status {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	color: rgba(255, 255, 255, 0.4);
}
.rx-quote-card__status::before {
	content: '';
	width: 6px; height: 6px;
	border-radius: 50%;
	background: currentColor;
	flex-shrink: 0;
}
.rx-quote-card[data-state='live']   .rx-quote-card__status { color: #4ADE80; }
.rx-quote-card[data-state='live']   .rx-quote-card__status::before { animation: rx-dot-pulse 2.2s ease-in-out infinite; }
.rx-quote-card[data-state='closed'] .rx-quote-card__status { color: #FFC56E; }
.rx-quote-card[data-state='stale']  .rx-quote-card__status { color: rgba(255, 255, 255, 0.4); }
.rx-quote-card__time { color: rgba(255, 255, 255, 0.3); }

/* Tick flash on the whole card */
.rx-quote-card--flash[data-tick='up']::after,
.rx-quote-card--flash[data-tick='down']::after {
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
	animation: rx-card-flash 1.1s ease-out forwards;
}
.rx-quote-card--flash[data-tick='up']::after   { background: radial-gradient(120% 80% at 80% 0%, rgba(74, 222, 128, 0.16), transparent 70%); }
.rx-quote-card--flash[data-tick='down']::after { background: radial-gradient(120% 80% at 20% 0%, rgba(255, 140, 140, 0.16), transparent 70%); }

@keyframes rx-card-flash {
	0%   { opacity: 1; }
	100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
	.rx-quote-card--flash::after { animation: none; }
	.rx-quote-card__side:hover   { transform: none; }
}

/* ============================================================
   Front-page floating live cards (.rx-live-float)
   Desktop corners only — never shown where it could overlap
   hero content on tablet / mobile.
   ============================================================ */
.rx-live-float { display: none; }

/* The float layer is positioned against the FULL page height (cards sit at a
   % of page height), so it needs the page body as its containing block. */
body.rx-has-float { position: relative; }

@media (min-width: 1280px) {
	.rx-live-float {
		display: block;
		position: absolute;    /* spans the whole document, not just the viewport */
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;          /* = page height (body is position:relative) */
		overflow: hidden;      /* clip cards to the page so they never add scroll */
		z-index: 0;            /* background plane: same layer as bg-fx, behind page content */
		pointer-events: none;  /* purely ambient: the live data shows, nothing is clickable */
		perspective: 1600px;   /* gives the slot rotations real depth */
	}
	.rx-live-float__slot {
		position: absolute;    /* `top` is set inline as a % of page height */
		width: 340px;          /* chunky: a solid terminal panel, not a sliver */
		pointer-events: none;  /* never interactive: this is a background element */
		/* Resting look — bg-fx.js randomises these per slot on every page load.
		   With only 4 cards per page they carry more presence each: brighter
		   and near full-size, but still clearly behind the content plane. */
		--rx-float-opacity: 0.7;
		--rx-float-scale: 0.96;
		--rx-float-rot: 0deg;
		opacity: 0;
		/* Steady scale is driven LIVE by the custom property so bg-fx.js can
		   resize the card to fit the gutter at load AND on every window resize.
		   (It must NOT live in the entrance keyframe: a forwards-filled
		   animation resolves its var() once at start and then holds a stale
		   value, so later JS updates to --rx-float-scale would never show.)
		   The transition lets those JS-driven scale changes glide. */
		scale: var(--rx-float-scale, 0.94);
		transition: scale 0.45s cubic-bezier(0.22, 1, 0.36, 1);
		transform-style: preserve-3d;   /* keep the gentle tilt in 3D under the layer's perspective */
		--rx-par: 0px;         /* scroll-parallax offset, scrubbed by bg-fx.js (composed into transform below) */
		/* Independent properties, no conflicts: entrance animates opacity, the
		   live `scale` property (above) sizes the card, drift animates
		   translate/rotate, the static 3D tilt + scroll parallax live on
		   transform (parallax via --rx-par so GSAP never clobbers the tilt). */
		animation:
			rx-float-in 0.9s cubic-bezier(0.22, 1, 0.36, 1) forwards,
			rx-float-drift 17s ease-in-out infinite;
		filter: drop-shadow(0 26px 50px rgba(0, 0, 0, 0.5));
	}
	/* A "backing" panel pushed behind the card in 3D space (translateZ under
	   the layer's perspective) gives the glass real edge thickness instead of
	   reading as a flat sheet — a sliver of it peeks out along the tilted
	   side, like the edge of a beveled glass pane. */
	.rx-live-float__slot::before {
		content: '';
		position: absolute;
		inset: 0;
		border-radius: var(--rx-r-lg, 16px);
		background: linear-gradient(165deg, rgba(255, 255, 255, 0.06), rgba(0, 0, 0, 0.55));
		transform: translate(4px, 5px) translateZ(-10px);
		z-index: -1;
		/* Follows the sharp layer's mask (set inline by bg-fx.js on tight
		   gutters) so the backing slab never pokes out sharp where the card
		   itself has handed over to the blurred ghost. */
		-webkit-mask-image: var(--rx-slot-mask, none);
		mask-image: var(--rx-slot-mask, none);
	}
	/* Blurred twin of the card (cloned by bg-fx.js when the card runs under
	   the content column): revealed by an inverse mask exactly where the
	   sharp layer fades out, so the covered portion reads as depth-of-field —
	   present but soft, never competing with foreground elements. */
	.rx-live-float__ghost {
		position: absolute;
		inset: 0;
		filter: blur(7px) saturate(85%) brightness(0.85);
		opacity: 0.6;
		pointer-events: none;
	}
	/* A gentle, glass-HUD lean — just enough dimension to read as 3D, not slanted.
	   translateY(var(--rx-par)) is the scroll parallax; the rotations are the tilt.
	   Side is an explicit class from PHP (seed-shuffled, independent of card
	   type) rather than nth-child odd/even — nth-child tracked the same
	   parity as the quote/viz type alternation, so every quote card ended up
	   on one side and every viz card on the other. */
	/* The clamp() side pin is only the no-JS fallback — bg-fx.js overrides it
	   inline, placing each card fully on-screen in the measured gutter beside
	   the content column (fading its inner edge with a mask when the gutter
	   is tight, hiding it when there's no meaningful room) so cards never
	   read as cut off or sit on top of foreground sections. */
	.rx-live-float__slot--right { right: clamp(24px, 4vw, 72px); transform: translateY(var(--rx-par)) rotateY(calc(-7deg + var(--rx-float-rot))) rotateX(2deg); }
	.rx-live-float__slot--left  { left:  clamp(24px, 4vw, 72px); transform: translateY(var(--rx-par)) rotateY(calc(7deg + var(--rx-float-rot)))  rotateX(2deg); }
	/* Desync the drift + entrance (delay AND duration) so the cards never
	   move in unison — each floats on its own slow orbit. */
	.rx-live-float__slot:nth-child(3n)   { animation-delay: 0.50s,  -4s; animation-duration: 0.9s, 26s; }
	.rx-live-float__slot:nth-child(3n+1) { animation-delay: 0.35s,  -9s; animation-duration: 0.9s, 21s; }
	.rx-live-float__slot:nth-child(3n+2) { animation-delay: 0.60s, -13s; animation-duration: 0.9s, 24s; }

	/* Glassmorphism boost, floating instances only: frostier, softly lit, glowing.
	   Border thickened and shadow deepened (vs. the base .rx-quote-card) so the
	   panel reads as a slab of glass with real depth, not a flat decal. */
	.rx-live-float .rx-quote-card {
		min-width: 0;
		width: 100%;
		background:
			linear-gradient(150deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0.02) 55%),
			rgba(13, 19, 38, 0.42);
		-webkit-backdrop-filter: blur(22px) saturate(135%);
		backdrop-filter: blur(22px) saturate(135%);
		border-width: 1.5px;
		border: 1px solid rgba(255, 255, 255, 0.16);
		box-shadow:
			inset 0 1px 0 rgba(255, 255, 255, 0.22),
			inset 0 0 0 1px rgba(255, 255, 255, 0.04),
			0 24px 60px -28px rgba(0, 0, 0, 0.7),
			0 0 60px -20px rgba(220, 79, 44, 0.18);
	}
	/* Cyan glow on every third card so the run isn't all orange. */
	.rx-live-float__slot:nth-child(3n+2) .rx-quote-card,
	.rx-live-float__slot:nth-child(3n+2) .rx-viz-card {
		box-shadow:
			inset 0 1px 0 rgba(255, 255, 255, 0.22),
			inset 0 0 0 1px rgba(255, 255, 255, 0.04),
			0 24px 60px -28px rgba(0, 0, 0, 0.7),
			0 0 60px -20px rgba(43, 183, 240, 0.18);
	}
	/* Chunkier: roomier padding and a bigger price so the card reads as a
	   real terminal module at a glance, not a shrunken widget. */
	.rx-live-float .rx-quote-card { padding: 18px 20px 15px; gap: 12px; }
	.rx-live-float .rx-quote-card__price { font-size: 20px; letter-spacing: -0.02em; }

	/* Abstract chart panels (candles / market depth / momentum / volume),
	   interleaved with the live quote cards for variety. Decorative texture
	   only — no real data, so the card is aria-hidden in markup. Shares the
	   quote card's glass shell for visual consistency. */
	.rx-viz-card {
		width: 100%;
		padding: 18px 20px 16px;
		background:
			linear-gradient(150deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0.02) 55%),
			rgba(13, 19, 38, 0.42);
		-webkit-backdrop-filter: blur(22px) saturate(135%);
		backdrop-filter: blur(22px) saturate(135%);
		border: 1.5px solid rgba(255, 255, 255, 0.16);
		border-radius: 16px;
		box-shadow:
			inset 0 1px 0 rgba(255, 255, 255, 0.22),
			inset 0 0 0 1px rgba(255, 255, 255, 0.04),
			0 24px 60px -28px rgba(0, 0, 0, 0.7);
	}
	/* Terminal-module header: hairline divider + bordered timeframe chip,
	   like a platform widget's title bar — not a floating caption. */
	.rx-viz-card__head {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding-bottom: 9px;
		margin-bottom: 12px;
		border-bottom: 1px solid rgba(255, 255, 255, 0.08);
	}
	.rx-viz-card__label {
		font-size: 12px;
		font-weight: 700;
		letter-spacing: 0.02em;
		color: rgba(255, 255, 255, 0.85);
	}
	.rx-viz-card__tag {
		font-size: 10px;
		font-weight: 600;
		text-transform: uppercase;
		letter-spacing: 0.08em;
		color: rgba(255, 255, 255, 0.55);
		padding: 2px 7px;
		border: 1px solid rgba(255, 255, 255, 0.14);
		border-radius: 6px;
	}
	.rx-viz-card__chart {
		position: relative;
		height: 86px;
		overflow: visible;
		/* Faint plot-area gridlines — chart furniture, reads as a terminal. */
		background-image:
			linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px),
			linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
		background-size: 25% 33.4%;
	}
	.rx-viz-card__chart .rx-bg-fx__viz { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0.85; }
	.rx-viz-card__chart .rx-bg-fx__viz polyline,
	.rx-viz-card__chart .rx-bg-fx__viz line {
		fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
	}
	.rx-viz-card__chart .rx-bg-fx__viz rect,
	.rx-viz-card__chart .rx-bg-fx__viz circle { fill: currentColor; stroke: none; }
	.rx-viz-card__chart .rx-bg-fx__viz .rx-bg-fx__node-line { stroke-width: 1; opacity: 0.5; }
	.rx-viz-card__chart .rx-bg-fx__osc-slow { opacity: 0.5; }

	/* Guide lines (last price, RSI 30/70 bands, volume baseline, depth mid):
	   the dashed chart furniture that makes a panel read as an actual
	   terminal module. Always steel — never a decorative colour. */
	.rx-viz-card__chart .rx-viz-guide {
		stroke: rgba(255, 255, 255, 0.28);
		stroke-width: 1;
		stroke-dasharray: 4 4;
		fill: none;
	}
	.rx-viz-card__chart .rx-viz-guide--last { stroke: rgba(255, 197, 110, 0.55); }

	/* Restrained, professional palette: semantic green/red where direction
	   means something, steel for structure, a single brand-orange accent —
	   no rainbow tints. */
	.rx-viz-card--candles .rx-candle--up   { color: #3FBE74; }
	.rx-viz-card--candles .rx-candle--down { color: #E06A6A; }
	.rx-viz-card--depth .rx-depth-bid { fill: rgba(74, 222, 128, 0.55); }
	.rx-viz-card--depth .rx-depth-ask { fill: rgba(255, 122, 122, 0.5); }
	.rx-viz-card--oscillator { color: rgba(255, 255, 255, 0.55); }
	.rx-viz-card--oscillator .rx-bg-fx__osc-fast { stroke: var(--rx-orange-300, #F08566); opacity: 1; }
	.rx-viz-card--bars { color: rgba(255, 255, 255, 0.35); }
	.rx-viz-card--bars .rx-viz-accent { fill: var(--rx-orange-300, #F08566); }
}

/* A touch more room on very wide screens */
@media (min-width: 1700px) {
	.rx-live-float__slot { width: 360px; }
}

/* Registered so the scroll-parallax offset interpolates as a real length. */
@property --rx-par {
	syntax: '<length>';
	inherits: false;
	initial-value: 0px;
}

@keyframes rx-float-in {
	/* Fade to the per-slot resting opacity (randomised by bg-fx.js). Scale is
	   deliberately NOT animated here — it's a live property on the slot so JS
	   can resize the card to the gutter after this animation has finished. */
	to { opacity: var(--rx-float-opacity, 0.55); }
}

/* Zero-gravity drift: a slow, lazy loop on BOTH axes with a whisper of
   rotation, so cards feel untethered rather than bobbing on a spring.
   Uses the individual `translate`/`rotate` properties so it layers cleanly
   over the static 3D transform tilt (which lives on `transform`). */
@keyframes rx-float-drift {
	0%, 100% { translate: 0 0;           rotate: 0deg; }
	25%      { translate: 9px -15px;     rotate: 0.8deg; }
	50%      { translate: -7px -24px;    rotate: -0.5deg; }
	75%      { translate: -11px 7px;     rotate: 0.6deg; }
}

@media (prefers-reduced-motion: reduce) {
	.rx-live-float__slot { animation: none; opacity: var(--rx-float-opacity, 0.55); scale: var(--rx-float-scale, 0.9); }
}
