/* Feature List 002 — scroll-stacked cards.
 *
 * A column of cards that pin to the top of the viewport one after another: each
 * card stops where the one before it stopped, minus a step, so the stack builds a
 * stepped edge of every card underneath. When the last card lands, the whole stack
 * scrolls away together.
 *
 * THE PINNING IS `position: sticky` — NOT JAVASCRIPT. That is the whole structural
 * mechanism, and it is worth being explicit about why:
 *
 *   • It costs nothing. No scroll listener, no measuring, no re-measuring on
 *     resize — the browser does it on the compositor.
 *   • It is correct at every viewport with no breakpoints, because every value it
 *     depends on is a length, not a computed pixel snapshot.
 *   • It is the progressive-enhancement floor. With JavaScript off, GSAP absent,
 *     or `prefers-reduced-motion: reduce`, the stacking STILL WORKS — only the
 *     recede is missing. Nothing about the section's structure depends on a script.
 *
 * pattern.js adds two things, and neither positions anything: the margins that make
 * every card release together (see "Evening out the stack"), and the recede.
 *
 * THE RELEASE IS NATIVE TOO, and it is why nothing here counts the cards or
 * measures the section. A sticky element stops sticking when it would overflow its
 * containing block, so every card releases within a step of the others and the
 * stack leaves as one.
 *
 * THE LAST CARD DOES NOT DWELL, and that is the intended behaviour: it settles at
 * the top and the stack releases in the same moment, so scrolling carries straight
 * on into whatever follows. The section ends at the last card — nothing extra to
 * scroll through before the next section arrives.
 *
 * That falls out of sticky for free: a sticky box is constrained by its containing
 * block's CONTENT box, and the last card is the last flow child, so the content box
 * ends at its bottom edge and there is no room to push it down.
 *
 * ⚠ …WHICH IS ONLY TRUE WHILE THE CARDS ARE THE SAME HEIGHT, and that is the trap.
 * A card stops sticking when the remaining room drops below its OWN height plus its
 * OWN pin, so the card with the largest `height + top` releases FIRST — not the
 * lowest one. Give the middle card a taller photograph and it leaves the stack
 * before the last card has even arrived: measured here with a middle card 102px
 * taller than its neighbours, it had slid 35px past its pin while the last card was
 * still 239px short of its own, ending up ABOVE the first card.
 *
 * And making room for the last card to land is not enough on its own. Once the
 * stack lets go, every card's bottom is held to the section's end, so a card's top
 * sits at `end − its height`: the taller card rises faster than the rest and pokes
 * out above the first card as the stack leaves (measured on O meni: 107px, with a
 * card 107px taller than the others). The stack only leaves as ONE when every card
 * releases at the same moment, which means every card's `height + top` must be the
 * same.
 *
 * pattern.js makes them the same — see "Evening out the stack" below. It is the one
 * part of the layout that is not pure CSS, because the difference is a fact about
 * the rendered cards, and it computes to ZERO whenever the cards are uniform, which
 * is the common case.
 */

.feature-list-002 {
	/* ── Geometry ──────────────────────────────────────────────────────────── */
	/* Where the FIRST card stops, measured from the top of the viewport: the site's
	   gutter, so the stack sits the same distance from the top as page content does
	   from the sides. `--gutter` is a clamp, so it tightens on narrow screens with
	   no breakpoint of its own — about 72px on a desktop, 20px on a phone.

	   ⚠ THIS IS DELIBERATELY LESS THAN THE HEADER'S HEIGHT, and it has a
	   consequence. The pin used to be `--header-height`, precisely so the stack
	   cleared the bar. The bar is sticky and auto-hides, so now whenever it returns
	   on a scroll up it sits ON TOP of the pinned cards — a 129px bar over cards
	   pinned at 72px. That is the same trade the `--no-top-gutter` switch at the
	   bottom of this file warns about, taken deliberately because the design wants
	   the cards high on the screen. If it ever reads as a bug rather than a choice,
	   put the pin back on `--header-height` — do not chase the bar's hidden state,
	   which would jog every card up and down as it toggles. */
	--stack-top: var(--gutter);

	/* How much SOONER each subsequent card stops. This is the visible depth of the
	   stack: at rest you see this much of every card underneath the top one. */
	--stack-step: var(--space-sm);

	/* ── The recede (pattern.js scrubs it; both unitless scale deltas) ─────── */
	/* How much the FIRST card shrinks by, once pinned. */
	--stack-recede: 0.06;

	/* How much LESS each subsequent card shrinks. Floored at zero, so on a deep
	   stack the later cards simply do not recede rather than going inside out:
	   at these values cards 1–4 shrink by 6 / 4.5 / 3 / 1.5% and a fifth onwards
	   sits at full size.

	   Set the falloff to 0 for a uniform recede, or `--stack-recede: 0` to turn
	   the effect off entirely — per instance, or inside a breakpoint. */
	--stack-recede-falloff: 0.015;
}

