/* ============================================================
   Motion — entrance, scroll reveal, stagger, hover.

   One shared module for every front-end view that has motion: the
   front page, pages, the vehicle archive and single vehicles (see
   inc/assets.php). Rules for a view that is not the current one
   simply do not match, so there is nothing to gate per template.

   Animates opacity and transform only, so nothing here triggers
   layout or reflow, and every effect is disabled under
   prefers-reduced-motion.

   Two techniques, each used where it is safe:

   1. Above the fold: a pure-CSS entrance that plays on load. No
      JavaScript, so it can never be left half-applied, and the
      initial hidden state lives in this head-loaded sheet, present
      before first paint — so there is no flash of the final state.

   2. Below the fold: revealed as sections scroll into view. The
      hidden state (.crd-reveal) is added by motion.js, and only to
      elements that start off-screen. If that script never runs,
      nothing is hidden and all content stays visible.

   Two rules when extending this:

   - Whichever element holds the LCP image animates with transform
     only, never opacity, because fading it in delays LCP. That is
     the homepage hero media, the page-hero backdrop, the vehicle
     gallery, and the catalogue's results column (its first card
     image is the largest thing on that page).

   - An element gets one technique or the other, never both. A load
     animation with `both` fill keeps its final opacity applied for
     good, which would out-rank the .crd-reveal hidden state and
     leave the reveal dead.

   Contents
     1. Tokens and keyframes
     2. Homepage hero
     3. Page hero (inner pages)
     4. Vehicle catalogue header
     5. Single vehicle header
     6. Scroll reveal and stagger
     7. Hover touches
     8. Motion off
   ============================================================ */

/* ============================================================
   1. Tokens and keyframes
   ============================================================ */

