/* ===========================================================================
 * Opportunità — Floating Scroll System
 * Implements the "Scroll System" handoff (IMPLEMENTATION.md v1.0) 1:1.
 *
 * Reveals itself after the first viewport, morphs on hover into a compact
 * drag-to-scroll rail, and parks itself into a reserved slot in the footer.
 *
 * THE THREE RENAMES THE PLATFORM FORCED
 * -------------------------------------
 * Every value below — pixel, duration, curve, delay, opacity, colour — is the
 * handoff's. Only three *names* had to change, and each for a concrete reason:
 *
 *   1. `.ops` (handoff page root)  ->  `.op-public-page`
 *      That wrapper already is this platform's page root and already wraps the
 *      footer, so it is the element that can carry `data-foot`.
 *
 *   2. `[data-theme="light|dim|dark"]`  ->  `html[data-op-theme="light|dim|
 *      dark-contrast"]`. The platform's theme attribute lives on <html> and is
 *      written before first paint by the early inline script in class-assets.php.
 *      "dark" in the handoff is this platform's "dark-contrast".
 *
 *   3. `--opx-* / --acc / --w1..5 / --sc-shadow`  ->  `--opss-*`
 *      opportunita-pricing.css already defines a full `--opx-*` palette ON
 *      `.op-pricing`, which *is* an `.op-public-page` — the widget would have
 *      inherited the pricing page's tokens and changed colour on that one route.
 *      `--acc` additionally had to move because `@property` registers globally
 *      with `inherits: true`: an unprefixed `--acc` would be handed to every
 *      element on the site.
 *
 * Everything else — including the RTL mirror, which the handoff does not cover
 * because its demo page is LTR-only — is marked with its own comment.
 *
 * @package Opportunita_Core
 * @since 1.1.42.0
 * =========================================================================== */

/* ---- 1. THEME TOKENS ----------------------------------------------------
   Three themes, switched by html[data-op-theme] on the document element.
   --opss-w1..--opss-w5 are the five rail-light hues; --opss-acc is the live
   animated accent. Scoped to .op-public-page so nothing leaks into the
   WordPress admin bar, the block theme, or the Workspace dashboard. */

.op-public-page {
	--opss-bg: #ffffff;
	--opss-surface: #ffffff;
	--opss-surface-2: #f8fafc;
	--opss-surface-3: #f1f5f9;
	--opss-text: #0f172a;
	--opss-text-muted: #475569;
	--opss-text-quiet: #7b8798;
	--opss-border: #e2e8f0;
	--opss-border-strong: #cbd5e1;
	--opss-accent: #0d9488;
	--opss-accent-2: #0f766e;
	--opss-accent-soft: rgba(13, 148, 136, 0.08);
	--opss-on-accent: #ffffff;
	--opss-ink: #0f172a;
	--opss-on-ink: #ffffff;
	--opss-shadow: rgba(15, 23, 42, 0.20);
	--opss-w1: #0d9488;
	--opss-w2: #6366f1;
	--opss-w3: #d97706;
	--opss-w4: #3b82f6;
	--opss-w5: #e11d48;
}

html[data-op-theme="dim"] .op-public-page {
	--opss-bg: #151a22;
	--opss-surface: #1a212b;
	--opss-surface-2: #1e2631;
	--opss-surface-3: #242e3b;
	--opss-text: #eef2f7;
	--opss-text-muted: #a9b6c7;
	--opss-text-quiet: #7d8b9e;
	--opss-border: #2c3745;
	--opss-border-strong: #3d4a5c;
	--opss-accent: #2dd4bf;
	--opss-accent-2: #5eead4;
	--opss-accent-soft: rgba(45, 212, 191, 0.12);
	--opss-on-accent: #06231f;
	--opss-ink: #2dd4bf;
	--opss-on-ink: #06231f;
	--opss-shadow: rgba(0, 0, 0, 0.45);
	--opss-w1: #2dd4bf;
	--opss-w2: #818cf8;
	--opss-w3: #fbbf24;
	--opss-w4: #38bdf8;
	--opss-w5: #fb7185;
}

