/* ==================================================================
   WAXORBIT - 3D INTERACTIVE FRAGRANCE HERO
   Loaded only on the front page, only when the 3D hero is enabled.
   Every selector is scoped to .wo-hero3d, so nothing here can reach
   the header, footer, WooCommerce, or other homepage sections.

   Layout contract with the script:
     .wo-hero3d__focus  - an invisible box that marks WHERE the product
                          should appear. The script reads its size and
                          position and frames the 3D camera to fill it.
                          Change the composition here, not in JS.
     --wo-hero3d-stacked - 1 = copy under the product (phones, tablets
                          in portrait), 0 = copy beside it. The shader
                          uses this to place its legibility scrim.
   ================================================================== */

.wo-hero3d {
	--wo-hero3d-stacked: 1;

	position: relative;
	isolation: isolate;
	overflow: hidden;
	display: flex;
	align-items: stretch;
	min-height: 100vh;
	min-height: 100svh;
	background: var(--wo-bg);
	color: var(--wo-text);
	-webkit-tap-highlight-color: transparent;
}

/* ---- Stage: canvas + poster, full bleed behind everything ---- */

.wo-hero3d__stage {
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
}

/* Ambient fallback glow: what visitors without WebGL see behind the
   poster, and what everyone sees for the split second before the
   canvas fades in. */
.wo-hero3d__stage::before,
.wo-hero3d__stage::after {
	content: '';
	position: absolute;
	inset: -20%;
	pointer-events: none;
	transition: opacity 1.2s var(--wo-ease-out);
}

.wo-hero3d__stage::before {
	background:
		radial-gradient(22% 20% at 70% 44%, rgba(255, 110, 180, 0.20), transparent 70%),
		radial-gradient(20% 18% at 76% 58%, rgba(160, 100, 255, 0.22), transparent 70%),
		radial-gradient(18% 16% at 66% 60%, rgba(255, 215, 90, 0.14), transparent 70%);
	filter: blur(30px);
	animation: wo-hero3d-drift 22s ease-in-out infinite alternate;
}

.wo-hero3d__stage::after {
	background:
		linear-gradient(90deg, var(--wo-bg) 0%, rgba(20, 14, 42, 0.55) 45%, rgba(20, 14, 42, 0) 70%);
}

@keyframes wo-hero3d-drift {
	from { transform: translate3d(-3%, -2%, 0) rotate(-2deg) scale(1); }
	to   { transform: translate3d(3%, 2%, 0) rotate(2deg) scale(1.06); }
}

.wo-hero3d__canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
	opacity: 0;
	transition: opacity 1.1s var(--wo-ease-out);
}

.wo-hero3d.is-3d-ready .wo-hero3d__canvas {
	opacity: 1;
}

.wo-hero3d.is-3d-ready .wo-hero3d__stage::before,
.wo-hero3d.is-3d-ready .wo-hero3d__stage::after {
	opacity: 0;
}

/* ---- Content grid ---- */

.wo-hero3d__inner {
	position: relative;
	z-index: 2;
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	grid-template-rows: minmax(clamp(280px, 48svh, 480px), 1fr) auto;
	padding-top: var(--wo-header-offset);
	padding-bottom: clamp(2.25rem, 7vw, 4rem);
	pointer-events: none;
}

.wo-hero3d__inner > .wo-hero3d__content {
	pointer-events: auto;
}

/* Where the product appears. Invisible - see the header comment. */
.wo-hero3d__focus {
	grid-row: 1;
	grid-column: 1;
	justify-self: center;
	align-self: stretch;
	width: min(66vw, 320px);
	min-height: 260px;
	margin-block: var(--wo-space-2) var(--wo-space-16);
	position: relative;
	pointer-events: none;
}

.wo-hero3d__content {
	grid-row: 2;
	grid-column: 1;
	justify-self: center;
	text-align: center;
	max-width: 36rem;
}

.wo-hero3d .wo-hero__text {
	margin-inline: auto;
}

.wo-hero3d .wo-hero__actions {
	justify-content: center;
}

/* ---- Poster: ONLY for devices that can't run 3D, or JS off ----
   With JS on, the poster is display:none (so its lazy image is never
   even downloaded) and the hero shows its glow + copy until the 3D
   scene fades in - no old image appears first. */

.wo-hero3d__poster {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: opacity 0.9s var(--wo-ease-out), visibility 0s linear 0s;
}

.wo-hero3d .wo-hero3d__poster img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	max-width: none;
	object-fit: contain;
	object-position: center;
	filter: drop-shadow(0 30px 40px rgba(8, 4, 22, 0.55));
}

.wo-hero3d .wo-hero3d__poster--photo img {
	object-fit: cover;
	border-radius: var(--wo-radius-xl);
	filter: none;
	box-shadow: var(--wo-shadow-lg);
}

.js .wo-hero3d__poster {
	display: none;
}

