/* ============================================================
   Reviews - "What people say" (Page Sections layout "reviews",
   brief 4.9; notes home-desktop 3.11 and home-mobile 3.11;
   renders home-desktop-v4 y 5514-6445, home-mobile-v4 y 9559-10245)
   White section: the shared section header with the Google rating
   pill as its aside, then the review cards in a scroll-snap
   carousel (assets/js/carousel.js draws one dot per reachable snap
   point; no autoplay, no arrows, as designed).
   - Phones (< 768): pill 21px under the heading; one card per view
     (295 wide at 402) at the 42px card inset, the next card peeking
     45px at the right edge; every card is a snap point and the last
     one stops at the same inset. Below 402 the inset and the peek
     shrink with the screen so the card keeps its room.
   - Tablet (768-1023): pill under the heading (it would fit beside it
     from about 886px; one tablet layout is kept); two cards per view
     inside the container, snapping a page of two at a time.
   - Desktop (>= 1024): pill right-aligned and centred on the H2;
     a grid of three across that grows downwards: six cards, then
     "Show more reviews" adds six at a time up to 18 (Miles
     2026-11-01, assets/js/reviews.js; all of them without it). The
     track never overflows, so the dots stay hidden.
   Phones and tablets keep the carousel to the first six cards. An odd
   count there is padded out on tablets so the last page starts on its
   own card (--reviews-pad-tablet, set by section-reviews.php).
   Every card in the carousel shares the tallest card's height (the
   design's 232 / 240 mix is a file slip, brief 4.9), never less than
   the drawn frame (232; 257 on phones). The dots sit 53 (desktop) /
   48 (phones) below the cards; their tap targets overhang the section
   padding so the visible dots keep the section's standard bottom
   spacing (normalised from 69, brief 2.1 and 12).
   Cards are sized against the track (a size container, cqi units);
   browsers without container units (Safari 15) get vw-based widths
   from the --reviews-track fallbacks, swapped out in the @supports
   block at the end of the file.
   ============================================================ */

/* ---------- Header ---------- */

/* Phones: the pill 21px under the H2 box (26px under the heading's
   Figma frame, home-mobile 3.11), then 35px to the cards. */
.reviews__header {
	margin-bottom: 35px;
}

/* No cards (rating pill only): the section padding closes the band. */
.reviews__header:last-child {
	margin-bottom: 0;
}

/* The designed break: "Trusted by beginners and / instructors alike". */
.reviews__header .section-header__title {
	max-width: 14em;
}

.reviews__header .section-header__aside {
	margin-top: 21px;
}

/* ---------- Google rating pill: 349 x 47, Cream, 1px Border Warm ---------- */

/* 349px wide from 402 up. Narrower phones (375, 360) would overflow the
   text column, so the stars shrink with the viewport there (23px boxes
   at 402, about 19px at 360); at 320 the text wraps as a last resort. */
.rating-pill {
	--rating-star: clamp(16px, 21.3vw - 57.3px, 23px);
	display: inline-flex;
	align-items: center;
	gap: 9px;
	max-width: 100%;
	min-height: 47px;
	padding: 4px 16px;
	border: var(--border-hairline) solid var(--color-border);
	border-radius: var(--radius-pill);
	background-color: var(--color-surface-warm);
	color: var(--color-text);
	font-size: var(--fs-small);
	font-weight: var(--fw-semibold);
	line-height: var(--lh-body);
	text-decoration: none;
	transition: border-color var(--transition);
}

.rating-pill__google {
	width: 24px;
	height: 24px;
}

/* 104 x 18 of ink: 23px stars on a 21.25px pitch. */
.rating-pill__stars {
	display: inline-flex;
	flex: none;
	color: var(--color-rating);
}

.rating-pill__stars .icon {
	width: var(--rating-star);
	height: var(--rating-star);
}

.rating-pill__stars .icon + .icon {
	margin-left: calc(var(--rating-star) * -0.076);
}

.rating-pill__text {
	margin-left: 4px;
	text-decoration: underline;
	text-decoration-color: transparent;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
	transition: text-decoration-color var(--transition);
}

/* Link hover: the border turns Navy and the text underlines (colour
   only, nothing moves). Touch screens show the underline at rest. */
a.rating-pill:hover,
a.rating-pill:focus-visible {
	border-color: var(--color-link);
}

a.rating-pill:hover .rating-pill__text,
a.rating-pill:focus-visible .rating-pill__text {
	text-decoration-color: currentColor;
}

a.rating-pill:focus-visible {
	outline-color: var(--color-focus-light);
}

@media (hover: none) {
	a.rating-pill .rating-pill__text {
		text-decoration-color: currentColor;
	}
}

/* ---------- Carousel ---------- */

/* Phones: the track runs edge to edge (out of the container's gutter),
   so the card inset moves onto the list and the scroll padding: 42px
   from 402 up, shrinking below (about 38 at 360). The viewport is a
   size container so the cards can be sized against it. */
