/*
 * Motion presets. Which element uses which preset: assets/motion.json (one map for the whole site).
 * Timing tokens: theme.json custom.motion. Runner: assets/js/motion.js (adds .is-in when an element scrolls in).
 *
 * Everything that hides content is scoped to html.zain-motion, which a head script sets only when the visitor
 * hasn't asked for reduced motion — so no-JS, reduced motion, the editor and scripts/figma-check.py see the page
 * exactly as designed. Each preset sets the start values below; .is-in returns them to normal.
 * Only opacity, translate, scale, filter and mask move — never layout.
 *
 *   fade-up   rise + fade (the classic scroll reveal)        fade-down  header drop-in on load
 *   zoom-in   scale up from 94% + fade                      blur-in    rise out of a blur (Apple-style statement)
 *   words     heading revealed word by word (split by JS)   reveal     photo fades in from a blur to sharp, rises a little
 *   count     number counts up (JS), no fade of its own     art        the element's ::before/::after art rises in
 *   draw      ::before/::after arrows draw left → right     hero       backdrop settles (Ken Burns), people rise
 */

html.zain-motion [data-zm],
html.zain-motion [data-zm-children] > * {
	--zm-delay: calc(var(--zm-wait, 0ms) + var(--zm-i, 0) * var(--wp--custom--motion--step));
	opacity: var(--zm-opacity, 0);
	translate: var(--zm-translate, 0 0);
	scale: var(--zm-scale, 1);
	filter: var(--zm-filter, none);
	transition:
		opacity var(--wp--custom--motion--duration) var(--wp--custom--motion--ease) var(--zm-delay),
		translate var(--wp--custom--motion--duration) var(--wp--custom--motion--ease) var(--zm-delay),
		scale var(--wp--custom--motion--duration) var(--wp--custom--motion--ease) var(--zm-delay),
		filter var(--wp--custom--motion--duration) var(--wp--custom--motion--ease) var(--zm-delay),
		transform var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--ease);
}

html.zain-motion [data-zm].is-in,
html.zain-motion [data-zm-children] > .is-in {
	opacity: 1;
	translate: 0 0;
	scale: 1;
	filter: none;
}

/* Containers that only stagger their children stay put */
html.zain-motion [data-zm-children]:not([data-zm]) {
	opacity: 1;
	translate: none;
	scale: none;
	filter: none;
	transition: none;
}

/* An in-page link to a part that hasn't risen in yet (Home "Book Now" → calendar): the browser aims at its lowered
   start position, so it would land one distance too far once it rises. Aim one distance lower instead. */
html.zain-motion [data-zm="fade-up"][id]:not(.is-in) {
	scroll-margin-top: calc(var(--zain-scroll-gap, 0px) + var(--wp--custom--motion--distance));
}

/* ------------------------------------------------------------------ Presets: start values */

[data-zm="fade-up"],
[data-zm-children="fade-up"] > * {
	--zm-translate: 0 var(--wp--custom--motion--distance);
}

[data-zm="fade-down"] {
	--zm-translate: 0 calc(-0.5 * var(--wp--custom--motion--distance));
}

[data-zm="zoom-in"],
[data-zm-children="zoom-in"] > * {
	--zm-scale: 0.94;
	--zm-translate: 0 calc(0.5 * var(--wp--custom--motion--distance));
}

[data-zm="blur-in"] {
	--zm-translate: 0 calc(0.5 * var(--wp--custom--motion--distance));
	--zm-filter: blur(12px);
}

/* reveal: the photo fades in from a soft blur to sharp while it rises a little (slower than blur-in for text) */
[data-zm="reveal"] {
	--zm-translate: 0 calc(0.5 * var(--wp--custom--motion--distance));
	--zm-filter: blur(16px);
}

html.zain-motion [data-zm="reveal"] {
	transition:
		opacity var(--wp--custom--motion--duration-slow) var(--wp--custom--motion--ease) var(--zm-delay),
		translate var(--wp--custom--motion--duration-slow) var(--wp--custom--motion--ease) var(--zm-delay),
		filter var(--wp--custom--motion--duration-slow) var(--wp--custom--motion--ease) var(--zm-delay);
}

/* Elements whose own box doesn't move: their art or children animate instead */
[data-zm="count"],
[data-zm="art"],
[data-zm="draw"],
[data-zm="hero"],
[data-zm="words"] {
	--zm-opacity: 1;
}

/* words: hidden until motion.js has split it, then each word rises out of a blur */
html.zain-motion [data-zm="words"]:not(.zain-split) {
	opacity: 0;
}

.zain-word {
	display: inline-block;
	max-width: 100%; /* a word longer than the line still wraps ("Qualifications" at 320px) */
}

html.zain-motion [data-zm="words"] .zain-word {
	opacity: 0;
	translate: 0 0.35em;
	filter: blur(8px);
	transition:
		opacity var(--wp--custom--motion--duration) var(--wp--custom--motion--ease),
		translate var(--wp--custom--motion--duration) var(--wp--custom--motion--ease),
		filter var(--wp--custom--motion--duration) var(--wp--custom--motion--ease);
	transition-delay: calc(var(--zm-delay) + var(--zm-w, 0) * 70ms);
}

html.zain-motion [data-zm="words"].is-in .zain-word {
	opacity: 1;
	translate: 0 0;
	filter: none;
}