/* The handoff calls this theme "dark"; on this platform it is "dark-contrast". */
html[data-op-theme="dark-contrast"] .op-public-page {
	--opss-bg: #08090c;
	--opss-surface: #0e1014;
	--opss-surface-2: #121419;
	--opss-surface-3: #181b21;
	--opss-text: #f9fafb;
	--opss-text-muted: #b6bdc8;
	--opss-text-quiet: #868d99;
	--opss-border: #20242b;
	--opss-border-strong: #333941;
	--opss-accent: #2dd4bf;
	--opss-accent-2: #5eead4;
	--opss-accent-soft: rgba(45, 212, 191, 0.13);
	--opss-on-accent: #06231f;
	--opss-ink: #2dd4bf;
	--opss-on-ink: #06231f;
	--opss-shadow: rgba(0, 0, 0, 0.60);
	--opss-w1: #2dd4bf;
	--opss-w2: #818cf8;
	--opss-w3: #fbbf24;
	--opss-w4: #38bdf8;
	--opss-w5: #fb7185;
}

/* ---- 2. WIDGET SHELL ----------------------------------------------------
   .opw is fixed and pointer-transparent; only the puck, the top button and
   the invisible hover zone accept the pointer. --opss-acc animates between
   the five hues via @property (a plain custom property cannot be
   transitioned). Browsers without @property still get the colour, just
   without the 1.6s crossfade. */

@property --opss-acc {
	syntax: '<color>';
	inherits: true;
	initial-value: #0d9488;
}

.opw {
	position: fixed;
	/* 16px from the corner, not the handoff's 20/24: .op-dock-trigger — the
	   platform's floating control on the opposite corner — sits at
	   16px + env(safe-area-inset-*), and the pair has to be symmetric about the
	   viewport. The safe-area term is the dock's too; it keeps the control clear
	   of the iOS home indicator. Instructed change. */
	right: calc(16px + env(safe-area-inset-right, 0px));
	bottom: calc(16px + env(safe-area-inset-bottom, 0px));
	z-index: 60;
	/* The handoff's page inherits line-height: normal from <body>;
	   .op-public-page sets 1.5, which rendered the tooltip and the badge
	   ~3px taller than the reference. Pin the reference's own value. */
	line-height: normal;
	--opss-acc: var(--opss-accent);
	pointer-events: none;
	transition: --opss-acc 1.6s cubic-bezier(.4, 0, .2, 1);
}

.opw-inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	position: relative;
	z-index: 1;
	pointer-events: none;
	transition: opacity .55s cubic-bezier(.16, 1, .3, 1), transform .68s cubic-bezier(.16, 1, .3, 1), filter .5s ease;
}

.opw-morph,
.opw-top {
	pointer-events: auto;
}

.opw[data-open="0"] .opw-track,
.opw[data-open="0"] .opw-thumb {
	pointer-events: none;
}

/* entrance / exit: scale + blur, never a hard cut. The exit curve is
   deliberately ease-IN, so the control accelerates away rather than
   mirroring its entrance. */
.opw[data-ready="0"] .opw-inner {
	opacity: 0;
	transform: translateY(18px) scale(.48);
	filter: blur(5px);
	pointer-events: none;
	transition: opacity .34s ease .06s, transform .6s cubic-bezier(.5, 0, .75, 0), filter .3s ease;
}

/* invisible hover catchment — grows with the rail so the pointer never falls out */
.opw-zone {
	position: absolute;
	right: -16px;
	bottom: -18px;
	width: 88px;
	height: 92px;
	border-radius: 24px;
	pointer-events: auto;
	z-index: 0;
	transition: width .5s cubic-bezier(.16, 1, .3, 1), height .55s cubic-bezier(.16, 1, .3, 1);
}

.opw[data-ready="0"] .opw-zone {
	pointer-events: none;
}

.opw[data-open="1"] .opw-zone {
	width: 112px;
	height: 392px;
}

/* ---- 3. BACK-TO-TOP BUTTON --------------------------------------------- */

.opw-topwrap {
	position: relative;
	display: flex;
	align-items: center;
	opacity: 0;
	transform: translateY(18px) scale(.62);
	pointer-events: none;
	transition: opacity .34s ease, transform .52s cubic-bezier(.16, 1, .3, 1);
}

