/* ============================================================
   SoftoAI Motion — premium reveal engine (CWV-safe)
   Base state = FINAL state (fail-open, LCP-safe). The JS engine
   adds .sa-armed only to below-fold elements; nothing is hidden
   by CSS alone, so blocked/slow JS never blanks content.
   ============================================================ */
:root {
	--sa-ease: cubic-bezier(0.22, 1, 0.36, 1); /* expo-out — the "signature" */
	--sa-dur: 0.9s;
	--sa-shift: 26px;
	--sa-stagger-step: 90ms;
}

/* Reveal ---------------------------------------------------- */
/* Final state — no rules needed; the element renders normally. */

/* From-state (added by JS to below-fold elements only). */
.sa-reveal.sa-armed {
	opacity: 0;
	transform: translate3d(0, var(--sa-shift), 0);
	will-change: opacity, transform;
}
.sa-reveal.sa-armed.sa-fade {
	transform: none; /* fade only, no movement */
}

/* Premium reveal flavours — all overflow-safe (no horizontal slide) and
   CWV-safe (transform/opacity/filter/clip only). Applied via modifier class. */
.sa-reveal.sa-armed.sa-scale { transform: scale(0.94); }
.sa-reveal.sa-armed.sa-blur  { filter: blur(14px); }
.sa-reveal.sa-armed.sa-clip  { transform: none; clip-path: inset(0 0 100% 0); }
.sa-reveal.sa-armed.sa-rise-lg { transform: translate3d(0, calc(var(--sa-shift) * 2.4), 0); }

/* Play to final. */
.sa-reveal.sa-in {
	opacity: 1;
	transform: none;
	filter: none;
	clip-path: inset(0 0 0 0);
	transition:
		opacity var(--sa-dur) var(--sa-ease),
		transform var(--sa-dur) var(--sa-ease),
		filter var(--sa-dur) var(--sa-ease),
		clip-path var(--sa-dur) var(--sa-ease);
}

/* Stagger (container children) ----------------------------- */
.sa-stagger.sa-armed > * {
	opacity: 0;
	transform: translate3d(0, var(--sa-shift), 0);
	will-change: opacity, transform;
}
.sa-stagger.sa-in > * {
	opacity: 1;
	transform: none;
	transition: opacity var(--sa-dur) var(--sa-ease), transform var(--sa-dur) var(--sa-ease);
	/* --i is set per child by the engine. */
	transition-delay: calc(var(--i, 0) * var(--sa-stagger-step));
}

