/**
 * Component: Feature Grid — styles
 * Scoped to .feature-grid (BEM root). Tokens from style.css.
 *
 * Comp (1440, page y; Figma SVG export v2; section 1642–2383): H2 line box
 * 1787.9 · tiles 2021–2108 · titles 2155.9 · copy 2198.2. Column centres
 * 378 / 720 / 1062 → three 312px columns, 30px gaps, centred in the 1000px
 * band. Copy wraps where the comp does because 312 sits between the longest
 * line (297) and the next word.
 * v3 (2026-09-29) moves all of it 40px down (the hero grew) and its line shape
 * 36px, so the section ends 4px sooner after its copy: padding-bottom 117.
 */

.feature-grid {
	position: relative;
	padding: 146px var(--gutter) 117px;
	scroll-margin-top: 24px;
}

.feature-grid__inner {
	max-width: var(--content-w);
	margin: 0 auto;
	text-align: center;
}

.feature-grid__heading {
	max-width: 9.8em; /* 470px at 48px — breaks after "to Stay" at every size */
	margin-inline: auto;
}

.feature-grid__list {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 312px));
	justify-content: center;
	gap: 30px;
	margin: 113px 0 0; /* the small squares poke above this; they're absolute */
	padding: 0;
	list-style: none;
}

.feature-grid__item {
	display: flex;
	flex-direction: column;
	align-items: center;
	margin: 0;
}

/* ── Line shape ───────────────────────────────────────────────── */
/* Straddles the boundary with how_it_works, so it is positioned from the
   section's bottom edge and overflows it on purpose. The wrapper is the
   centred 1440 container the shape is pinned to (≥1440 it stays whole beside
   the content instead of sticking to the screen edge); below 1440 it shrinks
   with the viewport, holds 0.45 on tablet and hides on mobile. z-index -1
   with no stacking context in between puts it behind the content of both
   sections. */
.feature-grid__lines {
	position: absolute;
	inset: 0;
	max-width: var(--page-max);
	margin-inline: auto;
	pointer-events: none;
}

/* Comp box (−55.55, 2201.45, 398.2 × 399.1); section bottom 2383.
   Below 1440 the scale is (100vw − 400px) / 1040px — steeper than plain vw,
   so the lower loop never reaches the centred how_it_works heading on the
   way down (plain vw brushed its first letter around 1100). */
.feature-grid__line {
	z-index: -1;
	left: max(-55.55px, 21.365px - 5.3413vw);
	top: calc(100% - min(181.55px, 17.4567vw - 69.827px));
	width: min(398.2px, 38.2885vw - 153.154px);
}

/* ── Icon tile ────────────────────────────────────────────────── */
/* The comp's tile uses a Figma PROGRESSIVE blur: sharp at its light corner,
   blurring to σ 4 at the opposite one (the SVG export flattens that to a flat
   stdDeviation 4; the Figma render shows the sharp corner). Built as three
   copies of the tile — sharp (::before), σ 2 and σ 4 (__blur's pseudos) —
   each masked to its share of the diagonal and ADDED together with
   plus-lighter inside the isolated art box: weights always sum to 1, so it is
   a true cross-fade (plain stacking would darken the middle).
   ::after is the small square, a flat blur 4. Sizes are 1440 px × --art-scale
   so mobile shrinks the group in one place. Gradients are Figma's, converted
   to CSS angles/stops; the tile lightens toward the corner opposite its
   square. */
.feature-grid__art {
	--art-scale: 1;
	--tile-fill: linear-gradient(220.24deg, var(--color-teal-lo) 50%, var(--color-teal-hi) 114.73%);
	--blur-dir: 45deg; /* sharp → soft */
	--blur-pad: calc(12px * var(--art-scale)); /* room for the σ 4 halo */
	--blur-pad-d: calc(var(--blur-pad) * 1.41421); /* the same, along the diagonal */
	position: relative;
	isolation: isolate;
	display: grid;
	place-items: center;
	width: calc(87px * var(--art-scale));
	height: calc(87px * var(--art-scale));
}

.feature-grid__art::before,
.feature-grid__art::after,
.feature-grid__blur::before,
.feature-grid__blur::after {
	content: "";
	position: absolute;
}

