/* ===========================================================================
   ONE to Z — motion.css, ported whole.
   ---------------------------------------------------------------------------
   The theme's movement layer: reveal-on-scroll, the magnetic buttons, the
   label swap on press, the brand wheel that spins while a brand page loads,
   the page-background video pools. Carried across in full for the same reason
   style.css was — the previous port took the rules it recognised and left the
   ones it did not, which is how the swap ended up rendering "ADD TO CARTADD TO
   CART" and the wheel never appeared at all.

   Its reduced-motion block is intact and is load-bearing: someone who has
   asked their operating system for less movement gets a site that works and
   simply does not move. Do not "tidy" that block away.
   =========================================================================== */

/**
 * One to Z — motion layer.
 *
 * Loaded on the front page, the Landing template and brand archives. The
 * custom cursor lives in cursor.css because it loads site-wide. Everything in
 * here is progressive: with JS off, or on a touch device, or when the visitor
 * has asked for reduced motion, the page still renders and reads correctly.
 */

/* ==========================================================================
   1. Page loader
   ========================================================================== */
.otz-loader {
	position: fixed;
	inset: 0;
	z-index: 9999;
	display: flex;
	align-items: flex-end;
	justify-content: flex-end;
	padding: 0 6vw 6vh;
	background: var(--otz-black);
	transition: opacity .6s ease, visibility .6s ease;
}

.otz-loader::before {
	content: "";
	position: absolute;
	inset: 0;
	background: radial-gradient(60vw 50vh at 30% 40%, rgb(var(--otz-brand-deep-rgb) / .18), transparent 65%);
}

.otz-loader__count {
	position: relative;
	font-family: var(--otz-font-display);
	font-size: clamp(4rem, 16vw, 13rem);
	line-height: .85;
	color: #fff;
	letter-spacing: -.02em;
}

.otz-loader__count sup {
	font-size: .28em;
	vertical-align: super;
	color: var(--otz-orange);
}

.otz-loader__bar {
	position: absolute;
	left: 0;
	bottom: 0;
	height: 3px;
	width: 0;
	background: linear-gradient(90deg, var(--otz-orange), var(--otz-gold));
	transition: width .25s ease-out;
}

/*
 * The status line. Bottom left, opposite the number, so the two do not fight
 * for the same corner. Its own transition on opacity would stutter every time
 * the text swaps, so the change is instant and the eye follows the bar instead.
 */
.otz-loader__say {
	position: absolute;
	left: 6vw;
	bottom: calc(6vh + .4rem);
	max-width: min(60vw, 32ch);
	margin: 0;
	color: rgb(255 255 255 / .62);
	font-size: clamp(.82rem, 2.6vw, 1rem);
	font-weight: 600;
	letter-spacing: .04em;
}

.otz-loader__say::after {
	content: "";
	display: inline-block;
	width: 1.6em;
	text-align: left;
	animation: otz-loader-dots 1.4s steps(4, end) infinite;
}

@keyframes otz-loader-dots {
	0%   { content: ""; }
	25%  { content: "."; }
	50%  { content: ".."; }
	75%  { content: "..."; }
	100% { content: ""; }
}

@media (max-width: 600px) {
	.otz-loader__say { left: 20px; bottom: calc(6vh + .3rem); max-width: 74vw; }
}

/*
 * The floor: the curtain lifts even if no script lifts it.
 *
 * This overlay is created by JavaScript and, until now, removed only by
 * JavaScript. Anything that stopped that script part-way — an exception, a
 * bundle truncated by an optimiser plugin, a minifier that mangled it — left
 * a paying visitor looking at a black rectangle with a stalled number on it,
 * with no way out but to leave. There was no lower bound on that.
 *
 * A delayed animation costs nothing, runs in the compositor with no script
 * involved at all, and puts a hard limit on how long the shop can be hidden.
 * It sits deliberately later than every JavaScript timeout, so in normal
 * operation it never fires. It is not a timing mechanism. It is a floor.
 */
.otz-loader {
	animation: otz-loader-failsafe 1ms linear 9s forwards;
}

@keyframes otz-loader-failsafe {
	to {
		opacity: 0;
		visibility: hidden;
		pointer-events: none;
	}
}