.opw[data-open="1"] .opw-topwrap {
	opacity: 1;
	transform: none;
	pointer-events: auto;
	transition-delay: .14s;
}

.opw-top {
	position: relative;
	z-index: 1;
	width: 46px;
	height: 46px;
	border-radius: 999px;
	display: grid;
	place-items: center;
	border: 1px solid var(--opss-border);
	background: var(--opss-surface);
	color: var(--opss-text);
	cursor: pointer;
	box-shadow: 0 10px 30px var(--opss-shadow);
	transition: background .22s ease, color .22s ease, border-color .22s ease, transform .3s cubic-bezier(.16, 1, .3, 1), border-radius .45s cubic-bezier(.16, 1, .3, 1);
	/* Hardening only — provably no-ops on a fixed 46x46 grid box with one
	   centred child, but they stop a block theme's UA-ish button rules from
	   reaching in. */
	appearance: none;
	-webkit-appearance: none;
	font: inherit;
	margin: 0;
	padding: 0;
}

.opw-top:hover {
	transform: translateY(-2px);
	border-color: var(--opss-acc);
	color: var(--opss-acc);
}

.opw-top:focus-visible {
	outline: none;
	box-shadow: 0 0 0 3px var(--opss-accent-soft);
}

.opw-arw {
	transition: transform .72s cubic-bezier(.16, 1, .3, 1);
}

.opw-top:hover .opw-arw {
	transform: rotate(360deg) translateY(-1px);
}

.opw-tip {
	position: absolute;
	right: calc(100% + 12px);
	white-space: nowrap;
	padding: 7px 12px;
	border-radius: 9px;
	border: 1px solid var(--opss-border);
	background: var(--opss-surface-2);
	color: var(--opss-text);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .01em;
	box-shadow: 0 10px 26px var(--opss-shadow);
	opacity: 0;
	transform: translateX(10px) scale(.94);
	pointer-events: none;
	transition: opacity .22s ease, transform .38s cubic-bezier(.16, 1, .3, 1);
}

.opw-topwrap:hover .opw-tip {
	opacity: 1;
	transform: none;
}

/* colour halo: two counter-rotating conic blurs that read as light leaking
   from the button's border. Fades out over .75s when the pointer leaves —
   slow on purpose, so the light dies down rather than switching off. */
.opw-halowrap {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 0;
	height: 0;
	z-index: 0;
	pointer-events: none;
	opacity: 0;
	transition: opacity .75s cubic-bezier(.4, 0, .2, 1);
}

.opw-topwrap:hover .opw-halowrap {
	opacity: 1;
	transition-duration: .35s;
}

.opw-halo {
	position: absolute;
	left: 0;
	top: 0;
	width: 46px;
	height: 46px;
	margin: -23px 0 0 -23px;
	border-radius: 999px;
	background: conic-gradient(from 0deg, var(--opss-w1), var(--opss-w2), var(--opss-w3), var(--opss-w5), var(--opss-w4), var(--opss-w1));
	filter: blur(9px);
	animation: opwHalo 2.8s ease-in-out infinite;
	transition: border-radius .5s ease;
}

.opw-halo2 {
	position: absolute;
	left: 0;
	top: 0;
	width: 46px;
	height: 46px;
	margin: -23px 0 0 -23px;
	border-radius: 999px;
	background: conic-gradient(from 180deg, var(--opss-w4), var(--opss-w1), var(--opss-w2), var(--opss-w3), var(--opss-w4));
	filter: blur(3px);
	animation: opwRim 2.2s ease-in-out infinite;
}

@keyframes opwHalo {
	0%, 100% { opacity: .4; transform: scale(1.04) rotate(0deg); }
	50% { opacity: .95; transform: scale(1.32) rotate(180deg); }
}

@keyframes opwRim {
	0%, 100% { opacity: 0; transform: scale(1.01) rotate(0deg); }
	45% { opacity: .5; transform: scale(1.12) rotate(-120deg); }
}

.op-public-page[data-foot="1"] .opw-halo,
.op-public-page[data-foot="1"] .opw-halo2 {
	border-radius: 14px;
}

