/* Parallax — one mechanism for every «Parallax effect» note in the macro.

   Twelve notes on the pages that are already built say the same sentence:
   «зображення рухається повільніше за основний контент під час скролу», with
   the same reference, Locomotive Scroll «02. Parallax effect». Nine of them
   point at layouts this task owns — Головна `4342:19685` (банер), `4343:19688`
   (картки афіші), `4348:19860` (картки акторів); Афіша `4496:35831`;
   Репертуар `4549:26003`; Вистава `4497:25453` (банер), `4497:25439`
   (актори), `4497:25446` («Що кажуть виконавці»), `4497:25450` («Перед
   виставою»). The three on the person page (`4497:25456`, `4497:25465`,
   `4497:25469`) are the same class on person.css's own boxes and belong to
   that task, as does the article banner `4550:25475`, which already carries a
   hand-written copy of this effect in article.css.

   None of the notes gives a distance, a duration or an easing, and none has a
   prototype transition. The article banner already settled the number for this
   project — 80 px of travel over the box's own pass through the viewport,
   `cover 0% → 100%` — so that is the shared default here; a consumer with a
   shorter box overrides `--c-parallax-travel`.

   A CSS scroll-driven animation, not a script: it costs no JavaScript, cannot
   jank behind a `scroll` handler, and a browser without `animation-timeline`
   simply shows the still image, which is the design without the effect.

   No layout shift, ever: the moving layer is absolutely positioned inside a box
   that already has its own size (`aspect-ratio` or a fixed height) and
   `overflow: hidden`, and it is `--c-parallax-travel` taller than that box, so
   the travel can never uncover an edge. Nothing about the box's own geometry
   changes, which is what keeps every recorded spec-diff untouched.

   `translate`, not `transform`: it is a separate property, so a layer that
   already carries a hand-measured crop in `transform` (home.css's
   `.home-hero__photo--theme`) keeps it and composes.

   `:is()` only to raise specificity to 0,2,0 — the consumers' own
   `position/inset/height` rules are single-class, and stylesheet order between
   components is set by the enqueue graph, not by this file. */

.c-parallax {
	--c-parallax-travel: 80px;
}

@supports (animation-timeline: view()) {

	/* The timeline is declared on the BOX, not on the layer, and the layer
	   refers to it by name. `animation-timeline: view()` on the layer itself
	   would resolve against the layer's nearest scrollport — and that is the
	   box, because every one of these boxes clips, which makes it a scroll
	   container. Inside it the layer never moves, so the progress sat at
	   exactly 50 % at every scroll position and nothing travelled. A named view
	   timeline on the box is tracked through the BOX's nearest scrollport
	   instead.

	   Which is the rule a consumer has to honour: **no ancestor of the box may
	   be a scroll container**, or the module silently stops. `overflow: hidden`
	   makes one; `overflow: clip` does not. Two sections were exactly that case
	   (`.performance-testimonials`, `.performance-visit-info`) and their layers
	   stood still at 0.50 and 0.46 until both were turned to `clip` (fix
	   round 1, C2). `catchup-2026-09-22.spec.js` now walks every layer's
	   ancestors and fails on the first scrollable one, so the next consumer
	   finds out from a test rather than from the page. */
	:has(> .c-parallax) {
		view-timeline-name: --c-parallax;

		/* Explicit, because the default `auto` reads the scroller's
		   `scroll-padding` — and site-header.css puts the sticky header's
		   height there, which would make the length of every parallax pass
		   depend on the header. The pass is the box's own crossing of the
		   viewport: viewport + box height, nothing else. */
		view-timeline-inset: 0;
	}

	.c-parallax:is(.c-parallax) {
		position: absolute;
		top: calc(var(--c-parallax-travel) / -2);
		left: 0;
		height: calc(100% + var(--c-parallax-travel));
		animation: c-parallax linear both;
		animation-timeline: --c-parallax;
		animation-range: cover 0% cover 100%;
	}

	@keyframes c-parallax {

		from {
			translate: 0 calc(var(--c-parallax-travel) / -2);
		}

		to {
			translate: 0 calc(var(--c-parallax-travel) / 2);
		}
	}
}

/* Off under both switches (accessibility-ua.md §3.1 and §4 «Зменшити
   анімацію»; the carried ruling of plan 04). The global rules in base.css zero
   transition and animation DURATIONS, which a scroll-driven animation does not
   have — so it is turned off by name, and the layer is put back to exactly the
   box it fills when there is no effect. */
html[data-motion="reduced"] .c-parallax:is(.c-parallax) {
	/* stylelint-disable-next-line declaration-no-important -- reduced motion */
	animation: none !important;
	top: 0;
	height: 100%;
	translate: none;
}

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

	.c-parallax:is(.c-parallax) {
		/* stylelint-disable-next-line declaration-no-important -- reduced motion */
		animation: none !important;
		top: 0;
		height: 100%;
		translate: none;
	}
}