.otz-loader.is-done {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

html.otz-loading,
html.otz-loading body {
	overflow: hidden;
}

/* ==========================================================================
   2. Smooth scroll
   ========================================================================== */
/*
 * The body MUST keep scrolling — a spacer element gives the document its real
 * height while the content sits in a fixed, transformed wrapper. Setting
 * overflow:hidden here would kill the scrollbar and freeze window.scrollY,
 * which is exactly how this broke the first time.
 */
html.otz-smooth {
	scroll-behavior: auto;
}

html.otz-smooth body {
	overflow-x: hidden;
}

.otz-smooth-wrap {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	will-change: transform;
}

/* topbar + header move into one fixed bar, outside the transformed wrapper */
.otz-fixed-top {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 300;
}

html.otz-smooth .otz-fixed-top .otz-header {
	position: static;
}

/* ==========================================================================
   3. Video hero
   ========================================================================== */
.otz-hero--video {
	position: relative;
	display: flex;
	align-items: center;
	min-height: 92vh;
	min-height: 92dvh;
	padding: 0;
	overflow: hidden;
	border-bottom: 1px solid var(--otz-border);
}

.otz-hero__media {
	position: absolute;
	inset: -8% 0 -8% 0;
	z-index: 0;
	will-change: transform;
}

.otz-hero__media video,
.otz-hero__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.otz-hero__scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	background:
		linear-gradient(90deg, rgb(37 31 46 / .92) 0%, rgb(37 31 46 / .55) 45%, rgb(37 31 46 / .25) 100%),
		linear-gradient(0deg, rgb(37 31 46 / .85) 0%, transparent 45%);
}

.otz-hero--video .otz-hero__inner {
	position: relative;
	z-index: 2;
	padding: 8vh 0;
}

.otz-hero--video::after {
	display: none;
}

.otz-hero__scroll {
	position: absolute;
	left: 50%;
	bottom: 26px;
	z-index: 2;
	transform: translateX(-50%);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	color: var(--otz-muted);
	font-size: .7rem;
	font-weight: 700;
	letter-spacing: .18em;
	text-transform: uppercase;
}

.otz-hero__scroll span {
	display: block;
	width: 1px;
	height: 42px;
	background: linear-gradient(180deg, var(--otz-orange), transparent);
	animation: otz-scroll-hint 2.4s ease-in-out infinite;
}

@keyframes otz-scroll-hint {
	0%, 100% { transform: scaleY(.35); transform-origin: top; opacity: .4; }
	50%      { transform: scaleY(1);   transform-origin: top; opacity: 1; }
}

.otz-video-toggle {
	position: absolute;
	right: 24px;
	bottom: 24px;
	z-index: 3;
	width: 44px;
	height: 44px;
	padding: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: rgb(37 31 46 / .55);
	border: 1px solid var(--otz-border);
	border-radius: 50%;
	color: var(--otz-text);
}

.otz-video-toggle:hover {
	background: var(--otz-orange);
	color: #2a1c0a;
	transform: none;
	box-shadow: none;
}

.otz-video-toggle svg { width: 15px; height: 15px; }
.otz-video-toggle .otz-icon-play { display: none; }
.otz-video-toggle.is-paused .otz-icon-play { display: block; }
.otz-video-toggle.is-paused .otz-icon-pause { display: none; }

/* ==========================================================================
   4b. Mid-page featured band
   ========================================================================== */
.otz-band {
	position: relative;
	display: flex;
	align-items: center;
	min-height: 62vh;
	min-height: 62dvh;
	padding: clamp(56px, 8vw, 110px) 0;
	overflow: hidden;
	border-block: 1px solid var(--otz-border);
}

.otz-band__media {
	position: absolute;
	inset: -10% 0;
	z-index: 0;
	will-change: transform;
}

.otz-band__media video {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.otz-band__scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	background:
		linear-gradient(270deg, rgb(37 31 46 / .9) 0%, rgb(37 31 46 / .45) 52%, rgb(37 31 46 / .3) 100%),
		linear-gradient(0deg, rgb(37 31 46 / .8), transparent 55%);
}

.otz-band__inner {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	text-align: right;
}

.otz-band__inner h2 {
	max-width: 12ch;
	font-size: clamp(2rem, 4.6vw, 3.4rem);
}

.otz-band__inner p {
	max-width: 46ch;
	color: var(--otz-muted);
	font-size: 1.05rem;
	margin-bottom: 1.6rem;
}