.js .wo-hero3d.is-3d-unsupported .wo-hero3d__poster,
.js .wo-hero3d.is-3d-failed:not(.is-3d-ready) .wo-hero3d__poster {
	display: flex;
}

/* ---- Hotspot: the accessible "activate" button over the bottle ---- */

.wo-hero3d__hotspot {
	position: absolute;
	top: 0;
	left: 0;
	z-index: 3;
	width: 0;
	height: 0;
	pointer-events: none;
	will-change: transform;
	opacity: 0;
	transition: opacity 0.6s var(--wo-ease-out) 0.6s;
}

.wo-hero3d.is-3d-ready .wo-hero3d__hotspot {
	opacity: 1;
}

.wo-hero3d:not(.is-3d-ready) .wo-hero3d__hotspot {
	visibility: hidden;
}

.wo-hero3d__activate {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	padding: 0;
	margin: 0;
	border: 0;
	border-radius: 42% / 30%;
	background: transparent;
	cursor: pointer;
	pointer-events: auto;
	touch-action: manipulation;
	-webkit-appearance: none;
	appearance: none;
}

.wo-hero3d__activate:disabled {
	cursor: default;
}

.wo-hero3d__activate:focus {
	outline: none;
}

.wo-hero3d__activate:focus-visible {
	box-shadow: var(--wo-ring);
}

/* Touch point: a quiet pulse on the wooden cap. */
.wo-hero3d__ring {
	position: absolute;
	left: 50%;
	top: 5%;
	width: 18px;
	height: 18px;
	margin: -9px 0 0 -9px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.18);
	border: 1.5px solid rgba(255, 255, 255, 0.75);
	box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.5), 0 0 14px rgba(255, 120, 190, 0.45);
	animation: wo-hero3d-pulse 2.4s var(--wo-ease-out) infinite;
	pointer-events: none;
	transition: opacity var(--wo-duration-slow) var(--wo-ease);
}

@keyframes wo-hero3d-pulse {
	0%   { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.45), 0 0 14px rgba(255, 120, 190, 0.45); }
	70%  { box-shadow: 0 0 0 22px rgba(255, 255, 255, 0), 0 0 14px rgba(255, 120, 190, 0.45); }
	100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0), 0 0 14px rgba(255, 120, 190, 0.45); }
}

.wo-hero3d__hint {
	position: absolute;
	left: 50%;
	top: 100%;
	transform: translate(-50%, 0.5rem);
	padding: 0.45rem 0.95rem;
	border-radius: var(--wo-radius-pill);
	background: rgba(20, 14, 42, 0.55);
	border: 1px solid var(--wo-line);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
	color: var(--wo-text-muted);
	font-size: var(--wo-text-xs);
	font-weight: var(--wo-weight-medium);
	letter-spacing: var(--wo-tracking-wide);
	white-space: nowrap;
	pointer-events: none;
	transition: opacity var(--wo-duration-slow) var(--wo-ease), transform var(--wo-duration-slow) var(--wo-ease);
}

.wo-hero3d.is-activated .wo-hero3d__ring,
.wo-hero3d.is-activated .wo-hero3d__hint {
	opacity: 0;
}

.wo-hero3d.is-diffusing .wo-hero3d__ring {
	opacity: 0.35;
	animation-duration: 4s;
}

.wo-hero3d.is-diffusing .wo-hero3d__hint {
	opacity: 0;
	transform: translate(-50%, 0.9rem);
}

/* ------------------------------------------------------------------
   600px+ : tablets in portrait - more room for the product
   ------------------------------------------------------------------ */

@media (min-width: 600px) {

	.wo-hero3d__inner {
		grid-template-rows: minmax(clamp(340px, 50svh, 620px), 1fr) auto;
	}

	.wo-hero3d__focus {
		width: min(46vw, 380px);
	}
}

/* ------------------------------------------------------------------
   992px+ and landscape : copy beside the product
   ------------------------------------------------------------------ */

@media (min-width: 992px), (orientation: landscape) and (min-width: 600px) and (max-height: 600px) {

	.wo-hero3d {
		--wo-hero3d-stacked: 0;
	}

	.wo-hero3d__inner {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		grid-template-rows: minmax(0, 1fr);
		align-items: center;
		padding-bottom: var(--wo-space-12);
	}

	.wo-hero3d__content {
		grid-row: 1;
		grid-column: 1;
		justify-self: start;
		text-align: left;
	}

	.wo-hero3d .wo-hero__text {
		margin-inline: 0;
	}

	.wo-hero3d .wo-hero__actions {
		justify-content: flex-start;
	}

	.wo-hero3d__focus {
		grid-row: 1;
		grid-column: 2;
		align-self: center;
		justify-self: center;
		width: min(100%, 440px);
		height: min(66svh, 760px);
		margin: 0;
	}

	.wo-hero3d__stage::before {
		transform-origin: 70% 50%;
	}
}