/*
 * The class is DOUBLED, for the trap this theme already hit in `gallery-grid-001`:
 * Gutenberg puts `.block-editor-block-list__block { position: relative }` on every
 * block in the canvas. That is a single class, so a bare `.feature-list-002__card`
 * would only TIE — and a tie falls to source order, which is REVERSED between the
 * two surfaces (pattern CSS is enqueued after global styles on the front end, but
 * loaded as an editor style before them in the canvas). Left single, the cards pin
 * on the page and lie flat while editing.
 */
.feature-list-002__card.feature-list-002__card {
	--k: 1;

	position: sticky;
	top: calc(var(--stack-top) + (var(--k) - 1) * var(--stack-step));

	/* Later cards already paint over earlier ones — same stacking context, later in
	   the DOM — so this is belt and braces rather than load-bearing. It is here so
	   the order survives a card that introduces its own stacking context. */
	z-index: var(--k);

	/* The recede scales the card. Anchoring the origin to the TOP edge is what makes
	   it read as receding rather than as sliding: once a card is pinned, its top edge
	   is the ONLY part of it still visible — a `--stack-step` sliver above the card
	   covering it — so the growth must never move that edge. Scaling from the centre
	   would drag the sliver down out of sight, which looks like a layout bug. */
	transform-origin: top center;
}


.feature-list-002__text > div {
	padding:var(--space-lg);
}

/*
 * Each card's index — the only per-card value, and the reason the count is free.
 * Add or remove cards and the stack re-steps itself.
 *
 * `of .feature-list-002__card` is load-bearing, and the EDITOR is why. Gutenberg
 * renders a block appender as the last child of a container in the canvas, and a
 * section like this one may well gain a heading above the cards later; a plain
 * `:nth-child(2)` would count either of those as a card and shift every offset by a
 * step. Counting only the cards makes the two surfaces agree and lets the section
 * hold whatever else it needs to.
 *
 * Twelve is the ceiling. A thirteenth card falls back to `--k: 1` and pins with the
 * first rather than breaking the section — and a stack of thirteen is already far
 * more scrolling than the pattern is good for.
 */
.feature-list-002__card:nth-child(1 of .feature-list-002__card) { --k: 1; }
.feature-list-002__card:nth-child(2 of .feature-list-002__card) { --k: 2; }
.feature-list-002__card:nth-child(3 of .feature-list-002__card) { --k: 3; }
.feature-list-002__card:nth-child(4 of .feature-list-002__card) { --k: 4; }
.feature-list-002__card:nth-child(5 of .feature-list-002__card) { --k: 5; }
.feature-list-002__card:nth-child(6 of .feature-list-002__card) { --k: 6; }
.feature-list-002__card:nth-child(7 of .feature-list-002__card) { --k: 7; }
.feature-list-002__card:nth-child(8 of .feature-list-002__card) { --k: 8; }
.feature-list-002__card:nth-child(9 of .feature-list-002__card) { --k: 9; }
.feature-list-002__card:nth-child(10 of .feature-list-002__card) { --k: 10; }
.feature-list-002__card:nth-child(11 of .feature-list-002__card) { --k: 11; }
.feature-list-002__card:nth-child(12 of .feature-list-002__card) { --k: 12; }

/*
 * THE RECEDE — a pinned card keeps responding to scroll.
 *
 * Once a card has pinned it shrinks slightly as you scroll on, reaches a floor, and
 * holds there. The card that lands on top of it does the same, but by less. So a
 * settled stack is graduated — the deepest card smallest, the one you are reading at
 * full size — and it reads as a deck receding into the page rather than as a pile of
 * identical slabs.
 *
 * WHEN IT STOPS is the next card's arrival, not a distance. Each card's shrink is
 * scrubbed across exactly the stretch where the next card travels to its own pin, and
 * freezes the moment that card lands. Two things fall out of that for free: the range
 * is defined in the same terms as the geometry above (a pinning point), so it follows
 * a token change or a breakpoint without an edit; and the LAST card never recedes,
 * because nothing stacks on it.
 *
 * HOW MUCH is derived from `--k`, the index the stack already assigns — so, like
 * everything else here, the card count stays free. Add a card and it takes the next
 * step down on its own.
 *
 * THE AMOUNT IS CSS AND THE PROGRESS IS JS, deliberately. pattern.js knows nothing
 * about the magnitude: it scrubs `--recede-progress` from 0 to 1 and stops. That keeps
 * this stylesheet the one place the effect is tuned, and it is why the two knobs above
 * can be overridden per instance or inside a media query with no JavaScript to match.
 *
 * `max()` rather than a clamp on the whole expression, because the floor is the only
 * bound that matters: a negative budget would scale a card UP, which is the one thing
 * that cannot be a rounding artifact — it inverts the depth order.
 */