.reviews__viewport {
	--reviews-inset: min(var(--inset-card-mobile), 10.45vw);
	container-type: inline-size;
	margin-inline: calc(-1 * var(--gutter));
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	scroll-padding-inline: var(--reviews-inset);
	scrollbar-width: none;
}

.reviews__viewport::-webkit-scrollbar {
	display: none;
}

@media (prefers-reduced-motion: no-preference) {
	.reviews__viewport {
		scroll-behavior: smooth;
	}
}

/* Drawn inside the track: it runs to the screen edges on phones. */
.reviews__viewport:focus-visible {
	outline-color: var(--color-focus-light);
	outline-offset: -2px;
}

/* --reviews-track is the track's width (100cqi, see the end of the file;
   100vw without container units). Cards: 295 x 257 at 402 (x 41 / 356 /
   671 drawn) - the track minus the inset, the gap and a peek of the next
   card (45px at 402, about 40 at 360), never wider than the desktop
   card. max-content: the list is as wide as its cards plus its padding,
   and the end padding (the track minus one card and the inset) lets the
   last card snap to the same inset as the others. */
.reviews__list {
	--reviews-track: 100vw;
	--reviews-peek: clamp(28px, 11.2vw, 45px);
	--reviews-card: min(411px, var(--reviews-track) - var(--reviews-inset) - var(--gap-grid) - var(--reviews-peek));
	display: flex;
	gap: var(--gap-grid);
	width: max-content;
	margin: 0;
	padding: 0 calc(var(--reviews-track) - var(--reviews-card) - var(--reviews-inset)) 0 var(--reviews-inset);
	list-style: none;
}

.reviews__item {
	display: flex;
	flex: none;
	width: var(--reviews-card);
	scroll-snap-align: start;
}

/* 48px under the cards. The 11px dot sits centred in its tap target
   (main.css), which overhangs the bottom padding by the same amount, so
   the visible dots sit the section padding above the end. */
.reviews__dots {
	--reviews-dot-overhang: calc((var(--tap-target) - 11px) / 2);
	margin-top: calc(48px - var(--reviews-dot-overhang));
	margin-bottom: calc(-1 * var(--reviews-dot-overhang));
}

/* ---------- Review card ---------- */

/* The drawn frame (257 on phones, 232 from tablet up) is the minimum;
   longer reviews grow the card, and the whole carousel with it. Long
   unbroken strings (a pasted link) wrap instead of spilling out.
   position: relative contains the visually hidden ", " in the byline:
   an absolutely positioned span with no positioned ancestor inside the
   track escapes its overflow clipping and widens the page. */
.review-card {
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	min-height: 257px;
	padding: 24px;
	border: var(--border-hairline) solid var(--color-border);
	border-radius: var(--radius-md);
	background-color: var(--color-surface-warm);
	color: var(--color-text);
	overflow-wrap: anywhere;
}

/* 44px avatar, then name and course 12px to its right, centred on it. */
.review-card__author {
	display: flex;
	align-items: center;
	gap: 12px;
}

.review-card__avatar {
	display: grid;
	flex: none;
	place-items: center;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	background-color: var(--color-surface-dark);
	color: var(--color-text-on-dark);
	font-size: var(--fs-body);
	font-weight: var(--fw-semibold);
	line-height: 1;
}

