/* VeloxityScreens Slots Game widget */

.vlx-slots-widget {
	position: relative;
	width: var(--vlx-slots-screen-width, 1080px);
	height: var(--vlx-slots-screen-height, 1920px);
	overflow: hidden;
	background: #0c0f1e;
	font-family: inherit;
	-webkit-user-select: none;
	user-select: none;
	touch-action: manipulation;
}

.vlx-slots-widget [x-cloak] {
	display: none !important;
}

/* ------------------------------ preloader ------------------------------ */

.vlx-slots-preloader {
	position: absolute;
	inset: 0;
	z-index: 60;
	display: flex;
	align-items: center;
	justify-content: center;
	background: #0c0f1e;
}

.vlx-slots-preloader-box {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 18px;
	color: #fff;
}

.vlx-slots-spinner {
	width: 64px;
	height: 64px;
	border: 6px solid rgba(255, 255, 255, 0.18);
	border-top-color: #f5c542;
	border-radius: 50%;
	animation: vlx-slots-spin 0.9s linear infinite;
}

@keyframes vlx-slots-spin {
	to { transform: rotate(360deg); }
}

.vlx-slots-preloader-label {
	font-size: 28px;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.vlx-slots-preloader-track {
	width: 280px;
	height: 8px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.15);
	overflow: hidden;
}

.vlx-slots-preloader-track span {
	display: block;
	height: 100%;
	background: #f5c542;
	border-radius: 999px;
	transition: width 0.2s ease;
}

.vlx-slots-preloader-percent {
	font-size: 20px;
	opacity: 0.7;
}

/* -------------------------------- stage -------------------------------- */

.vlx-slots-stage {
	position: absolute;
	inset: 0;
	overflow: hidden;
	background-size: cover;
	background-position: center;
}

.vlx-slots-bg-video {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	pointer-events: none;
}

/* -------------------------------- reels -------------------------------- */

.vlx-slots-reels {
	position: absolute;
	--vlx-slots-reel-gap: 24px;
}

.vlx-slots-reels-track {
	display: flex;
	gap: var(--vlx-slots-reel-gap);
	width: 100%;
	height: calc(var(--vlx-slots-symbol-size, 220px) * var(--vlx-slots-visible-rows, 3));
}

/*
 * Rounding the whole bank means rounding the OUTER corners of the end reels.
 * Done that way it needs no clipping, so the separators keep the vertical
 * overhang they are drawn with — clipping the track to a rounded box would
 * shear their ends off.
 *
 * The corner values are written by the Reel block radius control straight onto
 * the end reels. That is deliberate: Elementor prefixes its own selectors with
 * the element id, so a stylesheet rule here could never outrank the per-reel
 * radius it needs to override. The control targets :first-of-type /
 * :last-of-type because Alpine leaves its x-for <template> in the DOM as the
 * track's first child.
 */

.vlx-slots-reel {
	position: relative;
	flex: 1 1 0;
	height: 100%;
	/* The inner viewport does the clipping now, so separators are free to sit
	   in the gap outside the reel box. */
	overflow: visible;
	background-color: #f7f3e8;
	background-image: var(--vlx-slots-reel-bg-image, none);
	background-size: cover;
	background-position: center;
}

/*
 * The strip can be tens of thousands of pixels tall, so the motion-blur
 * filter is applied to this window-sized viewport instead — the blurred
 * (rasterized) area stays constant no matter how long the strip is.
 */
.vlx-slots-reel-viewport {
	position: absolute;
	inset: 0;
	overflow: hidden;
	border-radius: inherit;
}

.vlx-slots-strip {
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	transform: translate3d(0, 0, 0);
}

.vlx-slots-filters {
	position: absolute;
	width: 0;
	height: 0;
	pointer-events: none;
}

.vlx-slots-symbol {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	box-sizing: border-box;
	/* The drum curvature shifts the artwork inside its cell. Clipping to the
	   cell guarantees a symbol can never bleed into a neighbouring row, which
	   would read as a duplicate peeking in at the top or bottom of the reel. */
	overflow: hidden;
}

.vlx-slots-symbol img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	pointer-events: none;
	will-change: filter;
}

/*
 * Reel volume. A physical reel is a drum turning on a horizontal axis, so it
 * falls away into shadow at the top and bottom, catches a specular band across
 * the middle, and sits recessed in its housing. These layers sell that
 * without touching the symbols themselves.
 */