.feature-list-002__card {
	--recede: max(
		0,
		var(--stack-recede) - (var(--k) - 1) * var(--stack-recede-falloff)
	);

	/* Declared, not merely defaulted in the `var()` below. GSAP reads the current
	   value to start its tween from, and an undeclared custom property computes to
	   the guaranteed-invalid value — which parses out as NaN and silently kills the
	   tween rather than erroring. */
	--recede-progress: 0;
}

/*
 * GATED ON A CLASS pattern.js adds, mirroring `is-stack-evened` below, and the reason
 * is not tidiness. A `transform` — even `scale(1)` — makes the card a stacking context
 * and a containing block for fixed and absolutely-positioned descendants. Declaring it
 * unconditionally would change how every card's contents resolve on a page whose JS
 * never ran, or whose reader asked for reduced motion, purely to express an identity.
 * With the class, no script means no transform at all: byte for byte the old behaviour.
 */
.feature-list-002.is-stack-receding > .feature-list-002__card {
	transform: scale(calc(1 - var(--recede) * var(--recede-progress)));
}

/*
 * EVENING OUT THE STACK — every card the same height, and every card releases at
 * the same moment.
 *
 * SAME HEIGHT, because a later card can only hide an earlier one that is no taller.
 * A card taller than the ones that land on it shows its foot beneath them, a band
 * of a different photograph under the stack. pattern.js measures the cards and
 * sets `--stack-card-h` to the tallest; each card takes it as a minimum height.
 * Where the photos set the height (a desktop) that is a safety net — keep the
 * photos one proportion, see pattern.php. Where the text does (a stacked card on
 * a tablet or phone), it is what keeps them even.
 *
 * A sticky card is held inside its section by its MARGIN box, so a bottom margin
 * lengthens how far down the page it reaches without changing the card. pattern.js
 * measures each card's `height + top`, and gives each card the difference to the
 * largest as `--stack-pad`: a bottom margin, cancelled by the same amount of
 * negative top margin on the next card (`--stack-pad-prev`), so nothing in the
 * flow moves. Every card now reaches equally far, so they all let go when the last
 * card lands, and leave together, keeping their steps.
 *
 * The last card's pad is real trailing space — exactly the room it needs to land
 * before the others would leave — because nothing follows it to cancel it.
 *
 * Margins, and on the cards, because both of the other homes were measured and
 * do nothing: padding on the section is OUTSIDE the content box that constrains a
 * sticky box, and a box after the last card holds the stack open but cannot change
 * when each card releases relative to the others.
 *
 * Three classes, over core's flex reset of child margins at (0,1,1). Gated on the
 * class: with no JavaScript there is no measurement, so no margin either.
 */
.feature-list-002.is-stack-evened > .feature-list-002__card {
	min-block-size: var(--stack-card-h, 0px);
	margin-block-start: calc(-1 * var(--stack-pad-prev, 0px));
	margin-block-end: var(--stack-pad, 0px);
}

/*
 * THE TOP-GUTTER SWITCH — on by default, off with a class.
 *
 * ON  (default)                     the stack pins clear of the header, plus a gap
 * OFF `feature-list-002--no-top-gutter`   the stack pins flush to the top, at 0
 *
 * Add the class to the SECTION, in Advanced → Additional CSS class(es). The steps
 * still come from `--stack-step` either way, so the cards read 0 / 20 / 40 with the
 * gutter off and 149 / 169 / 189 with it on.
 *
 * Worth knowing before switching it off: the site's header is sticky, so whenever it
 * comes back on a scroll up it will sit ON TOP of the pinned stack. That is exactly
 * what the gutter exists to prevent, so turning it off is a real design choice — it
 * suits a section where the bar is not expected to return over the stack, and it is
 * not a general improvement.
 *
 * The class is COMPOUNDED with the base rather than left to source order. Both
 * selectors would otherwise weigh (0,1,0) and the modifier would win only because it
 * happens to be written later in this file — true today, and quietly untrue the
 * moment someone reorders it.
 *
 * Nothing else has to change: pattern.js reads each card's resolved `top` rather than
 * recomputing the offsets, so the evening-out follows the switch on its own. It is a switch,
 * not a scale — for anything between the two, set `--stack-top` directly instead.
 */
