/**
 * PPB Core — shared interaction tokens and utility classes.
 * All transitions, easing, and motion patterns live here.
 *
 * Usage: reference these variables in component CSS.
 * Do NOT hardcode transition durations or easing elsewhere.
 */

:root {
	/* Durations */
	--ppb-duration-fast: 150ms;
	--ppb-duration-base: 250ms;
	--ppb-duration-slow: 400ms;
	--ppb-duration-xslow: 600ms;

	/* Easing */
	--ppb-ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94);
	--ppb-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
	--ppb-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

	/* Compound shorthands (duration + easing) */
	--ppb-transition-fast: var(--ppb-duration-fast) var(--ppb-ease-out);
	--ppb-transition-base: var(--ppb-duration-base) var(--ppb-ease-out);
	--ppb-transition-slow: var(--ppb-duration-slow) var(--ppb-ease-out);
	--ppb-transition-xslow: var(--ppb-duration-xslow) var(--ppb-ease-in-out);
}

/* Reduced motion: honour the OS preference globally */
@media (prefers-reduced-motion: reduce) {
	:root {
		--ppb-duration-fast: 0ms;
		--ppb-duration-base: 0ms;
		--ppb-duration-slow: 0ms;
		--ppb-duration-xslow: 0ms;
	}
}

/* ------------------------------------------------------------------
   Section reveal
   Subtle fade + rise when an element enters the viewport.
   - No-JS safe: without the ppb-js-reveal class (added by reveal.js),
     elements are visible in their final state.
   - Runs once per element; the JS unobserves after firing.
   - Respects prefers-reduced-motion.

   Header load reveal (`data-ppb-reveal-load`): same motion; fired once after
   load (see reveal.js), not on scroll — used for page-header copy block.
   ------------------------------------------------------------------ */

.ppb-js-reveal [data-ppb-reveal],
.ppb-js-reveal [data-ppb-reveal-load] {
	opacity: 0;
	transform: translateY(16px);
	transition:
		opacity var(--ppb-transition-base),
		transform var(--ppb-transition-base);
}

.ppb-js-reveal [data-ppb-reveal].ppb-reveal--in,
.ppb-js-reveal [data-ppb-reveal-load].ppb-reveal--in {
	opacity: 1;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.ppb-js-reveal [data-ppb-reveal],
	.ppb-js-reveal [data-ppb-reveal].ppb-reveal--in,
	.ppb-js-reveal [data-ppb-reveal-load],
	.ppb-js-reveal [data-ppb-reveal-load].ppb-reveal--in {
		opacity: 1;
		transform: none;
		transition: none;
	}
}

/* ------------------------------------------------------------------
   Unified :focus-visible
   One treatment across interactive elements. Uses primary accent for visibility;
   2px offset so it does not crowd the element. `:where()` keeps specificity at 0
   so component-specific focus rules still win.
   ------------------------------------------------------------------ */

:where(
	a,
	button,
	[role="button"],
	input,
	select,
	textarea,
	summary,
	[tabindex]:not([tabindex="-1"])
):focus-visible {
	outline: 2px solid var(--color-primary);
	outline-offset: 2px;
	border-radius: var(--ppb-radius-sm, 0.25rem);
}

:focus:not(:focus-visible) {
	outline: none;
}