:root {
	--crd-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

@keyframes crd-rise {
	from { opacity: 0; transform: translateY(16px); }
	to   { opacity: 1; transform: none; }
}

/* The same move without the fade, for a block holding the LCP image. */
@keyframes crd-rise-opaque {
	from { transform: translateY(16px); }
	to   { transform: none; }
}

/* Hero media: transform only, for the same reason. A gentle settle with a
   touch of scale does not delay LCP. */
@keyframes crd-media-in {
	from { transform: translateY(18px) scale(1.015); }
	to   { transform: none; }
}

/* A full-bleed backdrop scales in from slightly oversized rather than
   translating, which would expose the edge it is meant to cover. Its hero
   clips (`overflow: hidden` on .crd-page-hero--image), so the extra width
   costs no horizontal scroll. */
@keyframes crd-bg-settle {
	from { transform: scale(1.045); }
	to   { transform: none; }
}

/* ============================================================
   2. Homepage hero (CSS only, plays on load)
   ============================================================ */

.crd-home-hero__copy > * {
	animation: crd-rise 0.6s var(--crd-ease) both;
}
.crd-home-hero__copy > *:nth-child(1) { animation-delay: 0.05s; }
.crd-home-hero__copy > *:nth-child(2) { animation-delay: 0.12s; }
.crd-home-hero__copy > *:nth-child(3) { animation-delay: 0.19s; }
.crd-home-hero__copy > *:nth-child(4) { animation-delay: 0.26s; }
.crd-home-hero__copy > *:nth-child(5) { animation-delay: 0.33s; }

.crd-home-hero__media {
	animation: crd-media-in 0.7s var(--crd-ease) 0.05s both;
}

/* The availability request sits after the hero grid; bring it in last. */
.crd-home-hero > .crd-home-hero__grid ~ * {
	animation: crd-rise 0.6s var(--crd-ease) 0.4s both;
}

/* ============================================================
   3. Page hero (inner pages)

   The hero copy is a fixed set of elements rather than one container's
   children (see template-parts/sections/page-hero.php), so each is named and
   given its own delay instead of being counted with :nth-child.
   ============================================================ */

.crd-page-hero .crd-breadcrumbs,
.crd-page-hero__title,
.crd-page-hero__lead,
.crd-page-hero__aside,
.crd-page-hero__actions,
.crd-page-hero__note {
	animation: crd-rise 0.6s var(--crd-ease) both;
}
.crd-page-hero .crd-breadcrumbs { animation-delay: 0.04s; }
.crd-page-hero__title           { animation-delay: 0.1s; }
.crd-page-hero__lead            { animation-delay: 0.18s; }
.crd-page-hero__aside           { animation-delay: 0.26s; }
.crd-page-hero__actions         { animation-delay: 0.26s; }
.crd-page-hero__note            { animation-delay: 0.33s; }

/* The darkened backdrop is this hero's LCP image: transform only. */
.crd-page-hero__bg {
	animation: crd-bg-settle 0.9s var(--crd-ease) both;
}

/* ============================================================
   4. Vehicle catalogue header

   The catalogue's own header, filter rail and results column are all in the
   first screen, so they animate on load. The cards inside the results column
   are left alone here — motion.js reveals the ones that start off-screen.
   ============================================================ */

.crd-page-header > * {
	animation: crd-rise 0.6s var(--crd-ease) both;
}
.crd-page-header > *:nth-child(1) { animation-delay: 0.05s; }
.crd-page-header > *:nth-child(2) { animation-delay: 0.12s; }
.crd-page-header > *:nth-child(3) { animation-delay: 0.19s; }

.crd-catalogue__filters {
	animation: crd-rise 0.6s var(--crd-ease) 0.16s both;
}

/* Opaque: the first vehicle image is the largest element on the catalogue,
   so this column must not fade. */
.crd-catalogue__results {
	animation: crd-rise-opaque 0.7s var(--crd-ease) 0.16s both;
}

/* ============================================================
   5. Single vehicle header
   ============================================================ */

/* The gallery holds the vehicle's LCP image: transform only. */
.crd-vehicle__media {
	animation: crd-media-in 0.7s var(--crd-ease) 0.05s both;
}

/* The column beside it — title, price, specs, request form — cascades the way
   the homepage hero copy does. */
.crd-vehicle__summary > * {
	animation: crd-rise 0.6s var(--crd-ease) both;
}
.crd-vehicle__summary > *:nth-child(1) { animation-delay: 0.08s; }
.crd-vehicle__summary > *:nth-child(2) { animation-delay: 0.15s; }
.crd-vehicle__summary > *:nth-child(3) { animation-delay: 0.22s; }
.crd-vehicle__summary > *:nth-child(4) { animation-delay: 0.29s; }
.crd-vehicle__summary > *:nth-child(5) { animation-delay: 0.36s; }

/* ============================================================
   6. Scroll reveal and stagger (hidden state added by motion.js)

   This sheet is enqueued last (see inc/assets.php) so the transition below
   wins the tie against a component's own: .crd-vehicle-card, for one,
   transitions transform at the 180ms hover speed and does not list opacity
   at all, which would turn the reveal into a hard pop.

   motion.js removes both classes once the entrance has finished, so none of
   this lingers on the element to fight the hover states it ships with.
   ============================================================ */

.crd-reveal {
	opacity: 0;
	transform: translateY(22px);
	transition: opacity 0.6s var(--crd-ease), transform 0.6s var(--crd-ease);
}
.crd-reveal:not(.is-revealed) {
	will-change: opacity, transform;
}
.crd-reveal.is-revealed {
	opacity: 1;
	transform: none;
}

/* Stagger: siblings that enter together cascade instead of snapping in as one
   block. The delay is on the transition, so it only costs time on the way in
   and reverses to nothing once revealed.

   The 3n step follows the three columns these grids are built on, so a long
   grid (a full catalogue page) staggers every row rather than only the first. */
.crd-cards .crd-reveal:nth-child(3n + 2),
.crd-stats .crd-reveal:nth-child(3n + 2),
.crd-vehicle-grid .crd-reveal:nth-child(3n + 2) { transition-delay: 0.08s; }
.crd-cards .crd-reveal:nth-child(3n + 3),
.crd-stats .crd-reveal:nth-child(3n + 3),
.crd-vehicle-grid .crd-reveal:nth-child(3n + 3) { transition-delay: 0.16s; }

/* Steps stack vertically, so their cascade follows reading order instead. */
.crd-steps .crd-reveal:nth-child(2) { transition-delay: 0.09s; }
.crd-steps .crd-reveal:nth-child(3) { transition-delay: 0.18s; }
.crd-steps .crd-reveal:nth-child(4) { transition-delay: 0.27s; }
.crd-steps .crd-reveal:nth-child(5) { transition-delay: 0.36s; }

/* ============================================================
   7. Small hover interactions

   Only where the component has none of its own. The benefit card, step body,
   review card and vehicle card already lift in main.css / vehicles.css, and
   every Gutenberg button already lifts; those are left as they are.
   ============================================================ */

/* Those two cards lift already — nudge the icon inside them as well. */
.crd-benefit-card .crd-icon-tile,
.crd-step__body .crd-icon-tile {
	transition: transform 0.25s var(--crd-ease);
}
.crd-benefit-card:hover .crd-icon-tile,
.crd-step__body:hover .crd-icon-tile {
	transform: translateY(-3px) scale(1.06);
}

/* The location card is the one card in the set with no hover state of its
   own, and it sits in the same grid as the benefit card on About and
   Contact. Same restraint, no shadow: its tinted panel does not carry one. */
.crd-location-card {
	transition: transform 0.25s var(--crd-ease);
}
.crd-location-card:hover {
	transform: translateY(-4px);
}

/* Hero trust points respond gently to the pointer. */
.crd-points > * {
	transition: transform 0.25s var(--crd-ease);
}
.crd-points > *:hover {
	transform: translateY(-2px);
}

/* A subtle lift on the primary hero and closing-CTA buttons. The base
   transform transition already exists in main.css. */
.crd-home-hero__actions .wp-block-button__link:hover,
.crd-cta__actions .wp-block-button__link:hover {
	transform: translateY(-2px);
}

/* ============================================================
   8. Motion off

   main.css already collapses every duration site-wide under this query. These
   guards are kept explicit so this sheet cannot be read as depending on that.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
	.crd-home-hero__copy > *,
	.crd-home-hero__media,
	.crd-home-hero > .crd-home-hero__grid ~ *,
	.crd-page-hero .crd-breadcrumbs,
	.crd-page-hero__title,
	.crd-page-hero__lead,
	.crd-page-hero__aside,
	.crd-page-hero__actions,
	.crd-page-hero__note,
	.crd-page-hero__bg,
	.crd-page-header > *,
	.crd-catalogue__filters,
	.crd-catalogue__results,
	.crd-vehicle__media,
	.crd-vehicle__summary > * {
		animation: none;
	}
	.crd-reveal {
		opacity: 1;
		transform: none;
		transition: none;
	}
	.crd-benefit-card:hover .crd-icon-tile,
	.crd-step__body:hover .crd-icon-tile,
	.crd-location-card:hover,
	.crd-points > *:hover,
	.crd-home-hero__actions .wp-block-button__link:hover,
	.crd-cta__actions .wp-block-button__link:hover {
		transform: none;
	}
}