/* ---- 4. THE PUCK / RAIL (morph) ----------------------------------------
   The staggered delays are what makes it read as one gesture: the shell
   stretches, the line draws itself, the dot lands, then the button rises
   above it. */

.opw-morph {
	position: relative;
	/* 46px, not the handoff's 52: the platform already has a floating control
	   on the opposite corner (.op-dock-trigger) and the two have to read as one
	   family. Its trigger is 46x46 with a 1px border and an 18px icon, and so is
	   the back-to-top button directly above this one — so the whole stack is now
	   a single circle size. Instructed change; every other value is the
	   handoff's. */
	width: 46px;
	height: 46px;
	border-radius: 999px;
	border: 1px solid var(--opss-border);
	background: var(--opss-surface);
	color: var(--opss-text-muted);
	cursor: pointer;
	box-shadow: 0 10px 30px var(--opss-shadow);
	display: grid;
	place-items: center;
	padding: 0;
	-webkit-tap-highlight-color: transparent;
	transition: width .52s cubic-bezier(.16, 1, .3, 1), height .62s cubic-bezier(.16, 1, .3, 1), border-radius .52s cubic-bezier(.16, 1, .3, 1), background .25s ease, border-color .25s ease, box-shadow .35s ease, transform .5s cubic-bezier(.16, 1, .3, 1), opacity .3s ease;
}

.opw-morph:focus-visible {
	outline: none;
	border-color: var(--opss-acc);
	box-shadow: 0 0 0 3px var(--opss-accent-soft);
}

.opw[data-open="1"] .opw-morph {
	width: 44px;
	height: 268px;
	border-radius: 22px;
	border-color: var(--opss-border-strong);
	box-shadow: 0 18px 46px var(--opss-shadow);
}

/* in the footer the rail is gone; only the button parks in its slot */
.op-public-page[data-foot="1"] .opw .opw-morph {
	transform: scale(0);
	opacity: 0;
	pointer-events: none;
}

.op-public-page[data-foot="1"] .opw .opw-topwrap {
	opacity: 1;
	transform: none;
	pointer-events: auto;
	transition-delay: 0s;
}

.op-public-page[data-foot="1"] .opw-top {
	border-radius: 14px;
	background: var(--opss-ink);
	color: var(--opss-on-ink);
	border-color: transparent;
}

/* rotating icon set — one visible at a time, driven by data-cur.
   All five are stacked in one grid cell so the outgoing and incoming icon
   never reserve two slots. */
.opw-icons {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	transition: opacity .3s ease, transform .5s cubic-bezier(.16, 1, .3, 1), filter .3s ease;
}

.opw[data-open="1"] .opw-icons {
	opacity: 0;
	transform: scale(.4) rotate(-90deg);
	filter: blur(4px);
	pointer-events: none;
}

.opw-ic > svg {
	/* See .opw-morph: 18px is the dock trigger's icon, and the proportion the
	   handoff's 20-in-52 becomes at 46. */
	width: 18px;
	height: 18px;
}

.opw-ic {
	grid-area: 1/1;
	display: grid;
	place-items: center;
	opacity: 0;
	transform: rotate(-135deg) scale(.15);
	filter: blur(3px);
	transition: opacity .3s ease, transform .58s cubic-bezier(.16, 1, .3, 1), filter .3s ease;
}

.opw-icons[data-cur="0"] .opw-ic:nth-child(1),
.opw-icons[data-cur="1"] .opw-ic:nth-child(2),
.opw-icons[data-cur="2"] .opw-ic:nth-child(3),
.opw-icons[data-cur="3"] .opw-ic:nth-child(4),
.opw-icons[data-cur="4"] .opw-ic:nth-child(5) {
	opacity: 1;
	transform: none;
	filter: none;
	transition-delay: .16s;
	color: var(--opss-text);
}

/* ---- 5. TRACK, FILL, THUMB --------------------------------------------- */

.opw-track {
	position: absolute;
	left: 50%;
	top: 16px;
	bottom: 16px;
	width: 4px;
	margin-left: -2px;
	border-radius: 2px;
	background: var(--opss-border-strong);
	opacity: 0;
	transform: scaleY(.25);
	transform-origin: 50% 50%;
	transition: opacity .28s ease, transform .6s cubic-bezier(.16, 1, .3, 1);
}

