/**
 * Zezuru Elements — page transitions, loading indicators, reading
 * progress and button polish (Zezel_Transitions).
 *
 * Loaded site-wide only while one of those features is switched on in
 * Settings. Each feature is keyed by a data attribute on <html>, printed
 * by WordPress itself (language_attributes), so the right rules apply
 * from the first frame.
 *
 * @package Zezuru_Elements
 * @since   3.0.0
 */

:root {
	--zezel-pt-dur: 350ms;
	--zezel-pt-ease: cubic-bezier(.16, 1, .3, 1);
	--zezel-ui-c: var(--wp--preset--color--primary, #6c5ce7);
	--zezel-ui-top: var(--wp-admin--admin-bar--height, 0px);
}

/* =====================================================================
 * Page transitions — cross-document View Transitions
 * ===================================================================== */
@view-transition { navigation: auto; }

:root[data-zezel-pt]::view-transition-old(root),
:root[data-zezel-pt]::view-transition-new(root) {
	animation-duration: var(--zezel-pt-dur);
	animation-timing-function: var(--zezel-pt-ease);
}

/* Slide: forward goes left, back (history) goes right. */
:root[data-zezel-pt="slide"]::view-transition-old(root) { animation-name: zezel-pt-out-start; }
:root[data-zezel-pt="slide"]::view-transition-new(root) { animation-name: zezel-pt-in-end; }
:root[data-zezel-pt="slide"]:active-view-transition-type(zezel-back)::view-transition-old(root) { animation-name: zezel-pt-out-end; }
:root[data-zezel-pt="slide"]:active-view-transition-type(zezel-back)::view-transition-new(root) { animation-name: zezel-pt-in-start; }

/* Lift: the new page rises gently into place. */
:root[data-zezel-pt="lift"]::view-transition-old(root) { animation-name: zezel-pt-sink; }
:root[data-zezel-pt="lift"]::view-transition-new(root) { animation-name: zezel-pt-rise; }

/* Zoom: the old page drifts towards you, the new one settles. */
:root[data-zezel-pt="zoom"]::view-transition-old(root) { animation-name: zezel-pt-zoom-out; }
:root[data-zezel-pt="zoom"]::view-transition-new(root) { animation-name: zezel-pt-zoom-in; }

/* Morph: the clicked card's picture and title become the next page's. */
::view-transition-group(zezel-media),
::view-transition-group(zezel-title) {
	animation-duration: calc(var(--zezel-pt-dur) * 1.5);
	animation-timing-function: var(--zezel-pt-ease);
}
::view-transition-old(zezel-media),
::view-transition-new(zezel-media) {
	width: 100%;
	height: 100%;
	object-fit: cover;
	overflow: clip;
}
::view-transition-old(zezel-title),
::view-transition-new(zezel-title) {
	width: auto;
	height: 100%;
	object-fit: none;
	object-position: left top;
}
/* The header stays put. */
::view-transition-group(zezel-header) { z-index: 50; animation-duration: 0s; }
::view-transition-old(zezel-header) { display: none; }
::view-transition-new(zezel-header) { animation: none; }

@keyframes zezel-pt-out-start { to   { opacity: 0; translate: -48px 0; } }
@keyframes zezel-pt-in-end    { from { opacity: 0; translate: 48px 0; } }
@keyframes zezel-pt-out-end   { to   { opacity: 0; translate: 48px 0; } }
@keyframes zezel-pt-in-start  { from { opacity: 0; translate: -48px 0; } }
@keyframes zezel-pt-sink      { to   { opacity: 0; scale: .985; } }
@keyframes zezel-pt-rise      { from { opacity: 0; translate: 0 28px; } }
@keyframes zezel-pt-zoom-out  { to   { opacity: 0; scale: 1.035; } }
@keyframes zezel-pt-zoom-in   { from { opacity: 0; scale: .97; } }

/* Browsers without cross-document transitions: ui.js fades the page out
 * after a link is clicked, then navigates. */
:root[data-zezel-pt] body { transition: opacity calc(var(--zezel-pt-dur) * .8) var(--zezel-pt-ease), translate calc(var(--zezel-pt-dur) * .8) var(--zezel-pt-ease), scale calc(var(--zezel-pt-dur) * .8) var(--zezel-pt-ease); }
:root.zezel-leaving body { opacity: 0; }
:root.zezel-leaving[data-zezel-pt="slide"] body { translate: -32px 0; }
:root.zezel-leaving[data-zezel-pt="lift"] body { scale: .99; }
:root.zezel-leaving[data-zezel-pt="zoom"] body { scale: 1.02; }

/* =====================================================================
 * Loading indicator
 *
 * Drawn with pseudo-elements on <html>, so it exists from the first frame
 * without extra markup. It never covers content.
 * ===================================================================== */

/* Bar: grows while the page loads; completes when ui.js sees `load`. */
:root[data-zezel-loader="bar"]::before {
	content: "";
	position: fixed;
	z-index: 100000;
	top: var(--zezel-ui-top);
	left: 0;
	width: 100%;
	height: 3px;
	background: linear-gradient(90deg, color-mix(in srgb, var(--zezel-ui-c) 55%, transparent), var(--zezel-ui-c));
	box-shadow: 0 0 10px color-mix(in srgb, var(--zezel-ui-c) 60%, transparent);
	transform-origin: 0 50%;
	pointer-events: none;
	scale: 0 1;
	/* Without JavaScript it still fades away on its own after a few seconds. */
	animation: zezel-bar-grow 1.8s cubic-bezier(.1, .7, .3, 1) forwards, zezel-bar-hide .3s 6s forwards;
}
[dir="rtl"]:root[data-zezel-loader="bar"]::before { transform-origin: 100% 50%; }
:root[data-zezel-loader="bar"].zezel-pageready::before { animation: zezel-bar-done .45s cubic-bezier(.16, 1, .3, 1) forwards; }
:root[data-zezel-loader="bar"].zezel-navigating::before { animation: zezel-bar-nav 6s cubic-bezier(.08, .7, .2, 1) forwards; }

@keyframes zezel-bar-grow { from { scale: 0 1; opacity: 1; } to { scale: .72 1; opacity: 1; } }
@keyframes zezel-bar-hide { to { opacity: 0; } }
@keyframes zezel-bar-done { from { scale: .72 1; opacity: 1; } 60% { scale: 1 1; opacity: 1; } to { scale: 1 1; opacity: 0; } }
@keyframes zezel-bar-nav { 0% { scale: 0 1; opacity: 1; } 15% { scale: .45 1; } 100% { scale: .92 1; opacity: 1; } }

/* Spinner: a small ring in the corner, only when loading takes a while. */
:root[data-zezel-loader="spinner"]::after {
	content: "";
	position: fixed;
	z-index: 100000;
	top: calc(var(--zezel-ui-top) + 14px);
	inset-inline-end: 14px;
	width: 22px;
	height: 22px;
	border-radius: 50%;
	border: 2.5px solid color-mix(in srgb, var(--zezel-ui-c) 22%, transparent);
	border-top-color: var(--zezel-ui-c);
	box-shadow: 0 4px 14px -4px rgba(15, 16, 32, .25);
	background: color-mix(in srgb, Canvas 80%, transparent);
	pointer-events: none;
	opacity: 0;
	/* Appears after 400 ms, so fast pages never show it. */
	animation: zezel-spin .7s linear infinite, zezel-spin-show .2s .4s forwards, zezel-bar-hide .2s 8s forwards;
}
:root[data-zezel-loader="spinner"].zezel-pageready::after { animation: zezel-spin .7s linear infinite; opacity: 0; transition: opacity .2s ease; }
:root[data-zezel-loader="spinner"].zezel-navigating::after { animation: zezel-spin .7s linear infinite, zezel-spin-show .2s .25s forwards; }

@keyframes zezel-spin { to { rotate: 360deg; } }
@keyframes zezel-spin-show { to { opacity: 1; } }

/* =====================================================================
 * Reading progress
 * ===================================================================== */
.zezel-readbar {
	position: fixed;
	z-index: 99999;
	top: var(--zezel-ui-top);
	left: 0;
	right: 0;
	height: 3px;
	pointer-events: none;
	background: color-mix(in srgb, var(--zezel-ui-c) 12%, transparent);
}
.zezel-readbar__fill {
	display: block;
	height: 100%;
	background: var(--zezel-ui-c);
	transform-origin: 0 50%;
	scale: var(--zezel-read, 0) 1;
}
[dir="rtl"] .zezel-readbar__fill { transform-origin: 100% 50%; }
@supports (animation-timeline: scroll()) {
	.zezel-readbar__fill {
		animation: zezel-read linear both;
		animation-timeline: scroll(root block);
	}
}
@keyframes zezel-read { from { scale: 0 1; } to { scale: 1 1; } }

/* =====================================================================
 * Button polish (theme buttons everywhere). Wrapped in :where() so a
 * block's own micro-interaction (Motion panel) always wins.
 * ===================================================================== */
:root[data-zezel-polish] :where(.wp-element-button, .wp-block-button__link, .wp-block-search__button, input[type="submit"], button[type="submit"]) {
	transition: background-color .2s ease, color .2s ease, border-color .2s ease, box-shadow .25s cubic-bezier(.16, 1, .3, 1), translate .25s cubic-bezier(.16, 1, .3, 1), scale .15s cubic-bezier(.16, 1, .3, 1), filter .2s ease;
}
:root[data-zezel-polish] :where(.wp-element-button, .wp-block-button__link, .wp-block-search__button, input[type="submit"], button[type="submit"]):hover {
	translate: 0 -1px;
	filter: brightness(1.06);
	box-shadow: 0 10px 22px -12px color-mix(in srgb, var(--zezel-ui-c) 70%, transparent);
}
:root[data-zezel-polish] :where(.wp-element-button, .wp-block-button__link, .wp-block-search__button, input[type="submit"], button[type="submit"]):active {
	translate: 0 0;
	scale: .97;
	box-shadow: none;
}
:root[data-zezel-polish] :where(.wp-element-button, .wp-block-button__link, .wp-block-search__button, input[type="submit"], button[type="submit"]):focus-visible {
	outline: 2px solid var(--zezel-ui-c);
	outline-offset: 3px;
}

/* =====================================================================
 * Reduced motion: no transitions, no movement — loading feedback stays.
 * ===================================================================== */
@media (prefers-reduced-motion: reduce) {
	@view-transition { navigation: none; }
	:root[data-zezel-pt] body { transition: none !important; }
	:root.zezel-leaving body { opacity: 1; translate: none; scale: none; }
	:root[data-zezel-loader="spinner"]::after { animation-duration: 1.6s; }
	:root[data-zezel-polish] :where(.wp-element-button, .wp-block-button__link, .wp-block-search__button, input[type="submit"], button[type="submit"]) { translate: none !important; scale: none !important; }
}

@media print {
	:root[data-zezel-loader]::before,
	:root[data-zezel-loader]::after,
	.zezel-readbar { display: none !important; }
}
