/**
 * LTC Motion — centralized entrance-reveal, stagger and image-reveal
 * primitives for the homepage motion pass. Paired with assets/js/
 * ltc-motion.js (a single IntersectionObserver, one-shot per element).
 *
 * Progressive enhancement, not a requirement: every hidden state in
 * this file is scoped under `.js` (see header.php's inline no-js ->
 * js swap, which runs before first paint) so if JavaScript fails to
 * load or run, `.no-js` stays on <html>, none of these rules apply,
 * and every element is simply visible in its normal document flow —
 * the page never depends on this file or its script to show content.
 *
 * Stagger timing is pure CSS: templates set an inline
 * `style="--ltc-stagger-index: N"` on each item in a staggered group
 * (N = 0, 1, 2…), and transition-delay reads that custom property
 * multiplied by --ltc-stagger-interval (ltc-tokens.css). No JS is
 * needed to compute per-item delays.
 *
 * @package LTC_Child
 */

/* =========================================================
   Base reveal — fade + rise. The general-purpose entrance used for
   headings, copy, fact cells, and any staggered group.
   ========================================================= */

.js .ltc-reveal {
	opacity: 0;
	transform: translateY(var(--ltc-reveal-distance));
	transition: opacity var(--ltc-duration) var(--ltc-ease),
		transform var(--ltc-duration) var(--ltc-ease);
	transition-delay: calc(var(--ltc-stagger-index, 0) * var(--ltc-stagger-interval));
}

.js .ltc-reveal.is-inview {
	opacity: 1;
	transform: translateY(0);
}

/* Dense grids (Problem Navigation cards, Capability Explorer cards) —
   tightened duration/stagger so a fully-visible row group settles
   within ~600-750ms instead of the general-purpose pace above, which
   read as prolonged during ordinary/fast scrolling. Same fade+rise
   look and the same is-inview trigger, only the timing changes. */
.js .ltc-reveal.ltc-reveal--dense {
	transition-duration: var(--ltc-duration-dense);
	transition-delay: calc(var(--ltc-stagger-index, 0) * var(--ltc-stagger-interval-dense));
}

/* =========================================================
   Hero — pure-CSS, JS-independent entrance. Unlike every other
   section, the hero's reveal must never depend on ltc-motion.js
   having loaded/parsed/executed and its IntersectionObserver having
   fired: on a throttled device, the gap between first paint and that
   observer callback firing left the hero heading measurably invisible
   (verified: ~745ms under 6x CPU throttling) even though the hero is
   always above the fold. These two classes use a native CSS @keyframes
   animation instead of a JS-toggled class, so the browser's style/
   animation engine drives the reveal on its own schedule regardless of
   main-thread JS timing — content becomes visible on a fixed schedule
   tied only to CSS parsing, never to script execution. Not scoped
   under `.js`: the animation plays (and safely finishes at full
   opacity via `both` fill-mode) even with JavaScript entirely
   disabled, so there is no no-js fallback to maintain separately.
   Same visual language (duration/ease/distance/scale tokens) as the
   rest of the site's reveal system — only the trigger mechanism
   differs, not the look. */