.vlx-slots-gloss {
	position: absolute;
	inset: 0;
	pointer-events: none;
	/* Clips the housing-shadow bands to the reel's rounded shape — see the
	   note on those bands below. */
	overflow: hidden;
	/*
	 * Everything here is curved rather than banded. A drum has no edges to
	 * outline, so there is no rim stroke: the volume comes from an elliptical
	 * specular that bows across the face, barrel shading that deepens toward
	 * the top and bottom, and soft occlusion where the surface meets the
	 * housing.
	 */
	background:
		/* bowed specular — an ellipse, so the highlight curves like a drum */
		radial-gradient(
			ellipse 155% 22% at 50% 47%,
			rgba(255, 255, 255, calc(var(--vlx-slots-reel-sheen, 0.2) * 1.45)) 0%,
			rgba(255, 255, 255, calc(var(--vlx-slots-reel-sheen, 0.2) * 0.55)) 42%,
			transparent 78%
		),
		/* barrel shading: the surface rolls away from the light on a curve */
		radial-gradient(
			ellipse 190% 118% at 50% 50%,
			transparent 38%,
			rgba(0, 0, 0, calc(var(--vlx-slots-reel-depth, 0.35) * 0.22)) 70%,
			rgba(0, 0, 0, calc(var(--vlx-slots-reel-depth, 0.35) * 0.72)) 100%
		),
		/* the last sliver before the drum disappears into the machine */
		linear-gradient(
			to bottom,
			rgba(0, 0, 0, calc(var(--vlx-slots-reel-depth, 0.35) * 0.8)) 0%,
			rgba(0, 0, 0, calc(var(--vlx-slots-reel-depth, 0.35) * 0.22)) 9%,
			transparent 20%
		),
		linear-gradient(
			to top,
			rgba(0, 0, 0, calc(var(--vlx-slots-reel-depth, 0.35) * 0.8)) 0%,
			rgba(0, 0, 0, calc(var(--vlx-slots-reel-depth, 0.35) * 0.22)) 9%,
			transparent 20%
		),
		/* soft contact occlusion at the sides — blurred, never a drawn line */
		linear-gradient(
			to right,
			rgba(0, 0, 0, calc(var(--vlx-slots-reel-depth, 0.35) * 0.3)) 0%,
			transparent 7%,
			transparent 93%,
			rgba(0, 0, 0, calc(var(--vlx-slots-reel-depth, 0.35) * 0.3)) 100%
		);
	border-radius: inherit;
}

.vlx-slots-reel {
	box-shadow:
		0 8px 20px rgba(0, 0, 0, 0.32),
		0 1px 0 rgba(255, 255, 255, 0.12);
}

/*
 * Housing shadow where the drum passes behind the machine's opening.
 *
 * Inheriting the reel's radius is not enough on its own. These bands are only
 * a few px tall, and CSS clamps a corner radius to fit its own box — so a 70px
 * reel corner becomes a ~14px corner on the band, and the difference paints
 * outside the reel's curve. Clipping the gloss to the reel's shape is what
 * actually makes the shadow follow the corner, whatever radius is set on the
 * reel or on the whole block.
 */
.vlx-slots-reel.has-rim .vlx-slots-gloss::before,
.vlx-slots-reel.has-rim .vlx-slots-gloss::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	height: var(--vlx-slots-reel-rim-size, 14px);
	pointer-events: none;
	background: linear-gradient(
		to bottom,
		var(--vlx-slots-reel-rim-color, rgba(0, 0, 0, 0.55)) 0%,
		rgba(0, 0, 0, 0.12) 62%,
		transparent 100%
	);
}

.vlx-slots-reel.has-rim .vlx-slots-gloss::before {
	top: 0;
	border-top-left-radius: inherit;
	border-top-right-radius: inherit;
}

.vlx-slots-reel.has-rim .vlx-slots-gloss::after {
	bottom: 0;
	border-bottom-left-radius: inherit;
	border-bottom-right-radius: inherit;
	transform: scaleY(-1);
}

/*
 * Separators sit in the flex gap between reels, so each drum reads as its own
 * physical unit in the housing rather than one continuous panel.
 */