/* art: decorative ::before / ::after layers rise in after the content — only where they ARE art, never a colour band */
html.zain-motion [data-zm="art"]::before,
html.zain-motion [data-zm="art"]::after {
	opacity: 0;
	translate: 0 calc(1.5 * var(--wp--custom--motion--distance));
	transition:
		opacity var(--wp--custom--motion--duration-slow) var(--wp--custom--motion--ease) calc(var(--zm-delay) + 300ms),
		translate var(--wp--custom--motion--duration-slow) var(--wp--custom--motion--ease) calc(var(--zm-delay) + 300ms);
}

html.zain-motion [data-zm="art"].is-in::before,
html.zain-motion [data-zm="art"].is-in::after {
	opacity: 1;
	translate: 0 0;
}

/*
 * Runner (Home services, 292:347 / 386:2482): a trigger played him while he was still out of sight (desktop: with
 * the grid's top; mobile: with the Mood card's top), so he was always seen standing still. He is tied to the scroll
 * instead — he runs in from the lower left as his box comes up the screen and arrives at mid-screen, backwards when
 * scrolling up. Browsers without scroll-driven animations keep the art preset (desktop) or nothing.
 */
@supports (animation-timeline: view()) {
	html.zain-motion .zain-services__grid::after,
	html.zain-motion .zain-service--mood::after {
		transition: none;
		animation: zain-run-in linear both;
		animation-timeline: view();
		animation-range: entry 20% cover 50%;
	}
}

@keyframes zain-run-in {
	from {
		opacity: 0;
		translate: -22% 8%;
	}

	to {
		opacity: 1;
		translate: 0 0;
	}
}

/* draw: arrows (Why CBT) unroll in reading direction — the lower-left arrow (::after, card 1 → card 2) first, then
   the upper one (::before, card 2 → card 3) once it has finished (Habib 2026-10-22) */
html.zain-motion [data-zm="draw"]::before,
html.zain-motion [data-zm="draw"]::after {
	clip-path: inset(0 100% 0 0);
	transition: clip-path var(--wp--custom--motion--duration-slow) var(--wp--custom--motion--ease-in-out) calc(var(--zm-delay) + 400ms + var(--wp--custom--motion--duration-slow));
}

html.zain-motion [data-zm="draw"]::after {
	transition-delay: calc(var(--zm-delay) + 400ms);
}

html.zain-motion [data-zm="draw"].is-in::before,
html.zain-motion [data-zm="draw"].is-in::after {
	clip-path: inset(0);
}

/* hero: backdrop settles from 108% (Ken Burns), the people rise in over it */
html.zain-motion [data-zm="hero"]::before {
	scale: 1.08;
	transition: scale 2.4s var(--wp--custom--motion--ease);
}

html.zain-motion [data-zm="hero"]::after {
	opacity: 0;
	translate: 0 8%;
	transition:
		opacity var(--wp--custom--motion--duration-slow) var(--wp--custom--motion--ease) 400ms,
		translate var(--wp--custom--motion--duration-slow) var(--wp--custom--motion--ease) 400ms;
}

html.zain-motion [data-zm="hero"].is-in::before {
	scale: 1;
}

html.zain-motion [data-zm="hero"].is-in::after {
	opacity: 1;
	translate: 0 0;
}

@media (max-width: 1199px) {
	/* Mobile arrows run top → bottom */
	html.zain-motion [data-zm="draw"]::before,
	html.zain-motion [data-zm="draw"]::after {
		clip-path: inset(0 0 100% 0);
	}
}

/* ------------------------------------------------------------------ Interaction (all visitors; reduced motion
   is shortened to nothing by base.css) */

/* Cards lift a little under the pointer */
@media (hover: hover) {
	.zain-service,
	.zain-qual,
	.zain-focus__card {
		transition: transform var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--ease);
	}

	.zain-service:hover,
	.zain-qual:hover,
	.zain-focus__card:hover {
		transform: translateY(-6px);
	}
}

/* FAQ answers slide open (browsers without ::details-content just open) */
:root {
	interpolate-size: allow-keywords;
}

/* flow-root keeps the answer's top margin inside the panel: without it the margin escaped and vanished in one frame
   at the end of the close, so the rows below jumped 16px */
html.zain-motion .zain-faq::details-content {
	display: flow-root;
	block-size: 0;
	overflow: clip;
	transition:
		block-size var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--ease),
		content-visibility var(--wp--custom--motion--duration-fast) allow-discrete;
}

html.zain-motion .zain-faq[open]::details-content {
	block-size: auto;
}

html.zain-motion .zain-faq summary::before {
	transition: background-color 0.2s, rotate var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--ease);
}

html.zain-motion .zain-faq[open] summary::before {
	rotate: 180deg;
}

/* Booking calendar: the month fades in when the arrows change it */
html.zain-motion .zain-booking__month:not([hidden]) {
	animation: zain-month-in var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--ease);
}

@keyframes zain-month-in {
	from {
		opacity: 0;
		translate: 0 8px;
	}
}

/* Mobile menu slides down as it opens */
html.zain-motion .zain-menu__dialog[open] {
	transition:
		opacity var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--ease),
		translate var(--wp--custom--motion--duration-fast) var(--wp--custom--motion--ease);
}

@starting-style {
	html.zain-motion .zain-menu__dialog[open] {
		opacity: 0;
		translate: 0 -16px;
	}
}

/* Page to page: content cross-fades, the header stays put (cross-document view transitions) */
@media (prefers-reduced-motion: no-preference) {
	@view-transition {
		navigation: auto;
	}

	.zain-header {
		view-transition-name: zain-header;
	}
}