.review-card__byline {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

.review-card__name {
	font-size: var(--fs-body);
	font-weight: var(--fw-semibold);
	line-height: var(--lh-body);
}

.review-card__course {
	color: var(--color-text-muted);
	font-size: var(--fs-label);
	line-height: var(--lh-body);
}

/* Five stars of about 12px ink on an 18px pitch, 19px under the avatar
   (ink to ink). */
.review-card__stars {
	display: flex;
	gap: 3px;
	margin-top: 17px;
	color: var(--color-rating);
}

.review-card__star {
	width: 15px;
	height: 15px;
}

/* Below five stars the rest are drawn as outlines, so the rating does
   not rest on colour alone (the shape differs, not just the tint). */
.review-card__star--empty {
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linejoin: round;
}

/* 14/21 Navy, 19px under the stars (ink to ink). */
.review-card__quote {
	margin: 12px 0 0;
	font-size: var(--fs-small);
	line-height: var(--lh-body);
}

.review-card__quote p + p {
	margin-top: 10px;
}

/* ============================================================
   Tablet: two cards per view inside the container
   ============================================================ */

@media (min-width: 768px) {
	.reviews__header {
		margin-bottom: 40px;
	}

	.reviews__viewport {
		margin-inline: 0;
		scroll-padding-inline: 0;
	}

	/* The track now sits inside the gutters: ring it outside the cards. */
	.reviews__viewport:focus-visible {
		outline-offset: 4px;
	}

	/* An odd count ends on a lone card: half a view of end padding lets
	   that last page start on it (--reviews-pad-tablet is 1). */
	.reviews__list {
		--reviews-track: calc(100vw - 2 * var(--gutter));
		--reviews-card: calc((var(--reviews-track) - var(--gap-grid)) / 2);
		padding: 0 calc(var(--reviews-pad-tablet, 0) * (var(--reviews-track) + var(--gap-grid)) / 2) 0 0;
	}

	/* A page is two cards: only the first of each pair snaps. */
	.reviews__item {
		scroll-snap-align: none;
	}

	.reviews__item:nth-child(2n + 1) {
		scroll-snap-align: start;
	}

	.reviews__dots {
		margin-top: calc(53px - var(--reviews-dot-overhang));
	}

	.review-card {
		min-height: 232px;
	}
}

/* ============================================================
   Desktop: pill beside the heading; a grid of three across
   ============================================================ */

@media (min-width: 1024px) {
	/* The H2 and the pill share a row so the pill centres on the heading
	   (the header's own split layout would centre it on eyebrow + H2).
	   Centred on the H2's margin box (its 13px top margin included) the
	   pill lands within 1px of the drawn spot: the design centres it on
	   the heading's Figma frame, where Koulen sits about 4px lower in its
	   line box than in the browser. */
	.reviews__header.section-header--split {
		grid-template-columns: minmax(0, 1fr) auto;
		grid-template-areas:
			"eyebrow ."
			"title aside";
		align-items: center;
	}

	.reviews__header .section-header__main {
		display: contents;
	}

	.reviews__header .section-header__eyebrow {
		grid-area: eyebrow;
	}

	.reviews__header .section-header__title {
		grid-area: title;
	}

	.reviews__header.section-header--split .section-header__aside {
		grid-area: aside;
		margin: 0;
	}

	.reviews__header {
		margin-bottom: clamp(32px, 25.8px + 1.5414vw, 48px); /* main.css section-header spacing: 48 at 1440 */
	}

	/* Three across, growing downwards as batches are shown; each row is
	   as tall as its tallest card (cards in a row share that height;
	   hidden cards take no row). Nothing scrolls sideways, so no card is
	   a snap point. */
	.reviews__list {
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		width: auto;
		padding: 0;
	}

	.reviews__item,
	.reviews__item:nth-child(2n + 1) {
		width: auto;
		scroll-snap-align: none;
	}

	/* The designed quotes break at about 348px (the Figma text box is
	   narrower than the card); a 350px measure reproduces the drawn line
	   breaks without adding lines. */
	.review-card__quote {
		max-width: 350px;
	}
}

/* ============================================================
   Container units: the exact track width. Last in the file so it
   overrides the vw fallbacks above at every width; skipped where
   cqi is unknown (a var() holding an unknown unit would otherwise
   void the width instead of falling back).
   ============================================================ */

@supports (width: 1cqi) {
	.reviews__list {
		--reviews-track: 100cqi;
	}
}

/* ============================================================
   More reviews (Miles 2026-11-01; assets/js/reviews.js)
   ============================================================ */

/* The cards after the first six: never in the carousel (phones and
   tablets), and no snap points there (carousel.js would count them).
   Two classes, so this beats the tablet snap rule above. */
.reviews__item.reviews__item--extra {
	display: none;
	scroll-snap-align: none;
}

/* "Show more reviews", "View all reviews on Google" and "Show less",
   centred under the cards (after the dots where they show). Only the
   Google button shows below 1024px and without the script. */
.reviews__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 12px 32px;
	margin-top: 40px;
}

.reviews__show-more,
.reviews__show-less {
	display: none;
}

/* A text button: Navy, underlined, the tap target's height. */
.reviews__show-less {
	min-height: var(--tap-target);
	padding: 0 4px;
	border: 0;
	background: none;
	color: var(--color-link);
	font: inherit;
	font-weight: 600;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
	cursor: pointer;
	transition: color var(--transition);
}

.reviews__show-less:hover,
.reviews__show-less:focus-visible {
	color: var(--color-link-hover-on-light);
}

.reviews__show-less:focus-visible {
	outline: 2px solid var(--color-focus-light);
	outline-offset: 2px;
}

@media (min-width: 1024px) {
	/* Without the script every card shows; with it (has-js is set before
	   the first paint, so nothing flashes) only the batches it marks. */
	.reviews__item.reviews__item--extra {
		display: flex;
	}

	.has-js .reviews__item.reviews__item--extra:not(.is-shown) {
		display: none;
	}

	.reviews.is-ready.can-more .reviews__show-more {
		display: inline-flex;
	}

	.reviews.is-ready.can-more .reviews__google {
		display: none;
	}

	.reviews.is-ready.can-less .reviews__show-less {
		display: inline-block;
	}

	/* The cards coming in or going out fade while the grid's height glides
	   (reviews.js). */
	.reviews__item.is-entering,
	.reviews__item.is-leaving {
		opacity: 0;
	}
}

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
	.reviews__item.reviews__item--extra {
		transition: opacity var(--reviews-reveal-duration) ease;
	}
}