.feature-grid__art::before {
	inset: 0;
	border-radius: calc(20px * var(--art-scale));
	background: var(--tile-fill);
	-webkit-mask-image: linear-gradient(var(--blur-dir), #000, transparent 50%);
	mask-image: linear-gradient(var(--blur-dir), #000, transparent 50%);
}

/* No z-index here: this must not become a stacking context, or its layers
   would blend with each other instead of with the sharp tile. */
.feature-grid__blur {
	position: absolute;
	inset: 0;
}

/* Padded by a transparent border so the mask box holds the whole halo. */
.feature-grid__blur::before,
.feature-grid__blur::after {
	inset: calc(var(--blur-pad) * -1);
	border: var(--blur-pad) solid transparent;
	border-radius: calc(20px * var(--art-scale) + var(--blur-pad));
	background: var(--tile-fill) padding-box;
	mix-blend-mode: plus-lighter;
}

.feature-grid__blur::before {
	filter: blur(calc(2px * var(--art-scale)));
	-webkit-mask-image: linear-gradient(var(--blur-dir), transparent var(--blur-pad-d), #000 50%, transparent calc(100% - var(--blur-pad-d)));
	mask-image: linear-gradient(var(--blur-dir), transparent var(--blur-pad-d), #000 50%, transparent calc(100% - var(--blur-pad-d)));
}

.feature-grid__blur::after {
	filter: blur(calc(4px * var(--art-scale)));
	-webkit-mask-image: linear-gradient(var(--blur-dir), transparent 50%, #000 calc(100% - var(--blur-pad-d)));
	mask-image: linear-gradient(var(--blur-dir), transparent 50%, #000 calc(100% - var(--blur-pad-d)));
}

/* Small square: top-right of the tile (features 1 and 3). */
.feature-grid__art::after {
	--drift-x: 3px;
	--drift-y: -5px;
	top: calc(-24px * var(--art-scale));
	left: calc(85px * var(--art-scale));
	width: calc(28px * var(--art-scale));
	height: calc(28px * var(--art-scale));
	border-radius: calc(8px * var(--art-scale));
	background: linear-gradient(36.47deg, var(--color-teal-lo) 31.07%, var(--color-teal-deep, #010D0E) 104.11%);
	filter: blur(calc(4px * var(--art-scale)));
	animation: feature-grid-drift 7s ease-in-out infinite;
}

/* Feature 2: square bottom-right, so the tile lightens toward the top-left
   and sharpens there. */
.feature-grid__art--square-bottom {
	--tile-fill: linear-gradient(310.24deg, var(--color-teal-lo) 50%, var(--color-teal-hi) 114.73%);
	--blur-dir: 135deg;
}

.feature-grid__art--square-bottom::after {
	--drift-y: 5px;
	top: calc(81px * var(--art-scale));
	left: calc(80px * var(--art-scale));
	background: linear-gradient(126.47deg, var(--color-teal-lo) 31.07%, var(--color-teal-deep, #010D0E) 104.11%);
}

.feature-grid__item:nth-child(2) .feature-grid__art::after { animation-delay: -2.3s; }
.feature-grid__item:nth-child(3) .feature-grid__art::after { animation-delay: -4.6s; }

/* Without plus-lighter the layers can't cross-fade cleanly: fall back to one
   evenly blurred tile. */
@supports not (mix-blend-mode: plus-lighter) {
	.feature-grid__art::before {
		-webkit-mask-image: none;
		mask-image: none;
		filter: blur(calc(3px * var(--art-scale)));
	}

	.feature-grid__blur {
		display: none;
	}
}

@keyframes feature-grid-drift {
	0%, 100% { transform: translate(0, 0); }
	50%      { transform: translate(var(--drift-x), var(--drift-y)); }
}

.feature-grid__icon {
	position: relative;
	z-index: 1;
	display: block;
	width: calc(64px * var(--art-scale));
	height: calc(64px * var(--art-scale));
	color: var(--color-icon);
}

.feature-grid__icon svg {
	display: block;
	width: 100%;
	height: 100%;
}

/* Icons draw in once their item reveals. Scoped to [data-reveal] so the
   undrawn state only exists where the reveal script will finish it; the
   no-JS <noscript> rule in functions.php and the reduced-motion block below
   both force the finished state. */
.feature-grid__item[data-reveal] .feature-grid__icon path {
	stroke-dasharray: 1;
	stroke-dashoffset: 1;
}

.feature-grid__item.is-revealed .feature-grid__icon path {
	animation: feature-grid-draw 1.3s var(--ease-out) forwards;
	animation-delay: calc(var(--reveal-delay, 0ms) + 250ms);
}

@keyframes feature-grid-draw {
	to { stroke-dashoffset: 0; }
}

/* ── Copy ─────────────────────────────────────────────────────── */
.feature-grid__title {
	margin: 48px 0 0;
	font-family: var(--font-title);
	font-size: var(--text-h4);
	font-weight: 700;
	line-height: 1.25; /* 30 */
	color: var(--color-text);
}

.feature-grid__body {
	margin: 12px 0 0;
	font-size: var(--text-body-lg);
	line-height: 1.778; /* 32 */
	color: var(--color-text-muted);
}

/* ── Tablet ≤900px ────────────────────────────────────────────── */
@media (max-width: 900px) {
	.feature-grid {
		padding-top: 96px;
		padding-bottom: 96px;
	}

	.feature-grid__list {
		gap: 20px;
		margin-top: 87px;
	}

	.feature-grid__body {
		font-size: var(--text-body);
		line-height: 1.6;
	}

	/* 0.45 × the comp: small enough that the lower loop ends above the
	   how_it_works heading (96px below the boundary) at every tablet width. */
	.feature-grid__line {
		left: -25px;
		top: calc(100% - 81.7px);
		width: 179.2px;
	}
}

/* Inside the tablet band: three columns stop fitting their titles below
   ~640px, so stack before the mobile breakpoint. The gap leaves room for the
   small square poking above the next tile. */
@media (max-width: 640px) {
	.feature-grid__list {
		grid-template-columns: minmax(0, 1fr);
		gap: 72px;
		max-width: 340px;
		margin-inline: auto;
	}
}

/* ── Mobile ≤480px ────────────────────────────────────────────── */
@media (max-width: 480px) {
	.feature-grid {
		padding-top: 72px;
		padding-bottom: 72px;
	}

	.feature-grid__list {
		gap: 66px;
		margin-top: 66px;
	}

	.feature-grid__art {
		--art-scale: 0.875; /* 56px icons */
	}

	.feature-grid__title {
		margin-top: 42px;
	}

	/* No free margin beside the stacked copy for it to live in. */
	.feature-grid__lines {
		display: none;
	}
}

/* ── Reduced motion ───────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
	.feature-grid__art::after {
		animation: none;
	}

	.feature-grid__item[data-reveal] .feature-grid__icon path,
	.feature-grid__item.is-revealed .feature-grid__icon path {
		stroke-dashoffset: 0;
		animation: none;
	}
}