.opw[data-open="1"] .opw-track {
	opacity: 1;
	transform: none;
	transition-delay: .1s;
}

.opw-fill {
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	height: 0;
	border-radius: 2px;
	background: linear-gradient(180deg, transparent, var(--opss-acc));
	opacity: .38;
	transition: opacity .6s cubic-bezier(.4, 0, .2, 1), box-shadow .6s ease;
}

.opw[data-scroll="1"] .opw-fill {
	box-shadow: 0 0 9px var(--opss-acc);
}

/* light lives on the thumb, so the glow is always where the eye is */
.opw-glow {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 18px;
	height: 112px;
	margin: -56px 0 0 -9px;
	border-radius: 9px;
	background: linear-gradient(180deg, transparent, var(--opss-acc) 46%, var(--opss-acc) 54%, transparent);
	filter: blur(9px);
	opacity: 0;
	pointer-events: none;
	transition: opacity .6s cubic-bezier(.4, 0, .2, 1);
}

.opw-thumb {
	position: absolute;
	left: 50%;
	top: 0;
	width: 18px;
	height: 18px;
	margin-left: -9px;
	cursor: grab;
	touch-action: none;
	opacity: 0;
	transition: opacity .3s ease;
}

.opw[data-open="1"] .opw-thumb {
	opacity: 1;
	transition-delay: .24s;
}

.opw[data-drag="1"] .opw-thumb {
	cursor: grabbing;
}

.opw-dot {
	position: absolute;
	inset: 0;
	border-radius: 999px;
	background: var(--opss-surface);
	border: 2px solid var(--opss-acc);
	box-shadow: 0 0 0 4px var(--opss-accent-soft), 0 4px 12px var(--opss-shadow);
	transition: box-shadow .25s ease, border-color .3s ease, background .25s ease;
}

.opw-thumb:hover .opw-dot,
.opw[data-drag="1"] .opw-dot {
	background: var(--opss-acc);
	box-shadow: 0 0 0 7px var(--opss-accent-soft), 0 0 18px var(--opss-acc);
}

.opw-badge {
	position: absolute;
	right: calc(100% + 14px);
	top: 50%;
	transform: translateY(-50%) translateX(8px);
	white-space: nowrap;
	padding: 5px 9px;
	border-radius: 8px;
	background: var(--opss-ink);
	color: var(--opss-on-ink);
	font-family: var(--op-font-mono, monospace);
	font-size: 11px;
	font-weight: 600;
	opacity: 0;
	pointer-events: none;
	transition: opacity .2s ease, transform .32s cubic-bezier(.16, 1, .3, 1);
}

.opw[data-drag="1"] .opw-badge,
.opw-thumb:hover .opw-badge {
	opacity: 1;
	transform: translateY(-50%);
}

/* section markers on the rail */
.opw-tick {
	/* Decoration only. As a hit target a tick swallows the pointerdown the
	   track needs, and the event then bubbles to the puck and closes the rail
	   — a 10px dead band across the middle of the rail on touch. */
	pointer-events: none;
	position: absolute;
	left: 50%;
	width: 10px;
	height: 1px;
	margin-left: -5px;
	background: var(--opss-text-quiet);
	opacity: 0;
	transition: opacity .3s ease;
}

.opw[data-open="1"] .opw-tick {
	opacity: .45;
	transition-delay: .2s;
}

/* ---- 6. FOOTER DOCK ----------------------------------------------------- */

.ops-dockslot {
	/* The puck's placeholder, so it tracks the puck's size. */
	width: 46px;
	height: 46px;
	flex: none;
	border-radius: 999px;
	border: 1px dashed var(--opss-border-strong);
	opacity: .55;
	transition: opacity .45s ease;
}

.op-public-page[data-foot="1"] .ops-dockslot {
	opacity: 0;
}

.ops-dockcap {
	display: flex;
	align-items: center;
	gap: 12px;
	line-height: normal; /* same reason as .opw */
}

.ops-docklbl {
	opacity: 0;
	transform: translateX(10px);
	transition: opacity .45s ease .1s, transform .6s cubic-bezier(.16, 1, .3, 1) .1s;
	/* The demo carries these three inline on the label; they are the
	   reference values, moved into the sheet. */
	color: var(--opss-text-quiet);
	font-size: 13px;
	white-space: nowrap;
}