/* Reduced motion — belt-and-braces (engine also bails early). */
@media (prefers-reduced-motion: reduce) {
	.sa-reveal.sa-armed,
	.sa-stagger.sa-armed > * {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
}

/* ============================================================
   Hover treatments (CSS-only, zero JS)
   ============================================================ */
/* Image zoom within a fixed frame. */
.sa-zoom { overflow: hidden; }
.sa-zoom img { transition: transform 0.7s var(--sa-ease); will-change: transform; }
.sa-zoom:hover img { transform: scale(1.06); }

/* Duotone / grayscale → full colour on hover. */
.sa-duo img { filter: grayscale(1) contrast(1.03); transition: filter 0.5s var(--sa-ease); }
.sa-duo:hover img { filter: none; }

/* Lift — subtle raise + shadow. */
.sa-lift { transition: transform 0.4s var(--sa-ease), box-shadow 0.4s var(--sa-ease); }
.sa-lift:hover { transform: translate3d(0, -6px, 0); box-shadow: 0 24px 50px rgba(0, 0, 0, 0.18); }

/* ============================================================
   Scroll-image treatments
   ============================================================ */
/* Ken Burns — slow continuous zoom/pan. */
.sa-kenburns { overflow: hidden; }
.sa-kenburns img { animation: sa-kb 20s ease-in-out infinite alternate; will-change: transform; }
@keyframes sa-kb {
	from { transform: scale(1) translate(0, 0); }
	to   { transform: scale(1.12) translate(2%, -2%); }
}

/* Parallax on the inner image only (leaf media — never transforms an ancestor,
   so it can't break sticky/fixed descendants). Native CSS scroll-driven timeline
   runs OFF the main thread; unsupported browsers simply no-op (progressive). */
.sa-parallax { overflow: hidden; }
@media (hover: hover) and (pointer: fine) {
	@supports (animation-timeline: view()) {
		.sa-parallax img {
			animation: sa-par linear both;
			animation-timeline: view();
			animation-range: cover;
			will-change: transform;
		}
	}
}
@keyframes sa-par {
	from { transform: translate3d(0, -8%, 0) scale(1.16); }
	to   { transform: translate3d(0, 8%, 0) scale(1.16); }
}

@media (prefers-reduced-motion: reduce) {
	.sa-zoom:hover img,
	.sa-lift:hover { transform: none; }
	.sa-kenburns img,
	.sa-parallax img { animation: none; }
}

/* ============================================================
   Narrative / scroll-scrub (native CSS scroll-driven — off main thread,
   progressive: unsupported browsers simply render the final state)
   ============================================================ */
/* Sticky pin — hold an element while siblings scroll past. */
.sa-sticky { position: sticky; top: var(--sa-sticky-top, 90px); align-self: flex-start; }

/* Scrub brighten — dim → full as the element passes through the viewport. */
.sa-scrub { opacity: 1; }
@supports (animation-timeline: view()) {
	.sa-scrub {
		animation: sa-scrub linear both;
		animation-timeline: view();
		animation-range: entry 8% cover 42%;
	}
}
@keyframes sa-scrub { from { opacity: 0.28; } to { opacity: 1; } }

/* Scroll-progress bar — scaleX driven by document scroll. */
.sa-scrollbar {
	position: fixed;
	top: 0;
	left: 0;
	height: var(--sa-sb-h, 3px);
	width: 100%;
	transform: scaleX(0);
	transform-origin: 0 50%;
	background: var(--sa-sb-color, #a9783a);
	z-index: 9999;
}
@supports (animation-timeline: scroll()) {
	.sa-scrollbar {
		animation: sa-sb linear both;
		animation-timeline: scroll(root);
	}
}
@keyframes sa-sb { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* Horizontal scroll gallery — native scroll-snap (mobile-swipe friendly). */
.sa-hgallery {
	display: flex;
	gap: 20px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	padding-bottom: 10px;
	scrollbar-width: thin;
}
.sa-hgallery__item {
	flex: 0 0 var(--sa-hg-w, min(78%, 460px));
	scroll-snap-align: center;
	border-radius: 16px;
	overflow: hidden;
	aspect-ratio: 4 / 3;
	background: #15140f;
}
.sa-hgallery__item img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (prefers-reduced-motion: reduce) {
	.sa-scrub { animation: none; opacity: 1; }
	.sa-scrollbar { display: none; }
}

/* ============================================================
   Marquee widget
   ============================================================ */
.sa-marquee {
	overflow: hidden;
	display: flex;
	width: 100%;
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.sa-marquee__track {
	display: flex;
	flex: 0 0 auto;
	align-items: center;
	gap: var(--sa-mq-gap, 3rem);
	padding-right: var(--sa-mq-gap, 3rem);
	min-width: 100%;
	animation: sa-mq var(--sa-mq-dur, 24s) linear infinite;
}
.sa-marquee--reverse .sa-marquee__track { animation-direction: reverse; }
.sa-marquee--pause:hover .sa-marquee__track { animation-play-state: paused; }
.sa-marquee--nofade { -webkit-mask-image: none; mask-image: none; }
.sa-marquee__item { flex: 0 0 auto; display: inline-flex; align-items: center; }
.sa-marquee__item img { display: block; height: var(--sa-mq-h, 40px); width: auto; }

@keyframes sa-mq { to { transform: translate3d(-50%, 0, 0); } }

@media (prefers-reduced-motion: reduce) {
	.sa-marquee__track { animation: none; }
	.sa-marquee { -webkit-mask-image: none; mask-image: none; overflow-x: auto; }
}