@media (max-width: 700px) {
	.otz-band__inner {
		align-items: flex-start;
		text-align: left;
	}
	.otz-band__scrim {
		background: linear-gradient(0deg, rgb(37 31 46 / .92), rgb(37 31 46 / .55));
	}
}

/* ==========================================================================
   4b2. Brand archive media
   ========================================================================== */
/*
 * position: fixed, not absolute — and this is the whole bug, so it is worth
 * spelling out.
 *
 * As absolute with inset: 0, the containing block was #page, so this box grew
 * to the FULL HEIGHT OF THE PAGE. The video inside uses object-fit: cover,
 * which scales the source until it covers the box. On a 3000px-tall brand
 * archive that is a 3.1x zoom showing only the middle 24% of the frame — a
 * flat, dark field that reads as "the video stopped playing". It hadn't; you
 * were looking at a few hundred pixels of it, magnified.
 *
 * That also explains why it looked right for a moment on load: before the
 * products rendered the page was roughly one viewport tall, so the box was
 * viewport-shaped and the video fitted properly. The products arriving made
 * the page tall, and the zoom went with it.
 *
 * Fixed keeps the box exactly one viewport regardless of page length, so the
 * framing is correct at any content height, and the video sits still while the
 * products scroll over it.
 */
.otz-brand-media {
	position: fixed;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	pointer-events: none;
}

.otz-brand-media .otz-hero__media { inset: -6% 0; }

/*
 * The poster-to-video cross-fade.
 *
 * Only active once JavaScript has put .otz-vfade on <html>, so a visit where
 * this stylesheet loads and the script does not still shows the video rather
 * than a box that stays empty for ever.
 */
.otz-vfade .otz-brand-media video,
.otz-vfade .otz-page-bg--video video,
.otz-vfade .otz-hero__media video {
	opacity: 0;
	transition: opacity .55s ease;
}

.otz-vfade .otz-brand-media video.is-ready,
.otz-vfade .otz-page-bg--video video.is-ready,
.otz-vfade .otz-hero__media video.is-ready { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
	.otz-vfade .otz-brand-media video,
	.otz-vfade .otz-page-bg--video video,
	.otz-vfade .otz-hero__media video { transition: none; }
}

/*
 * The backdrop is printed at body level from wp_body_open, so it sits outside
 * #page entirely. #page already carries z-index: 1, which puts every piece of
 * page content above this z-index: 0 layer with no further rules needed.
 *
 * Belt and braces for anything that renders outside #page.
 */
.otz-brand-media ~ #page,
.otz-brand-media ~ .otz-container,
.otz-brand-media ~ .woocommerce-notices-wrapper {
	position: relative;
	z-index: 1;
}

.otz-brand-media .otz-hero__scrim {
	background:
		linear-gradient(0deg, var(--otz-black) 0%, rgb(37 31 46 / .72) 42%, rgb(37 31 46 / .55) 100%);
}

.otz-page-header {
	position: relative;
	isolation: isolate;
}

.otz-page-header > .otz-container { position: relative; z-index: 2; }

/* ==========================================================================
   4c. Brand wheel transition
   ==========================================================================
   Clicking a brand opens a full-screen overlay: the seal sits at the hub of a
   wheel with one slot per brand, spins fast, then decelerates so the chosen
   slot lands under the pointer at the top. Meanwhile the page hue cross-fades
   underneath, so when the overlay lifts the site is already in brand colours.
   ========================================================================== */
.otz-wheel {
	position: fixed;
	inset: 0;
	z-index: 9990;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgb(37 31 46 / .96);
	opacity: 0;
	visibility: hidden;
	transition: opacity .5s ease, visibility .5s ease;
}

.otz-wheel::before {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(70vw 70vh at 50% 50%, rgb(var(--otz-wheel-rgb, var(--otz-brand-rgb)) / .26), transparent 66%);
	transition: background .5s ease;
}

.otz-wheel.is-open {
	opacity: 1;
	visibility: visible;
}

.otz-wheel__stage {
	position: relative;
	width: min(74vmin, 520px);
	aspect-ratio: 1;
	transform: scale(.86);
	opacity: 0;
	transition: transform .7s cubic-bezier(.16, .84, .28, 1), opacity .5s ease;
}

.otz-wheel.is-open .otz-wheel__stage {
	transform: scale(1);
	opacity: 1;
}