@keyframes ltc-hero-fade-rise {
	from {
		opacity: 0;
		transform: translateY(var(--ltc-reveal-distance));
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@keyframes ltc-hero-image-reveal {
	from {
		opacity: 0;
		transform: scale(var(--ltc-image-reveal-scale));
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

.ltc-hero-reveal {
	animation: ltc-hero-fade-rise var(--ltc-duration) var(--ltc-ease) both;
	animation-delay: calc(var(--ltc-stagger-index, 0) * var(--ltc-stagger-interval));
}

.ltc-hero-image-reveal {
	animation: ltc-hero-image-reveal var(--ltc-duration-image) var(--ltc-ease) both;
}

@media (prefers-reduced-motion: reduce) {
	.ltc-hero-reveal,
	.ltc-hero-image-reveal {
		animation: none;
		opacity: 1;
		transform: none;
	}
}

/* =========================================================
   Image reveal — gentle scale-and-opacity for the positioning
   illustration (the hero photo uses the pure-CSS .ltc-hero-image-
   reveal above instead, for the JS-independence reasons noted there).
   Deliberately not a mask/clip wipe (the motion PLAN considered a
   clip-path wipe; in implementation a scale-from-1.03 + opacity reveal
   reads just as controlled, is cheaper — transform + opacity only, no
   layout/paint cost from an animated clip-path).
   ========================================================= */

.js .ltc-reveal-image {
	opacity: 0;
	transform: scale(var(--ltc-image-reveal-scale));
	transition: opacity var(--ltc-duration-image) var(--ltc-ease),
		transform var(--ltc-duration-image) var(--ltc-ease);
}

.js .ltc-reveal-image.is-inview {
	opacity: 1;
	transform: scale(1);
}

/* Facilitator photo — a distinct entrance from the hero's scale reveal
   (same "large image reveal" duration category, deliberately different
   motion: a soft edge wipe rather than a zoom) so the two photographs
   on the page do not feel like a repeated effect. */
.js .ltc-reveal-mask {
	opacity: 0;
	clip-path: inset(0 0 0 14%);
	transition: opacity var(--ltc-duration-image) var(--ltc-ease),
		clip-path var(--ltc-duration-image) var(--ltc-ease);
}

.js .ltc-reveal-mask.is-inview {
	opacity: 1;
	clip-path: inset(0 0 0 0%);
}

/* =========================================================
   Momentum Line graphic device (Gate 0 legacy component) — moved here
   from ltc-components.css so every entrance-reveal rule lives in one
   file. Behaviour unchanged: without JS the path renders fully drawn.
   ========================================================= */

.ltc-momentum-line {
	display: block;
	overflow: visible;
}

.ltc-momentum-line path {
	fill: none;
	stroke: var(--ltc-teal-500);
	stroke-width: 2;
	stroke-linecap: round;
}

.js .ltc-momentum-line--animate path {
	stroke-dasharray: 400;
	stroke-dashoffset: 400;
	transition: stroke-dashoffset 1200ms var(--ltc-ease);
}

.js .ltc-momentum-line--animate.is-inview path {
	stroke-dashoffset: 0;
}

/* =========================================================
   Methodology — sequential narrative animation. A dedicated system,
   not the generic .ltc-reveal: stages activate one at a time, each
   connector "draws" via stroke-dashoffset as it hands off to the next
   stage, and the loop-back capsule appears only once stage 5 has
   finished. Driven by ltc-motion.js adding .is-active to one stage/
   connector at a time in sequence, plus a final .ltc-cycle--complete
   class on the container that reveals the capsule.
   ========================================================= */

.js .ltc-cycle__node {
	opacity: 0;
	transform: translateY(10px) scale(0.94);
	transition: opacity var(--ltc-duration-standard) var(--ltc-ease),
		transform var(--ltc-duration-standard) var(--ltc-ease);
}

.js .ltc-cycle__node.is-active {
	opacity: 1;
	transform: translateY(0) scale(1);
}

.js .ltc-cycle__connector svg path {
	stroke-dasharray: 40;
	stroke-dashoffset: 40;
	transition: stroke-dashoffset var(--ltc-duration-standard) var(--ltc-ease);
}

.js .ltc-cycle__connector.is-active svg path {
	stroke-dashoffset: 0;
}

.js .ltc-cycle__return {
	opacity: 0;
	transform: translateY(8px);
	transition: opacity var(--ltc-duration-standard) var(--ltc-ease),
		transform var(--ltc-duration-standard) var(--ltc-ease);
}

.js .ltc-cycle.ltc-cycle--complete .ltc-cycle__return {
	opacity: 1;
	transform: translateY(0);
}

/* One restrained motion on the return arrow once the capsule appears
   — a single partial rotation, not a spin, not a loop. */
.js .ltc-cycle__return-arrow {
	transform: rotate(-35deg);
	transition: transform var(--ltc-duration-standard) var(--ltc-ease);
}

.js .ltc-cycle.ltc-cycle--complete .ltc-cycle__return-arrow {
	transform: rotate(0deg);
}

/* Mobile vertical sequence — same reveal primitive as everything else,
   in DOM order via --ltc-stagger-index set per <li>. */
.js .ltc-cycle-mobile__item,
.js .ltc-cycle-mobile__return {
	opacity: 0;
	transform: translateY(var(--ltc-reveal-distance));
	transition: opacity var(--ltc-duration-standard) var(--ltc-ease),
		transform var(--ltc-duration-standard) var(--ltc-ease);
	transition-delay: calc(var(--ltc-stagger-index, 0) * var(--ltc-stagger-interval));
}

.js .ltc-cycle-mobile__item.is-inview,
.js .ltc-cycle-mobile__return.is-inview {
	opacity: 1;
	transform: translateY(0);
}

/* =========================================================
   Capability-page motion — reuses every primitive above (.ltc-reveal,
   .ltc-reveal--dense, .ltc-hero-reveal, .ltc-hero-image-reveal) via the
   same shared IntersectionObserver in ltc-motion.js. Only two things
   are genuinely new here: a slightly stronger reveal for the dark
   feature sections (business benefits, custom-intervention), so the
   rhythm change reads as intentional, and a restrained active-state
   for the in-page section nav. Scoped to the capability "deep content"
   template only — no other template references these classes/ids.
   ========================================================= */

.js .ltc-reveal--dark {
	transform: translateY(calc(var(--ltc-reveal-distance) * 1.5));
	transition-duration: calc(var(--ltc-duration) * 1.15);
}

.js .ltc-reveal--dark.is-inview {
	transform: translateY(0);
}

/* Benefit-band cards carry a permanent static zigzag Y-offset
   (--ltc-zigzag-y, set in ltc-programmes.css) independent of reveal
   state. The generic .ltc-reveal transform must be composed with that
   offset rather than replacing it, or every staggered card would snap
   back to a flat row the moment its entrance animation finished. */
.js .ltc-benefit-band__card.ltc-reveal {
	transform: translateY(calc(var(--ltc-zigzag-y, 0px) + var(--ltc-reveal-distance)));
}

.js .ltc-benefit-band__card.ltc-reveal.is-inview {
	transform: translateY(var(--ltc-zigzag-y, 0px));
}

.ltc-inpage-nav a.is-active {
	color: var(--ltc-teal-700);
	text-decoration: underline;
	text-underline-offset: 4px;
}

/* =========================================================
   Reduced motion — every entrance/sequential effect above resolves to
   its finished state immediately. No opacity: 0 may survive this
   query under any circumstance.
   ========================================================= */

@media (prefers-reduced-motion: reduce) {
	.js .ltc-reveal,
	.js .ltc-reveal-image,
	.js .ltc-reveal-mask,
	.js .ltc-reveal--dark,
	.js .ltc-cycle__node,
	.js .ltc-cycle__return,
	.js .ltc-cycle-mobile__item,
	.js .ltc-cycle-mobile__return {
		opacity: 1;
		transform: none;
		clip-path: none;
		transition: none;
	}

	.js .ltc-momentum-line--animate path,
	.js .ltc-cycle__connector svg path {
		stroke-dashoffset: 0;
		transition: none;
	}

	.js .ltc-cycle__return-arrow {
		transform: none;
		transition: none;
	}
}
