/**
 * 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; }