/* the pointer that marks the winning slot */
.otz-wheel__needle {
	position: absolute;
	top: -2px;
	left: 50%;
	z-index: 4;
	width: 0;
	height: 0;
	transform: translateX(-50%);
	border-left: 13px solid transparent;
	border-right: 13px solid transparent;
	border-top: 22px solid var(--otz-brand-light);
	filter: drop-shadow(0 2px 6px rgb(0 0 0 / .5));
}

.otz-wheel__disc {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	border: 3px solid rgb(var(--otz-brand-rgb) / .5);
	overflow: hidden;
	will-change: transform;
	box-shadow: 0 0 0 10px rgb(37 31 46 / .6), 0 24px 70px rgb(0 0 0 / .55);

	/*
	 * The wedges are a conic gradient built by JS, starting half a slice before
	 * 0deg so the first wedge is centred on straight up. Exact by construction —
	 * no clip-path arithmetic to get wrong, which is what broke this twice.
	 */
	background: var(--otz-wheel-conic, #221d29);
}

/* spokes on the wedge boundaries, also from a conic gradient */
.otz-wheel__spokes {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	background: var(--otz-wheel-spokes, none);
	pointer-events: none;
}

/*
 * One item per slot. The outer element fills the disc and is rotated to the
 * slot's bisector; its content is counter-rotated by the same amount, so the
 * emblem and name sit exactly on the bisector and stay upright.
 */
.otz-wheel__item {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: flex-start;
	justify-content: center;
	padding-top: 5.5%;
	transform: rotate(var(--otz-item-angle));
	pointer-events: none;
}

.otz-wheel__itemin {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	width: 30%;
	transform: rotate(calc(var(--otz-item-angle) * -1));
}

.otz-wheel__itemin img {
	width: clamp(30px, 7.4vmin, 54px);
	height: clamp(30px, 7.4vmin, 54px);
	border-radius: 22%;
	box-shadow: 0 3px 10px rgb(0 0 0 / .45);
}

.otz-wheel__itemin span {
	font-family: var(--otz-font-body);
	font-size: clamp(.54rem, 1.55vmin, .78rem);
	font-weight: 800;
	letter-spacing: .04em;
	line-height: 1.12;
	text-align: center;
	text-transform: uppercase;
	color: #2b2136;
	text-shadow: 0 1px 0 rgb(255 255 255 / .35);
}

/* the winning slot brightens as it comes to rest */
.otz-wheel__glow {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	opacity: 0;
	pointer-events: none;
	background: conic-gradient(from calc(-1 * var(--otz-slice) / 2),
		rgb(255 255 255 / .3) 0deg, rgb(255 255 255 / .3) var(--otz-slice),
		transparent var(--otz-slice));
	transition: opacity .3s ease;
}

.otz-wheel.is-landed .otz-wheel__glow { opacity: 1; }

.otz-wheel__hub {
	position: absolute;
	top: 50%;
	left: 50%;
	z-index: 3;
	width: 34%;
	aspect-ratio: 1;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background: #fdfbf6;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 0 0 5px rgb(37 31 46 / .85), 0 10px 30px rgb(0 0 0 / .5);
	overflow: hidden;
}

.otz-wheel__hub img {
	width: 92%;
	height: 92%;
	object-fit: contain;
}

.otz-wheel__label {
	position: absolute;
	left: 50%;
	bottom: -14%;
	transform: translateX(-50%);
	white-space: nowrap;
	font-family: var(--otz-font-display);
	font-size: clamp(1.2rem, 4vmin, 2.2rem);
	letter-spacing: .04em;
	text-transform: uppercase;
	color: #fff;
	opacity: 0;
	transition: opacity .3s ease .1s;
}

.otz-wheel.is-landed .otz-wheel__label { opacity: 1; }

.otz-wheel.is-landed .otz-wheel__needle {
	animation: otz-needle-kick .4s cubic-bezier(.22, 1, .36, 1);
}

@keyframes otz-needle-kick {
	0%   { transform: translateX(-50%) translateY(0) scale(1); }
	35%  { transform: translateX(-50%) translateY(-7px) scale(1.22); }
	100% { transform: translateX(-50%) translateY(0) scale(1); }
}

/* --------------------------------------------------------------------------
   Dive through the winning slot.
   The winner always finishes at the top of the disc, so the zoom origin is a
   fixed point — 50% across, a quarter down — and never has to be calculated.
   easeInQuart accelerates, which reads as falling into the wedge.
   -------------------------------------------------------------------------- */
.otz-wheel__stage {
	transform-origin: 50% 25%;
}

.otz-wheel.is-diving .otz-wheel__stage {
	/* a touch of rotation while falling in makes it feel like passing through */
	transform: scale(16) rotate(6deg);
	opacity: 0;
	transition: transform 1.36s cubic-bezier(.5, 0, .78, .12),
	            opacity .8s ease .85s;
}

.otz-wheel.is-diving .otz-wheel__label { opacity: 0; transition: opacity .2s ease; }
.otz-wheel.is-diving .otz-wheel__needle { opacity: 0; transition: opacity .2s ease; }

/* the brand's own world, revealed behind the wedge as it swallows the screen */
.otz-wheel__zoom {
	position: absolute;
	inset: 0;
	z-index: 5;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	opacity: 0;
	visibility: hidden;
	transform: scale(1.45);
	transition: opacity 1.1s ease, transform 2.1s cubic-bezier(.16, .84, .28, 1), visibility 1.1s;
}

.otz-wheel.is-diving .otz-wheel__zoom {
	opacity: 1;
	visibility: visible;
	transform: scale(1);
}

.otz-wheel__zoom video {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.otz-wheel__zoom::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(70vw 70vh at 50% 50%, rgb(var(--otz-wheel-rgb, var(--otz-brand-rgb)) / .34), transparent 68%),
		linear-gradient(0deg, rgb(37 31 46 / .82), rgb(37 31 46 / .38));
}

/* the name stays outside the scaling stage, so it never blurs */
.otz-wheel__title {
	position: relative;
	z-index: 2;
	font-family: var(--otz-font-display);
	font-size: clamp(2.2rem, 9vmin, 6rem);
	letter-spacing: .02em;
	line-height: 1;
	text-align: center;
	text-transform: uppercase;
	color: #fff;
	opacity: 0;
	transform: scale(.94);
	transition: opacity .9s ease .45s, transform 1.8s cubic-bezier(.16, .84, .28, 1) .45s;
}

.otz-wheel.is-diving .otz-wheel__title {
	opacity: 1;
	transform: scale(1);
}

/* the page itself settles out of the zoom as it arrives */
@keyframes otz-arrive {
	from { transform: scale(1.09); opacity: 0; filter: saturate(1.35) blur(6px); }
	40%  { opacity: 1; }
	to   { transform: none; opacity: 1; filter: none; }
}

.otz-arriving {
	animation: otz-arrive .92s cubic-bezier(.16, .84, .28, 1) both;
}

/*
 * An explicit data-saver request outranks the theme setting — the visitor is
 * telling us they are paying for these bytes.
 */
@media (prefers-reduced-data: reduce) {
	.otz-hero__media video,
	.otz-band__media video { display: none; }
	.otz-video-toggle { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	.otz-wheel { display: none !important; }
	.otz-arriving { animation: none; }
}

/* ==========================================================================
   4. Scroll reveals
   ========================================================================== */
.otz-reveal {
	opacity: 0;
	transform: translateY(34px);
	transition: opacity .9s cubic-bezier(.22, 1, .36, 1),
	            transform .9s cubic-bezier(.22, 1, .36, 1);
}

.otz-reveal.is-in {
	opacity: 1;
	transform: none;
}

.otz-reveal-group > * {
	opacity: 0;
	transform: translateY(28px);
	transition: opacity .8s cubic-bezier(.22, 1, .36, 1),
	            transform .8s cubic-bezier(.22, 1, .36, 1);
}

.otz-reveal-group.is-in > * {
	opacity: 1;
	transform: none;
}

.otz-reveal-group.is-in > *:nth-child(1) { transition-delay: .00s; }
.otz-reveal-group.is-in > *:nth-child(2) { transition-delay: .06s; }
.otz-reveal-group.is-in > *:nth-child(3) { transition-delay: .12s; }
.otz-reveal-group.is-in > *:nth-child(4) { transition-delay: .18s; }
.otz-reveal-group.is-in > *:nth-child(5) { transition-delay: .24s; }
.otz-reveal-group.is-in > *:nth-child(6) { transition-delay: .30s; }
.otz-reveal-group.is-in > *:nth-child(7) { transition-delay: .36s; }
.otz-reveal-group.is-in > *:nth-child(8) { transition-delay: .42s; }

/* headline lines rising out of a mask */
.otz-line-mask {
	display: block;
	overflow: hidden;
}

.otz-line-mask > span {
	display: block;
	transform: translateY(105%);
	transition: transform 1s cubic-bezier(.22, 1, .36, 1);
}

.is-in .otz-line-mask > span,
.otz-line-mask.is-in > span {
	transform: none;
}

.otz-line-mask:nth-child(2) > span { transition-delay: .08s; }
.otz-line-mask:nth-child(3) > span { transition-delay: .16s; }

/* ==========================================================================
   5. Hover text swap — the doubled-label effect
   ========================================================================== */
.otz-swap {
	position: relative;
	display: inline-block;
	overflow: hidden;
	vertical-align: bottom;
}

.otz-swap__in,
.otz-swap__out {
	display: block;
	transition: transform .42s cubic-bezier(.22, 1, .36, 1);
}

.otz-swap__out {
	position: absolute;
	inset: 0;
	transform: translateY(100%);
}

.otz-swap:hover .otz-swap__in,
a:hover .otz-swap .otz-swap__in,
button:hover .otz-swap .otz-swap__in {
	transform: translateY(-100%);
}

.otz-swap:hover .otz-swap__out,
a:hover .otz-swap .otz-swap__out,
button:hover .otz-swap .otz-swap__out {
	transform: none;
}

/* ==========================================================================
   6. Magnetic buttons
   ========================================================================== */
.otz-magnetic {
	will-change: transform;
	transition: transform .4s cubic-bezier(.22, 1, .36, 1);
}

.otz-magnetic.is-pulled {
	transition: transform .1s linear;
}

/* ==========================================================================
   7. Marquee
   ========================================================================== */
.otz-marquee {
	overflow: hidden;
	padding: 18px 0;
	border-block: 1px solid var(--otz-border);
	background: var(--otz-panel);
}

.otz-marquee__track {
	display: flex;
	width: max-content;
	gap: 48px;
	animation: otz-marquee 26s linear infinite;
}

.otz-marquee:hover .otz-marquee__track {
	animation-play-state: paused;
}

.otz-marquee__item {
	display: inline-flex;
	align-items: center;
	gap: 48px;
	font-family: var(--otz-font-display);
	font-size: 1.25rem;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--otz-muted);
	white-space: nowrap;
}

.otz-marquee__item i {
	display: inline-block;
	width: 7px;
	height: 7px;
	background: var(--otz-orange);
	border-radius: 50%;
}

@keyframes otz-marquee {
	from { transform: translateX(0); }
	to   { transform: translateX(-50%); }
}

/* ==========================================================================
   8. Opt-outs
   ========================================================================== */
@media (hover: none), (pointer: coarse) {
	/*
	 * Two mobile modes, chosen by "Play background video on phones" in the
	 * Customizer, which puts .otz-mvideo on the body.
	 *
	 * Off (body without .otz-mvideo): the poster becomes a plain background
	 * image and motion.js strips the <video> sources before the browser can
	 * fetch them, so not a byte of video is downloaded.
	 *
	 * On (body.otz-mvideo): the video plays, muted and inline. Parallax stays
	 * off either way — it is expensive on a phone and barely visible.
	 */
	.otz-hero__media,
	.otz-band__media {
		background-position: center center;
		background-size: cover;
		background-repeat: no-repeat;
		inset: 0;
		transform: none !important;
	}

	body:not(.otz-mvideo) .otz-hero__media video,
	body:not(.otz-mvideo) .otz-band__media video { display: none; }

	body:not(.otz-mvideo) .otz-video-toggle { display: none; }

	/* when video is on, the toggle matters more on mobile, not less */
	body.otz-mvideo .otz-video-toggle {
		width: 44px;
		height: 44px;
		right: 14px;
		bottom: 14px;
	}

	.otz-hero--video { min-height: 72vh; min-height: 72dvh; }
}

@media (prefers-reduced-motion: reduce) {
	.otz-reveal,
	.otz-reveal-group > * {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}

	.otz-line-mask > span { transform: none !important; }
	.otz-marquee__track { animation: none; }
	.otz-hero__scroll span { animation: none; }
	.otz-loader { display: none; }
}

/* Never let the motion layer hide content if the script fails to run. */
.no-js .otz-reveal,
.no-js .otz-reveal-group > * {
	opacity: 1;
	transform: none;
}

.no-js .otz-loader { display: none; }