/* Landscape phones: the copy is tight, so it gets a smaller type scale. */
@media (orientation: landscape) and (max-height: 600px) and (max-width: 991.98px) {

	.wo-hero3d__inner {
		padding-top: calc(var(--wo-header-offset) - var(--wo-space-4));
		padding-bottom: var(--wo-space-6);
	}

	.wo-hero3d__focus {
		height: 72svh;
	}

	.wo-hero3d .wo-hero__logotype {
		font-size: var(--wo-text-3xl);
	}

	.wo-hero3d .wo-hero__text {
		display: none;
	}
}

@media (min-width: 1440px) {

	.wo-hero3d__focus {
		height: min(70svh, 820px);
	}
}

/* Short laptop screens. */
@media (min-width: 992px) and (max-height: 760px) {

	.wo-hero3d__focus {
		height: 70svh;
	}
}

/* ------------------------------------------------------------------
   Reduced motion: no drift, no pulse. The 3D scene itself renders a
   still frame (see loader.js), and activation jumps to the result.
   ------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {

	.wo-hero3d__stage::before,
	.wo-hero3d__ring {
		animation: none;
	}

	.wo-hero3d__canvas,
	.wo-hero3d__poster,
	.wo-hero3d__hotspot {
		transition: none;
	}
}

/* Hint wording follows the input the visitor actually has. */
.wo-hero3d__hint--fine {
	display: none;
}

@media (hover: hover) and (pointer: fine) {

	.wo-hero3d__hint--fine {
		display: inline;
	}

	.wo-hero3d__hint--touch {
		display: none;
	}
}

/* ------------------------------------------------------------------
   Loading screen
   Shown (with JS) until the 3D scene is ready: the whole hero softly
   blurred, the WaxOrbit mark slowly turning inside a ring that fills
   with the real progress, and the percentage counting 1% ... 100%.
   loader.js adds .is-3d-loaded after "100%" has been shown briefly;
   it never shows for visitors who get the still render instead.
   ------------------------------------------------------------------ */

.wo-hero3d__loading {
	position: absolute;
	inset: 0;
	z-index: 5;
	display: none;
	place-items: center;
	background:
		radial-gradient(40% 40% at 50% 50%, rgba(124, 92, 255, 0.2), transparent 70%),
		rgba(20, 14, 42, 0.55);
	-webkit-backdrop-filter: blur(18px) saturate(120%);
	backdrop-filter: blur(18px) saturate(120%);
	transition: opacity 0.9s var(--wo-ease-out), visibility 0s linear 0.9s;
}

.js .wo-hero3d__loading {
	display: grid;
}

.wo-hero3d.is-3d-loaded .wo-hero3d__loading,
.wo-hero3d.is-3d-unsupported .wo-hero3d__loading,
.wo-hero3d.is-3d-failed:not(.is-3d-ready) .wo-hero3d__loading {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

.wo-hero3d__loading-inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--wo-space-4);
}

.wo-hero3d__loading-badge {
	position: relative;
	width: clamp(120px, 14vw, 168px);
	aspect-ratio: 1;
	display: grid;
	place-items: center;
}

.wo-hero3d__loading-ring {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	transform: rotate(-90deg);
	overflow: visible;
}

.wo-hero3d__loading-track,
.wo-hero3d__loading-bar {
	fill: none;
	stroke-width: 3;
}

.wo-hero3d__loading-track {
	stroke: rgba(255, 255, 255, 0.12);
}

.wo-hero3d__loading-bar {
	stroke: url(#wo-hero3d-ring-grad);
	stroke-linecap: round;
	stroke-dasharray: 100 100;
	stroke-dashoffset: 100;
	filter: drop-shadow(0 0 6px rgba(255, 122, 192, 0.55));
}

.wo-hero3d__loading-mark {
	width: 62%;
	height: auto;
	border-radius: 24%;
	filter: drop-shadow(0 0 22px rgba(124, 92, 255, 0.55));
	animation: wo-hero3d-turn 6s linear infinite, wo-hero3d-breathe 3s ease-in-out infinite alternate;
}

.wo-hero3d__loading-pct {
	margin: 0;
	min-width: 4ch;
	text-align: center;
	font-family: var(--wo-font-body);
	font-size: var(--wo-text-lg);
	font-weight: var(--wo-weight-semibold);
	letter-spacing: var(--wo-tracking-wide);
	font-variant-numeric: tabular-nums;
	color: var(--wo-text);
	text-shadow: 0 0 18px rgba(155, 107, 255, 0.6);
}

@keyframes wo-hero3d-turn {
	from { transform: rotate(0deg); }
	to   { transform: rotate(360deg); }
}

@keyframes wo-hero3d-breathe {
	from { opacity: 0.75; }
	to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
	.wo-hero3d__loading-mark {
		animation: none;
	}

	.wo-hero3d__loading {
		transition: none;
	}
}

/* The pulsing touch dot on the cap is hidden - the whole bottle is the
   button (cursor changes to a pointer, keyboard focus still shows a ring). */
.wo-hero3d__ring {
	display: none;
}