.vlx-slots-reels-track.has-separators .vlx-slots-reel:not(:last-child)::after {
	content: '';
	position: absolute;
	top: calc(-1 * var(--vlx-slots-separator-overhang, 6px));
	bottom: calc(-1 * var(--vlx-slots-separator-overhang, 6px));
	right: calc(-1 * (var(--vlx-slots-reel-gap, 24px) / 2) - (var(--vlx-slots-separator-width, 10px) / 2));
	width: var(--vlx-slots-separator-width, 10px);
	border-radius: calc(var(--vlx-slots-separator-width, 10px) / 2);
	pointer-events: none;
	z-index: 4;
	background:
		linear-gradient(
			to bottom,
			rgba(0, 0, 0, 0.45) 0%,
			rgba(255, 255, 255, 0.14) 18%,
			rgba(255, 255, 255, 0.02) 50%,
			rgba(0, 0, 0, 0.45) 100%
		),
		linear-gradient(
			to right,
			color-mix(in srgb, var(--vlx-slots-separator-color, #b98b3c) 45%, #000) 0%,
			var(--vlx-slots-separator-color, #b98b3c) 32%,
			color-mix(in srgb, var(--vlx-slots-separator-color, #b98b3c) 55%, #fff) 50%,
			var(--vlx-slots-separator-color, #b98b3c) 68%,
			color-mix(in srgb, var(--vlx-slots-separator-color, #b98b3c) 45%, #000) 100%
		);
	box-shadow:
		0 0 10px rgba(0, 0, 0, 0.5),
		inset 0 0 0 1px rgba(255, 255, 255, 0.16);
}

/* ----------------------------- payline FX ------------------------------ */

.vlx-slots-payline-fx {
	position: absolute;
	inset: 0;
	overflow: hidden;
	pointer-events: none;
	z-index: 3;
}

/* ------------------------ payline highlight ---------------------------- */

/*
 * Marks the winning row once the reels have come to rest.
 *
 * Two pieces on purpose. The FILL is one band per reel, sitting inside that
 * reel's viewport and before the strip in document order, so the symbols paint
 * over it — a single overlay could only ever tint on top of the icons. The
 * OUTLINE is one element across the whole block, so it runs unbroken through
 * the gaps between reels the way a drawn-on payline does.
 *
 * Both are placed with `top`, not a transform, so GSAP owns transform outright
 * and can scale them on entry without fighting a translate for the centring.
 */
.vlx-slots-payline-band,
.vlx-slots-payline-outline {
	position: absolute;
	left: 0;
	right: 0;
	top: calc(50% - (var(--vlx-slots-symbol-size, 220px) / 2));
	height: var(--vlx-slots-symbol-size, 220px);
	box-sizing: border-box;
	pointer-events: none;
	opacity: 0;
}

.vlx-slots-payline-band {
	background: var(--vlx-slots-payline-fill, rgba(255, 214, 110, 0.3));
	border-radius: var(--vlx-slots-payline-radius, 18px);
}

.vlx-slots-payline-outline {
	border: var(--vlx-slots-payline-thickness, 4px) solid var(--vlx-slots-payline-color, #ffd66e);
	border-radius: var(--vlx-slots-payline-radius, 18px);
	box-shadow: 0 0 var(--vlx-slots-payline-glow, 18px) var(--vlx-slots-payline-color, #ffd66e);
}

.vlx-slots-burst {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 150%;
	height: 150%;
	transform: translate(-50%, -50%) scale(0.2);
	opacity: 0;
	border-radius: 50%;
	background: radial-gradient(
		circle,
		rgba(255, 222, 140, 0.55) 0%,
		rgba(255, 190, 60, 0.28) 32%,
		rgba(255, 170, 40, 0.10) 52%,
		transparent 70%
	);
}

.vlx-slots-shine {
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	width: 26%;
	opacity: 0;
	background: linear-gradient(
		100deg,
		transparent 0%,
		rgba(255, 255, 255, 0.10) 35%,
		rgba(255, 255, 255, 0.55) 50%,
		rgba(255, 255, 255, 0.10) 65%,
		transparent 100%
	);
}

.vlx-slots-reel-frame {
	position: absolute;
	inset: -40px;
	width: calc(100% + 80px);
	height: calc(100% + 80px);
	pointer-events: none;
	object-fit: fill;
}

/* ------------------------------- buttons ------------------------------- */

.vlx-slots-widget .vlx-slots-button {
	position: absolute;
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	padding: 22px 30px;
	border: 0;
	border-radius: 999px;
	background: #f5c542;
	color: #111;
	font-size: 40px;
	font-weight: 800;
	letter-spacing: 0.06em;
	cursor: pointer;
	transition: transform 0.12s ease, opacity 0.2s ease;
	z-index: 10;
}

.vlx-slots-widget .vlx-slots-button:active {
	transform: scale(0.96);
}

/*
 * Optional outline around the label.
 *
 * `paint-order: stroke fill` matters here: without it the stroke is centred on
 * the glyph edge and eats half its width inward, so bold type visibly thins as
 * the stroke grows. Painting the stroke first and the fill over it keeps the
 * letterform intact and puts the whole outline outside.
 *
 * Width defaults to 0, so nothing renders until it is set.
 */
.vlx-slots-widget .vlx-slots-button,
.vlx-slots-widget .vlx-slots-win-button {
	-webkit-text-stroke: var(--vlx-slots-btn-text-stroke, 0) var(--vlx-slots-btn-text-stroke-color, #000);
	paint-order: stroke fill;
}

/* ----------------------------- button skins ----------------------------- */

/*
 * Ready-made looks built from a base colour, a depth amount and an optional
 * shadow colour — so a client can keep the style but recolour it. Each skin
 * owns background, border and shadow (hence !important, they replace whatever
 * the style controls set); padding, typography and text colour are left alone
 * so those controls keep working on top.
 *
 * The depth each skin casts — the solid lip on glossy and pressed, the glow on
 * neon, the drop shadow on metal and glass — reads --vlx-slots-btn-shadow when
 * it is set, and otherwise derives from the base colour exactly as before. So
 * leaving the shadow control empty keeps the old look byte for byte.
 */
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button)[class*='is-style-']:not(.is-transparent-hitbox) {
	/* No `position` here on purpose. Stage buttons are already absolutely
	   placed by their own rule, and the popup button sits in normal flow —
	   forcing absolute here would tear it out of the popup's layout. Each
	   context supplies its own positioning below. */
	overflow: hidden;
	isolation: isolate;
	border: 0 !important;
	transition: transform 0.09s ease, box-shadow 0.09s ease, filter 0.2s ease;
}

/* The skins' sweep highlight is absolutely positioned, so a skinned popup
   button has to establish its own containing block. */
.vlx-slots-widget .vlx-slots-win-button[class*='is-style-'] {
	position: relative;
}

/* A slow highlight travelling across the face, shared by the lit skins. */
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-glossy:not(.is-transparent-hitbox)::after,
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-metal:not(.is-transparent-hitbox)::after,
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-glass:not(.is-transparent-hitbox)::after {
	content: '';
	position: absolute;
	top: -60%;
	bottom: -60%;
	width: 28%;
	left: -40%;
	background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.55), transparent);
	transform: skewX(-18deg);
	pointer-events: none;
	animation: vlx-slots-btn-sweep 4.5s ease-in-out infinite;
}

@keyframes vlx-slots-btn-sweep {
	0%, 62% { left: -40%; opacity: 0; }
	68% { opacity: 1; }
	100% { left: 130%; opacity: 0; }
}

/*
 * Glossy — a domed, candy-like face.
 *
 * All three stops are settable, not just the middle one. The old bottom stop
 * was mixed 74% toward pure black, which drags a saturated hue through grey on
 * the way down and reads as dirty — worst on yellows and oranges. The default
 * now stays close to the base colour, and any stop can be overridden outright.
 */
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-glossy:not(.is-transparent-hitbox) {
	background:
		linear-gradient(
			to bottom,
			var(--vlx-slots-btn-glossy-top, color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 80%, #fff)) 0%,
			var(--vlx-slots-btn-color, #f5c542) var(--vlx-slots-btn-glossy-split, 46%),
			var(--vlx-slots-btn-glossy-bottom, color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 88%, #000)) 100%
		) !important;
	box-shadow:
		inset 0 2px 0 rgba(255, 255, 255, 0.75),
		inset 0 -3px 8px rgba(0, 0, 0, calc(var(--vlx-slots-btn-depth, 0.5) * 0.4)),
		0 calc(var(--vlx-slots-btn-depth, 0.5) * 14px) calc(var(--vlx-slots-btn-depth, 0.5) * 26px) rgba(0, 0, 0, 0.42),
		0 calc(var(--vlx-slots-btn-depth, 0.5) * 5px) 0 var(--vlx-slots-btn-shadow, color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 48%, #000)) !important;
}

/* Metal — brushed plate with a bright band across the middle. */
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-metal:not(.is-transparent-hitbox) {
	background:
		linear-gradient(
			to bottom,
			color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 55%, #000) 0%,
			color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 88%, #fff) 34%,
			#fff 50%,
			color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 88%, #fff) 62%,
			color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 45%, #000) 100%
		) !important;
	box-shadow:
		inset 0 0 0 2px color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 55%, #fff),
		inset 0 3px 6px rgba(255, 255, 255, 0.5),
		0 calc(var(--vlx-slots-btn-depth, 0.5) * 12px) calc(var(--vlx-slots-btn-depth, 0.5) * 22px) var(--vlx-slots-btn-shadow, rgba(0, 0, 0, 0.5)) !important;
}

/* Pressed — a hard bottom edge the button drops onto, like a real key. */
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-pressed:not(.is-transparent-hitbox) {
	background: var(--vlx-slots-btn-color, #f5c542) !important;
	box-shadow:
		inset 0 3px 0 rgba(255, 255, 255, 0.45),
		0 calc(var(--vlx-slots-btn-depth, 0.5) * 12px) 0 var(--vlx-slots-btn-shadow, color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 42%, #000)),
		0 calc(var(--vlx-slots-btn-depth, 0.5) * 14px) calc(var(--vlx-slots-btn-depth, 0.5) * 18px) rgba(0, 0, 0, 0.45) !important;
}

/* Neon — dark body, glowing rim that breathes. */
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-neon:not(.is-transparent-hitbox) {
	background: rgba(8, 10, 22, 0.82) !important;
	box-shadow:
		inset 0 0 0 2px var(--vlx-slots-btn-color, #f5c542),
		inset 0 0 calc(var(--vlx-slots-btn-depth, 0.5) * 26px) var(--vlx-slots-btn-shadow, color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 45%, transparent)),
		0 0 calc(var(--vlx-slots-btn-depth, 0.5) * 22px) var(--vlx-slots-btn-shadow, color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 65%, transparent)) !important;
	/* Dark body needs light text — overridden the moment a colour is set. */
	color: color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 30%, #fff);
	text-shadow: 0 0 calc(var(--vlx-slots-btn-depth, 0.5) * 16px) var(--vlx-slots-btn-color, #f5c542);
	animation: vlx-slots-btn-neon 2.4s ease-in-out infinite;
}

.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-glass:not(.is-transparent-hitbox) {
	color: #fff;
	text-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
}

@keyframes vlx-slots-btn-neon {
	0%, 100% { filter: brightness(1); }
	50% { filter: brightness(1.28); }
}

/* Glass — translucent panel with a bright rim. */
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-glass:not(.is-transparent-hitbox) {
	background:
		linear-gradient(
			to bottom,
			color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 42%, transparent) 0%,
			color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 20%, transparent) 55%,
			color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 38%, transparent) 100%
		) !important;
	backdrop-filter: blur(9px);
	-webkit-backdrop-filter: blur(9px);
	box-shadow:
		inset 0 0 0 1.5px rgba(255, 255, 255, 0.55),
		inset 0 2px 10px rgba(255, 255, 255, 0.35),
		0 calc(var(--vlx-slots-btn-depth, 0.5) * 12px) calc(var(--vlx-slots-btn-depth, 0.5) * 24px) var(--vlx-slots-btn-shadow, rgba(0, 0, 0, 0.4)) !important;
}

/* Press feedback: each skin settles onto its own shadow. */
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-glossy:not(.is-transparent-hitbox):active,
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-metal:not(.is-transparent-hitbox):active,
.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-glass:not(.is-transparent-hitbox):active {
	transform: translateY(calc(var(--vlx-slots-btn-depth, 0.5) * 4px)) scale(0.985);
	filter: brightness(0.94);
}

.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-pressed:not(.is-transparent-hitbox):active {
	transform: translateY(calc(var(--vlx-slots-btn-depth, 0.5) * 10px));
	box-shadow:
		inset 0 3px 0 rgba(255, 255, 255, 0.3),
		0 calc(var(--vlx-slots-btn-depth, 0.5) * 2px) 0 color-mix(in srgb, var(--vlx-slots-btn-color, #f5c542) 42%, #000),
		0 calc(var(--vlx-slots-btn-depth, 0.5) * 4px) calc(var(--vlx-slots-btn-depth, 0.5) * 8px) rgba(0, 0, 0, 0.45) !important;
}

.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-neon:not(.is-transparent-hitbox):active {
	transform: scale(0.97);
	filter: brightness(1.5);
}

@media (prefers-reduced-motion: reduce) {
	.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button)[class*='is-style-']::after,
	.vlx-slots-widget :is(.vlx-slots-button, .vlx-slots-win-button).is-style-neon:not(.is-transparent-hitbox) {
		animation: none;
	}
}

/*
 * Transparent hit zones: the button art is baked into the client's background
 * image, so the element only supplies the touch target. It stays fully
 * invisible on the frontend and shows as a red block in the editor so the
 * zone can be lined up with the artwork.
 */
.vlx-slots-widget .vlx-slots-button.is-transparent-hitbox {
	padding: 0;
	min-width: 0;
	min-height: 0;
	background: transparent !important;
	background-image: none !important;
	color: transparent !important;
	border-color: transparent !important;
	box-shadow: none !important;
	outline: none !important;
}

.vlx-slots-widget .vlx-slots-button.is-transparent-hitbox > * {
	opacity: 0 !important;
}

.vlx-slots-editor-mode .vlx-slots-button.is-transparent-hitbox {
	background: rgba(255, 0, 0, 0.28) !important;
	outline: 2px solid rgba(255, 0, 0, 0.72) !important;
	outline-offset: -2px;
}

/* --------------------------------- HUD --------------------------------- */

.vlx-slots-widget .vlx-slots-hud {
	position: absolute;
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	padding: 14px 24px;
	color: #fff;
	font-size: 42px;
	font-weight: 700;
	z-index: 8;
}

/* ---------------------------- layers/popups ---------------------------- */

.vlx-slots-start-layer,
.vlx-slots-win-layer,
.vlx-slots-payout-layer {
	position: absolute;
	inset: 0;
	z-index: 30;
	display: flex;
	align-items: center;
	justify-content: center;
}

.vlx-slots-start-layer {
	background-size: cover;
	background-position: center;
	z-index: 40;
}

.vlx-slots-popup-overlay {
	position: absolute;
	inset: 0;
	background-color: #000;
	opacity: 0.72;
}

.vlx-slots-win-popup,
.vlx-slots-payout-popup {
	position: relative;
	width: 860px;
	max-width: 92%;
	background: #171b30;
	border-radius: 32px;
	box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55);
	z-index: 2;
	overflow: hidden;
}

.vlx-slots-popup-content {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 22px;
	padding: 64px 56px;
	max-height: 100%;
	overflow-y: auto;
	text-align: center;
}

/*
 * The cross is drawn, not typed. As a "×" glyph its ink sits 4.14px below the
 * em-box centre in the stack's default font, and flexbox centres the line box
 * rather than the ink — so it painted visibly low, and any typography change
 * would have shifted it again. Two rotated bars are centred on the button by
 * construction, whatever the font.
 */
.vlx-slots-widget .vlx-slots-popup-close {
	position: absolute;
	top: 22px;
	right: 30px;
	width: 56px;
	height: 56px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.12);
	color: #fff;
	cursor: pointer;
	/* Above the animated border ring (z-index 1). The ring is masked to the
	   popup's outside so it cannot paint inward, but the close control is the
	   one thing that must never be obscured, so the order is stated outright
	   rather than left to document order. */
	z-index: 5;
}

.vlx-slots-widget .vlx-slots-popup-close::before,
.vlx-slots-widget .vlx-slots-popup-close::after {
	content: '';
	position: absolute;
	left: 50%;
	top: 50%;
	width: var(--vlx-slots-close-length, 40%);
	height: var(--vlx-slots-close-weight, 3px);
	margin: 0;
	background: currentColor;
	border-radius: 999px;
}

.vlx-slots-widget .vlx-slots-popup-close::before {
	transform: translate(-50%, -50%) rotate(45deg);
}

.vlx-slots-widget .vlx-slots-popup-close::after {
	transform: translate(-50%, -50%) rotate(-45deg);
}

.vlx-slots-win-layer.is-closing {
	opacity: 0;
	transition: opacity 0.25s ease;
}

/*
 * Size comes through a variable so it can be px OR a percentage. Only `width`
 * is set — a percentage `height` would resolve against the wrapper's HEIGHT
 * and stop the icon being square, so the aspect ratio derives it instead.
 */
.vlx-slots-win-icon {
	width: var(--vlx-slots-prize-size, 220px);
	height: auto;
	aspect-ratio: 1 / 1;
	object-fit: contain;
	position: relative;
	z-index: 2;
}

/* --------------------------- prize glow -------------------------------- */

/*
 * A soft disc behind the prize, independent of the rays so it can be used on
 * its own. Width is a PERCENTAGE, which resolves against the icon wrapper —
 * and that wrapper shrink-wraps the icon — so the size tracks the prize
 * automatically when the icon size changes. `aspect-ratio` keeps it circular.
 *
 * Sits at z-index 1: above the rays, below the icon, so it reads as the glow
 * closest to the prize whether or not the rays are on.
 */
.vlx-slots-win-glow {
	position: absolute;
	left: 50%;
	top: 50%;
	/* A multiple of the prize, not of the wrapper — so it tracks the icon
	   whichever unit the prize size is given in. */
	width: calc(var(--vlx-slots-prize-size, 220px) * var(--vlx-slots-glow-scale, 1.6));
	aspect-ratio: 1 / 1;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	pointer-events: none;
	z-index: 1;
}

/* ------------------------- prize rays / halo --------------------------- */

/*
 * The rays are deliberately larger than the popup and are allowed to spill
 * past its edges, so the prize reads as the source of the light rather than
 * something sitting on a card.
 */
/*
 * Layering inside the win popup, bottom to top:
 *   popup background -> animated border (1) -> prize group (2) -> text (3)
 *   -> close button (5)
 *
 * The z-index here also makes this a stacking context, so the rays, halo,
 * glow and icon keep their own internal order while riding above the border
 * as one unit. Without it they compete with the ring individually and the
 * ring paints straight through the middle of them.
 */
.vlx-slots-win-icon-wrap {
	position: relative;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	/*
	 * Full width on purpose. A percentage prize size has to resolve against
	 * something meaningful, and a shrink-wrapped wrapper would size itself to
	 * the icon that is trying to size itself to the wrapper. At 100% the
	 * percentage reads against the popup's content width, and the icon stays
	 * centred by justify-content — so the rays and glow, which centre on this
	 * box, still land on the icon.
	 */
	width: 100%;
}

/*
 * Text and the action button have to be positioned to be ordered at all: a
 * non-positioned block paints beneath every positioned sibling, which put the
 * copy under both the ring and the rays.
 */
.vlx-slots-widget .vlx-slots-win-header,
.vlx-slots-widget .vlx-slots-win-subheader,
.vlx-slots-widget .vlx-slots-win-button {
	position: relative;
	z-index: 3;
}

.vlx-slots-win-popup.has-rays,
.vlx-slots-win-popup.has-rays .vlx-slots-popup-content {
	overflow: visible;
}

.vlx-slots-win-rays,
.vlx-slots-win-halo {
	position: absolute;
	left: 50%;
	top: 50%;
	width: var(--vlx-slots-rays-size, 880px);
	height: var(--vlx-slots-rays-size, 880px);
	pointer-events: none;
	z-index: 0;
	will-change: transform;
}

.vlx-slots-win-rays {
	/* One wedge per ray: the step is a full turn divided by the ray count, and
	   the wedge fills the configured share of that step. */
	--vlx-slots-ray-step: calc(360deg / var(--vlx-slots-rays-count, 24));
	--vlx-slots-ray-wedge: calc(var(--vlx-slots-ray-step) * var(--vlx-slots-rays-thickness, 0.32));
	background: repeating-conic-gradient(
		from 0deg,
		var(--vlx-slots-rays-color, rgba(255, 214, 110, 0.7)) 0deg var(--vlx-slots-ray-wedge),
		transparent var(--vlx-slots-ray-wedge) var(--vlx-slots-ray-step)
	);
	opacity: var(--vlx-slots-rays-opacity, 0.75);
	/* Concentrated around the prize and faded before the text; the reach
	   controls how far out the rays survive. */
	-webkit-mask-image: radial-gradient(
		circle,
		#000 calc(var(--vlx-slots-rays-reach, 46%) * 0.09),
		rgba(0, 0, 0, 0.7) calc(var(--vlx-slots-rays-reach, 46%) * 0.3),
		rgba(0, 0, 0, 0.22) calc(var(--vlx-slots-rays-reach, 46%) * 0.6),
		transparent var(--vlx-slots-rays-reach, 46%)
	);
	mask-image: radial-gradient(
		circle,
		#000 calc(var(--vlx-slots-rays-reach, 46%) * 0.09),
		rgba(0, 0, 0, 0.7) calc(var(--vlx-slots-rays-reach, 46%) * 0.3),
		rgba(0, 0, 0, 0.22) calc(var(--vlx-slots-rays-reach, 46%) * 0.6),
		transparent var(--vlx-slots-rays-reach, 46%)
	);
	animation: vlx-slots-rays-spin var(--vlx-slots-rays-speed, 26s) linear infinite;
}

.vlx-slots-win-halo {
	background: conic-gradient(
		from 0deg,
		var(--vlx-slots-halo-color-a, rgba(255, 176, 60, 0.85)),
		var(--vlx-slots-halo-color-b, rgba(255, 246, 190, 0.9)),
		var(--vlx-slots-halo-color-a, rgba(255, 176, 60, 0.85)),
		var(--vlx-slots-halo-color-b, rgba(255, 246, 190, 0.9)),
		var(--vlx-slots-halo-color-a, rgba(255, 176, 60, 0.85))
	);
	-webkit-mask-image: radial-gradient(circle, transparent 5%, #000 16%, rgba(0, 0, 0, 0.35) 28%, transparent 44%);
	mask-image: radial-gradient(circle, transparent 5%, #000 16%, rgba(0, 0, 0, 0.35) 28%, transparent 44%);
	opacity: var(--vlx-slots-halo-opacity, 0.55);
	animation: vlx-slots-rays-spin-reverse calc(var(--vlx-slots-rays-speed, 26s) * 1.7) linear infinite;
}

@keyframes vlx-slots-rays-spin {
	from { transform: translate(-50%, -50%) rotate(0deg); }
	to { transform: translate(-50%, -50%) rotate(360deg); }
}

@keyframes vlx-slots-rays-spin-reverse {
	from { transform: translate(-50%, -50%) rotate(360deg); }
	to { transform: translate(-50%, -50%) rotate(0deg); }
}

/* --------------------- animated popup border --------------------------- */

@property --vlx-slots-border-angle {
	syntax: '<angle>';
	inherits: false;
	initial-value: 0deg;
}

.vlx-slots-popup-border {
	position: absolute;
	inset: calc(-1 * var(--vlx-slots-border-thickness, 4px));
	/*
	 * NOT `inherit`. This box sits one thickness OUTSIDE the popup on every
	 * side, and two concentric rounded rectangles only stay parallel when the
	 * outer radius is the inner radius plus the gap between them. Inheriting
	 * the popup's radius leaves the outer corner too tight, which shows up as
	 * a crescent of daylight between the ring and the popup at each corner.
	 */
	border-radius:
		calc(var(--vlx-slots-popup-radius-tl, 32px) + var(--vlx-slots-border-thickness, 4px))
		calc(var(--vlx-slots-popup-radius-tr, 32px) + var(--vlx-slots-border-thickness, 4px))
		calc(var(--vlx-slots-popup-radius-br, 32px) + var(--vlx-slots-border-thickness, 4px))
		calc(var(--vlx-slots-popup-radius-bl, 32px) + var(--vlx-slots-border-thickness, 4px));
	padding: var(--vlx-slots-border-thickness, 4px);
	pointer-events: none;
	z-index: 1;
	opacity: var(--vlx-slots-border-opacity, 1);
	background: conic-gradient(
		from var(--vlx-slots-border-angle),
		var(--vlx-slots-border-color-a, #ffd66e),
		var(--vlx-slots-border-color-b, #ff9d3c),
		var(--vlx-slots-border-color-c, #fff6be),
		var(--vlx-slots-border-color-b, #ff9d3c),
		var(--vlx-slots-border-color-a, #ffd66e)
	);
	/* Punch out the middle so only the ring remains. */
	-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	mask-composite: exclude;
	animation: vlx-slots-border-rotate var(--vlx-slots-border-speed, 6s) linear infinite;
}

@keyframes vlx-slots-border-rotate {
	to { --vlx-slots-border-angle: 360deg; }
}

@media (prefers-reduced-motion: reduce) {
	.vlx-slots-win-rays,
	.vlx-slots-win-halo,
	.vlx-slots-popup-border {
		animation: none;
	}
}

.vlx-slots-widget .vlx-slots-win-header {
	margin: 0;
	color: #fff;
	font-size: 56px;
	font-weight: 800;
}

.vlx-slots-widget .vlx-slots-win-subheader {
	color: rgba(255, 255, 255, 0.82);
	font-size: 34px;
	white-space: pre-line;
}

.vlx-slots-widget .vlx-slots-win-button {
	border: 0;
	border-radius: 999px;
	padding: 24px 64px;
	background: #f5c542;
	color: #111;
	font-size: 38px;
	font-weight: 800;
	cursor: pointer;
	transition: transform 0.12s ease;
}

.vlx-slots-widget .vlx-slots-win-button:active {
	transform: scale(0.96);
}

/* ------------------------------- payouts ------------------------------- */

.vlx-slots-widget .vlx-slots-payout-title {
	margin: 0;
	color: #fff;
	font-size: 52px;
	font-weight: 800;
}

.vlx-slots-widget .vlx-slots-payout-rows,
.vlx-slots-payout-prizes {
	width: 100%;
	display: flex;
	flex-direction: column;
}

/* Right-hand side of a "prizes per combination" row: name then icon, pushed
   to the trailing edge so every prize lines up down the right. */
.vlx-slots-widget .vlx-slots-payout-prize {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 16px;
	text-align: right;
	min-width: 0;
	flex: 1 1 auto;
}

.vlx-slots-widget .vlx-slots-payout-prize-name {
	min-width: 0;
}

/*
 * Matched to the combination symbols opposite, and `flex: none` so the icon
 * never grows into the name's space — left to size itself it swallowed the row
 * and squeezed the name down to one letter per line.
 */
.vlx-slots-widget .vlx-slots-payout-prize img {
	flex: none;
	width: 72px;
	height: 72px;
	object-fit: contain;
}

.vlx-slots-payout-prizes-title {
	margin-top: 18px;
	padding-bottom: 10px;
	color: rgba(255, 255, 255, 0.6);
	font-size: 26px;
	text-transform: uppercase;
	letter-spacing: 0.1em;
}

.vlx-slots-widget .vlx-slots-payout-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
	padding: 16px 4px;
	border-bottom: 1px solid rgba(255, 255, 255, 0.14);
	font-size: 32px;
}

.vlx-slots-widget .vlx-slots-payout-row:last-child {
	border-bottom: 0;
}

.vlx-slots-payout-combo {
	display: flex;
	align-items: center;
	gap: 10px;
}

.vlx-slots-payout-combo img {
	width: 72px;
	height: 72px;
	object-fit: contain;
}

.vlx-slots-payout-plus {
	font-size: 40px;
	font-weight: 800;
	opacity: 0.7;
}

.vlx-slots-payout-score {
	font-weight: 800;
	white-space: nowrap;
}

/* ---------------------------- lever readout ---------------------------- */

/*
 * Setup aid, only rendered when the lever's own debug switch is on. Sized in
 * px against the fixed screen, so it stays legible on a 1080x1920 board.
 */
.vlx-slots-lever-debug {
	position: absolute;
	top: 24px;
	left: 24px;
	z-index: 50;
	min-width: 420px;
	padding: 16px 20px;
	border-radius: 12px;
	background: rgba(6, 10, 15, 0.82);
	border: 1px solid rgba(255, 255, 255, 0.16);
	color: #dbe3ec;
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 20px;
	line-height: 1.5;
	pointer-events: none;
}

.vlx-slots-lever-debug-row {
	display: flex;
	gap: 12px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.vlx-slots-lever-debug-row b {
	color: #ff5c33;
}

.vlx-slots-lever-debug-bar {
	position: relative;
	height: 14px;
	margin: 10px 0;
	border-radius: 7px;
	background: rgba(255, 255, 255, 0.12);
	overflow: hidden;
}

.vlx-slots-lever-debug-bar span {
	display: block;
	height: 100%;
	background: #4c9aff;
}

.vlx-slots-lever-debug-bar.is-over span {
	background: #35d07f;
}

/* Trigger point, so a pull can be read against the threshold at a glance. */
.vlx-slots-lever-debug-bar i {
	position: absolute;
	top: 0;
	bottom: 0;
	width: 2px;
	background: #ffd66e;
}