.op-public-page[data-foot="1"] .ops-docklbl {
	opacity: 1;
	transform: none;
}

/* The footer row that holds the language switcher and the parking slot.
   It inherits the exact spacing the language block used to own on its own,
   so a page without a language switcher looks unchanged. */
.op-footer__utilrow {
	align-items: center;
	border-top: 1px solid var(--op-slate-200, #d9dee3);
	display: flex;
	flex-wrap: wrap;
	gap: 20px;
	justify-content: space-between;
	margin: 28px 0 24px;
	padding-top: 22px;
}

.op-footer__utilrow .op-footer__language-block {
	border-top: 0;
	margin: 0;
	padding-top: 0;
}

@media (max-width: 600px) {
	.op-footer__utilrow {
		margin: 22px 0 18px;
		padding-top: 18px;
	}
}

/* ---- 7. RESPONSIVE ------------------------------------------------------
   Three states, exactly as the handoff's sizing table specifies:
   desktop (fine pointer), <=760px, and any coarse-pointer device. Touch
   targets stay above the 44px floor in all three. */

@media (max-width: 760px) {
	/* .opw keeps the 16px corner offset at every width — see its base rule. */
	.opw-inner {
		gap: 10px;
	}

	.opw-morph {
		width: 46px;
		height: 46px;
	}

	.opw[data-open="1"] .opw-morph {
		width: 46px;
		height: 216px;
	}

	.opw-zone {
		right: -12px;
		bottom: -14px;
		width: 82px;
		height: 86px;
	}

	.opw[data-open="1"] .opw-zone {
		width: 104px;
		height: 322px;
	}

	.opw-thumb {
		width: 22px;
		height: 22px;
		margin-left: -11px;
	}

	.opw-top {
		width: 46px;
		height: 46px;
	}

	.opw-tip {
		display: none;
	}

	.ops-dockcap {
		width: 100%;
		justify-content: flex-end;
	}
}

@media (hover: none) {
	.opw-tip {
		display: none;
	}

	.opw[data-open="1"] .opw-morph {
		width: 46px;
	}

	.opw-thumb {
		width: 26px;
		height: 26px;
		margin-left: -13px;
	}

	.opw-track {
		width: 5px;
		margin-left: -2.5px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.opw *,
	.opw {
		animation: none !important;
		transition-duration: .01ms !important;
	}
}

/* ---- 7b. TOUCH HARDENING ------------------------------------------------
   The handoff was authored against a mouse. Four things it does not do are
   what a finger actually needs, and all four were reported from iOS on the
   first release of this control. None of them change a single pixel. */

/* iOS raises the selection/copy callout on a long press over any element that
   is selectable — which is what "holding the scrollbar starts copy mode" is.
   The controller sets document.body.style.userSelect during a drag, but that
   is both too late (the callout arms on touchstart) and blind to the callout
   itself, which is a separate WebKit property. */
.opw,
.opw-zone,
.opw-inner,
.opw-topwrap,
.opw-top,
.opw-morph,
.opw-track,
.opw-thumb {
	-webkit-touch-callout: none;
	-webkit-user-select: none;
	user-select: none;
	-webkit-tap-highlight-color: transparent;
}

/* The browser decides between "pan the page" and "hand the gesture to the
   element" at touchstart, from touch-action alone — a preventDefault() on the
   first pointermove arrives after that decision. Without this the page pans
   under the thumb while the rail also scrolls it, which is the jumping and
   rubber-banding. The handoff sets it on .opw-thumb only; the track is the
   other half of the same control. */
.opw-track,
.opw-thumb {
	touch-action: none;
}

@media (hover: none) {
	/* There is no hover on a touch device, so the catchment cannot do its job
	   — all it does is lay an invisible 104x322 slab over the right edge that
	   swallows taps meant for the page underneath. */
	.opw-zone {
		pointer-events: none;
	}

	/* A 4-5px rail is not grabbable with a finger. This extends the track's
	   HIT area across the whole rail body without painting anything: a
	   pseudo-element is hit-tested but is not an event target, so pointerdown
	   still arrives with e.target === .opw-track. The thumb is a real child
	   and paints later, so it still wins where it overlaps.

	   This is also what stops a finger on the rail body from panning the page
	   and then, on release, firing a click on the puck that shuts the rail. */
	.opw-track::before {
		content: '';
		position: absolute;
		top: -16px;
		bottom: -16px;
		left: -22px;
		right: -22px;
	}
}

/* ---- 7c. THE SINGLE-OFFER STICKY APPLY BAR ------------------------------
   That bar is fixed, full width and z-index 90; the control rests at z 60 and
   24px from the bottom, so the bar simply covered it. The platform already
   solves this for the floating utility dock by lifting it while
   body.op-sticky-apply-active is set — the control now rides the same class,
   keeping its own resting offsets rather than the dock's.

   72px is the platform's own figure for the bar: .op-public-template
   .op-sticky-apply-active reserves exactly that much page padding, and the
   utility dock lifts by the same amount. */

/* The transition is scoped to the one route that owns the bar, so every other
   template keeps the handoff's transition list byte-for-byte. */
.op-single-offer .opw {
	transition: --opss-acc 1.6s cubic-bezier(.4, 0, .2, 1), bottom 180ms ease;
}

.op-sticky-apply-active .opw {
	bottom: calc(16px + 72px + env(safe-area-inset-bottom, 0px));
}

/* ---- 7d. SIMPLE MODE — TOUCH AND SMALL SCREENS --------------------------
   On a phone or a tablet the rail is the wrong control: a 4px line dragged
   with a thumb, over a page that is already scrolling under it. Below the
   platform's own mobile/tablet boundary — the same 1180px at which the utility
   dock hides and the burger menu takes over — and on any touch device, the
   control collapses to the one thing it does well there: back to top.

   The rail, its drag machinery and the five rotating icons all go together:
   the puck is the icons' host, and a control with a single function has
   nothing to rotate through. The controller reads this decision back out of
   the computed style (see simpleMode in the JS), so this media query stays the
   single source of truth for the breakpoint. */

@media (max-width: 1180px), (hover: none) {
	.opw-morph {
		display: none;
	}

	/* The button no longer waits for a rail that will never open. */
	.opw-topwrap {
		opacity: 1;
		transform: none;
		pointer-events: auto;
		transition-delay: 0s;
	}

	/* Nothing to catch: there is no hover, and no rail to hold open. */
	.opw-zone {
		display: none;
	}
}

/* ---- 8. RTL -------------------------------------------------------------
   Not in the handoff (its demo page is LTR only), but this platform ships
   Persian and Arabic. The control keeps its edge — the outer edge away from
   the utility dock, which itself mirrors to the right in RTL — so the two
   floating controls never stack on the same corner.

   Only the four directional declarations flip. Sizes, timings and curves are
   the handoff's, untouched. */

html[dir="rtl"] .opw {
	left: calc(16px + env(safe-area-inset-left, 0px));
	right: auto;
}

html[dir="rtl"] .opw-zone {
	left: -16px;
	right: auto;
}

html[dir="rtl"] .opw-tip {
	left: calc(100% + 12px);
	right: auto;
	transform: translateX(-10px) scale(.94);
}

html[dir="rtl"] .opw-topwrap:hover .opw-tip {
	transform: none;
}

html[dir="rtl"] .opw-badge {
	left: calc(100% + 14px);
	right: auto;
	transform: translateY(-50%) translateX(-8px);
}

html[dir="rtl"] .opw[data-drag="1"] .opw-badge,
html[dir="rtl"] .opw-thumb:hover .opw-badge {
	transform: translateY(-50%);
}

html[dir="rtl"] .ops-docklbl {
	transform: translateX(-10px);
}

html[dir="rtl"] .op-public-page[data-foot="1"] .ops-docklbl {
	transform: none;
}

/* .ops-dockcap keeps `justify-content: flex-end` in both directions —
   flex-end is writing-mode relative, so in RTL it already resolves to the
   left edge, the same edge the control parks on. */

@media (max-width: 760px) {
	html[dir="rtl"] .opw-zone {
		left: -12px;
		right: auto;
	}
}