.feature-list-002.feature-list-002--no-top-gutter {
	--stack-top: 0px;
}

/* ── Responsive ───────────────────────────────────────────────────────────
 * Media above the words from `lg` down — the first breakpoint this pattern has
 * ever had.
 *
 * FORCING THE STACK NEEDS `!important`, which is not a shortcut. Core stacks a
 * Columns block on its own, but only below 782px, and it declares the switch at
 * BOTH ends with `!important`: `flex-wrap: wrap !important` by default and
 * `flex-wrap: nowrap !important` from 782px up. Carrying the stack through the
 * tablet range therefore means matching that weight — no selector, however
 * specific, beats an `!important` without one.
 *
 * `order` moves the BOX, not the content. The text column stays first in the
 * document, so reading order and the tab sequence are unchanged while the image
 * appears above it. That is the reason to use `order` rather than swapping the
 * markup, which would put the image ahead of the heading for a screen reader.
 */
@media (max-width: 64rem) {
	/* No step at all once the cards stack. `--stack-step` is what you see of every
	   card underneath the top one; at 0 every card pins at the same line and each
	   one covers the last completely, so the section reads as cards replacing one
	   another rather than as a deck with visible edges. On a narrow screen the
	   cards are already nearly the full width, which left too little room either
	   side for the offset to read as depth rather than as a misalignment.

	   Zero rather than a token because there is no "zero" on the spacing scale,
	   and `--stack-top: 0px` in the no-top-gutter rule below sets the precedent.
	   The first card still pins at `--gutter`; this is only the distance BETWEEN
	   cards.

	   One knock-on worth knowing. A card stops sticking when the room left drops
	   below its own height plus its own pin, so the card with the largest
	   `height + top` releases first. With every `top` now equal, release order is
	   decided by card HEIGHT alone — previously the step broke ties between cards
	   of similar height. It changes which card lets go first on a mixed-height
	   stack, not whether the release works.

	   Nothing else has to change: pattern.js reads each card's RESOLVED `top`
	   rather than recomputing the offsets, so the evening-out follows this on its
	   own. */
	.feature-list-002.feature-list-002 {
		--stack-step: 0px;

		/* Space between the cards once they stack. With the step at 0 the cards
		   pin on the same line and cover each other completely, so without a gap
		   there is nothing between one card and the next in flow either — they
		   read as one continuous slab while scrolling between pins.

		   Doubled class because the gap is a BLOCK SETTING: core emits the
		   section's Block spacing as a generated single class, and the VacuShape
		   instance has it authored to 0, so a single class here would tie and
		   lose. Doubling also covers an instance that set some other value.

		   The evening-out margins sit on the cards, not in the gap, so they are
		   unaffected by it. */
		row-gap: var(--space-md);
	}

	.feature-list-002__card {
		flex-wrap: wrap !important;
		gap: 0;
		/* Height a card gains from `--stack-card-h` goes to its foot, under the
		   words. Left at `normal` it is shared between the two rows, opening a
		   gap between the photo and the words. */
		align-content: flex-start;
	}

	.feature-list-002__card > .wp-block-column {
		flex-basis: 100% !important;
	}

	.feature-list-002__media {
		order: -1;
	}

	.feature-list-002__text > div {
		padding: var(--space-lg) var(--gutter);
	}

	/* A full-width image in a stacked card is as tall as the card is wide, and on
	   a SHORT, wide screen that runs away: measured 907px of image inside a
	   1304px card on a 1024x768 landscape tablet, against a 768px viewport — so
	   no card ever fits the screen and the stack has nothing left to show. The
	   whole section is a pinned stack, so a card taller than the screen defeats
	   the mechanism rather than merely looking tall.

	   Capped against the VIEWPORT because viewport height is the dimension that
	   fails; a width-based ratio cannot see it. `svh`, not `dvh`, so it does not
	   re-evaluate as a mobile browser's URL bar collapses mid-scroll — the plain
	   vh line is the fallback for engines without svh.

	   It only bites where the width would otherwise win: on a phone the image
	   measures 336px against a ~338px cap, i.e. untouched.

	   Keyed to the CARD, not to `__media`, and that matters. Patterns are
	   unsynced, so pages built before the media column was given a class have
	   cards but no `__media` — and they are stacked by the rule above just the
	   same. Hanging the cap on the new class would have capped only new
	   insertions and left the existing ones taller than the screen: measured on
	   VacuShape at 1024x768, a 1186px card around a 907px image. The reorder
	   still needs the class, because there is no other way to name that column,
	   but the height fix does not and should not. */
	.feature-list-002__card img {
		inline-size: 100%;
		max-block-size: 40vh;
		max-block-size: 40svh;
		object-fit: cover;
	}
}
