/* ---------------------------------------------------------------------------
 * Page sections — the rules the global styles engine cannot emit.
 *
 * Everything here used to live in a <style> element inside a core/html block in
 * the homepage's own post_content. That markup did not survive wp_kses_post(),
 * so any editor below Administrator silently destroyed the hero the first time
 * they saved the page. CSS belongs in the theme, so here it is.
 *
 * Two rules of thumb for this file:
 *   1. Every selector that overrides a core block stylesheet is one step more
 *      specific than the core rule it beats, so it wins on specificity rather
 *      than on the order stylesheets happen to be printed in.
 *   2. Every block is commented with the reason theme.json cannot express it.
 * ------------------------------------------------------------------------- */


/* ===========================================================================
 * Home hero (patterns/home-hero-video.php — a core/cover, video background)
 * ========================================================================= */

/* The ground behind the clip. The cover's own overlay paints the scrim, so the
 * colour underneath the semi-transparent video has to come from somewhere; cover
 * does not support a block background (supports.color.background is false). */
.pickleball-hero.wp-block-cover {
	background-color: var(--wp--preset--color--primary);
}

/* Core's cover stylesheet sets `padding: 1em` on .wp-block-cover (0,1,0). The
 * hero's left/right padding has to line up with the site's root padding so the
 * headline sits on the same gutter as every other section. */
.pickleball-hero.wp-block-cover {
	padding-left: var(--wp--style--root--padding-left);
	padding-right: var(--wp--style--root--padding-right);
}

/* The inner container carries the constrained layout and therefore also picks
 * up .has-global-padding; that would double the gutter. */
.pickleball-hero.wp-block-cover>.wp-block-cover__inner-container {
	padding-left: 0;
	padding-right: 0;
}

/* The scrim. dimRatio/gradient already ask core for this, but core only emits
 * the gradient class when the cover has no media URL, so the token is applied
 * here explicitly. Beats core's `.wp-block-cover .wp-block-cover__background`
 * (0,2,0) at (0,3,0). */
.pickleball-hero.wp-block-cover .wp-block-cover__background {
	background-color: transparent;
	background-image: var(--wp--preset--gradient--hero-scrim);
	opacity: 1;
}

/* Canvas calls for the clip at 55% and the still at 45% so the headline keeps
 * its contrast against both. Core's own rules for these two elements are
 * (0,2,1) for the video and (0,2,0) for the image; these are one step more. */
.pickleball-hero.wp-block-cover video.wp-block-cover__video-background {
	opacity: 0.55;
}

.pickleball-hero.wp-block-cover img.wp-block-cover__image-background {
	opacity: 0.45;
}

/* Keep the still visible until the desktop clip is actually playing. */
.pickleball-hero.wp-block-cover video.wp-block-cover__video-background {
 visibility: hidden;
}
@media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
 .pickleball-hero.wp-block-cover.is-video-playing video.wp-block-cover__video-background { visibility: visible; }
 .pickleball-hero.wp-block-cover.is-video-playing img.wp-block-cover__image-background { visibility: hidden; }
}
@media (max-width: 899.98px) {
 .pickleball-hero.wp-block-cover video.wp-block-cover__video-background { display: none; }
}

/* Measure. theme.json has no per-block max-width for a heading inside a cover. */
.pickleball-hero .wp-block-heading {
	max-width: 17ch;
	text-wrap: balance;
}

/* The standfirst's measure, and its colour.
 *
 * The colour is here rather than on the block because it is a color-mix(), and
 * safecss_filter_attr() — the CSS half of kses — drops any declaration it does
 * not recognise. An inline `color: color-mix(...)` therefore disappears the
 * first time a non-administrator saves the page, taking the standfirst back to
 * full-strength base white against the scrim. */
.pickleball-hero__lede {
	max-width: 54ch;
	color: color-mix(in oklab, var(--wp--preset--color--base) 90%, transparent);
}


/* ===========================================================================
 * About team grid (patterns/about-team.php)
 * ========================================================================= */

.pickleball-team-card {
	height: 100%;
}

/* The portrait fills its column.
 *
 * Every box between the figure and the <img> has to be told to, not just the
 * image: core wraps a linked image in an inline-block <a>, and the site's WebP
 * plugin wraps it again in an inline <picture>. A shrink-to-fit box sizes
 * itself from the image's intrinsic width and treats the image's own
 * `width: 100%` as auto while doing it, so the portrait came out at its natural
 * 225px inside a 350px column instead of filling it. Measured at 390px wide
 * before this rule: figure 350px, img 225px. */
.pickleball-team-card .wp-block-image,
.pickleball-team-card .wp-block-image a,
.pickleball-team-card .wp-block-image picture,
.pickleball-team-card .wp-block-image img {
	display: block;
	width: 100%;
}

/* The stand-in for a bio page with no usable image in its content. A grid with
 * an aspect-ratio and centred initials — theme.json can style a group, but not
 * give it a square box with a centred single child. */
.pickleball-team-card__placeholder {
	aspect-ratio: 1;
	display: grid;
	place-items: center;
	border-radius: var(--wp--custom--radius--chip);
	background-image: var(--wp--preset--gradient--dark-band);
	border: 1px solid var(--wp--preset--color--line);
}

.pickleball-team-card__initials {
	margin: 0;
	font-family: var(--wp--preset--font-family--archivo);
	font-size: clamp(30px, 4vw, 44px);
	font-weight: 800;
	letter-spacing: 0.02em;
	line-height: 1;
	color: var(--wp--preset--color--accent);
}

/* ===========================================================================
 * Tints of the base colour, for copy sitting on a dark band
 *
 * These used to be inline `color: color-mix(...)` and `color: oklch(...)`
 * declarations on the block. safecss_filter_attr() — the CSS half of kses —
 * keeps only the declarations it recognises, and it recognises neither
 * function, so every one of them vanished the first time a non-administrator
 * saved the page. As classes they are immune, and they are also written once
 * instead of eight times.
 * ========================================================================= */

.pickleball-on-dark {
	color: color-mix(in oklab, var(--wp--preset--color--base) 84%, transparent);
}

.pickleball-on-dark-muted {
	color: color-mix(in oklab, var(--wp--preset--color--base) 74%, transparent);
}

.pickleball-on-dark-soft {
	color: color-mix(in oklab, var(--wp--preset--color--base) 82%, transparent);
}

.pickleball-stars {
	color: oklch(0.66 0.15 78);
}

/* Hero content alignment — fixed in patterns/home-hero-video.php, not here.
 *
 * The cover's inner container uses constrained layout, and core's rule is
 *   .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull))
 *   { margin-left: auto !important; margin-right: auto !important; }
 * Because it is !important, no selector in this file can beat it — an earlier
 * attempt at `.pickleball-hero ... > * { margin-inline: 0 }` matched, loaded and
 * was still overridden, leaving the h1 at 239px and the lede at 255px while the
 * badge and buttons sat at 32px.
 *
 * The children are now wrapped in a flow-layout group instead. Flow layout emits
 * only margin-block rules, never margin-inline: auto, so the 17ch and 54ch
 * measures below cap from the left as the canvas draws them. The wrapper is
 * itself a constrained child, so it still centres the 1280px column on wide
 * screens, which is the part of constrained layout worth keeping. */


/* ===========================================================================
 * Home Google reviews (patterns/home-reviews.php, inc/reviews.php)
 *
 * The cards are generated markup, not blocks, so none of this can come from
 * theme.json: a grid of fixed-height cards, a clamped quote and a round
 * initials avatar are all shapes the global styles engine has no vocabulary
 * for. Every value below is a theme token.
 * ========================================================================= */

/* The rating tile beside the heading. A flex child of the heading row, drawn
 * as the canvas draws it: sunken ground, hairline border, chip radius. */
.pickleball-reviews__summary {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--chip);
	background-color: var(--wp--preset--color--base-sunken);
}

.pickleball-reviews__score {
	margin: 0;
	font-family: var(--wp--preset--font-family--archivo);
	font-size: clamp(34px, 3.2vw, 46px);
	font-weight: 800;
	letter-spacing: -0.04em;
	line-height: 1;
}

.pickleball-reviews__summary-text {
	display: grid;
	gap: 4px;
}

.pickleball-reviews__summary-stars {
	margin: 0;
	font-size: 19px;
	letter-spacing: 0.1em;
	line-height: 1;
}

.pickleball-reviews__meta {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm);
	color: var(--wp--preset--color--contrast-muted);
}

/* Three across, then two, then one. The cards stretch to the tallest in the
 * row, which is what makes the fixed-height card of the canvas hold up when
 * one review truncates shorter than another. */
.pickleball-reviews__cards {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--30);
	align-items: stretch;
}

@media (max-width: 1023.98px) {
	.pickleball-reviews__cards {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 719.98px) {
	.pickleball-reviews__cards {
		grid-template-columns: minmax(0, 1fr);
	}
}

.pickleball-review-card {
	display: flex;
	flex-direction: column;
	gap: 14px;
	min-height: 260px;
	padding: 26px;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	background-color: var(--wp--preset--color--base);
	box-shadow: var(--wp--custom--shadow--card);
}

.pickleball-review-card__stars {
	margin: 0;
	font-size: 17px;
	letter-spacing: 0.08em;
	line-height: 1;
}

/* The quote takes the slack so the author row sits on the card's floor however
 * short the review is. inc/reviews.php already trims the text on a word
 * boundary; the clamp is the backstop for a wide card at a large font size. */
.pickleball-review-card__quote {
	flex: 1 1 auto;
	margin: 0;
	padding: 0;
	border: 0;
}

.pickleball-review-card__quote p {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 8;
	overflow: hidden;
	margin: 0;
	font-size: var(--wp--preset--font-size--base);
	line-height: 1.55;
	color: var(--wp--preset--color--contrast);
}

.pickleball-review-card__author {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-top: auto;
}

/* The initials stand in for the reviewer's Google photo on purpose: the photo
 * is a googleusercontent.com URL, and the theme does not call third-party
 * hosts at runtime. */
.pickleball-review-card__avatar {
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: var(--wp--custom--radius--pill);
	background-image: var(--wp--preset--gradient--dark-band);
	font-family: var(--wp--preset--font-family--archivo);
	font-size: 15px;
	font-weight: 800;
	letter-spacing: 0.02em;
	line-height: 1;
	color: var(--wp--preset--color--accent);
}

.pickleball-review-card__who {
	display: grid;
	gap: 2px;
	min-width: 0;
}

.pickleball-review-card__name {
	font-family: var(--wp--preset--font-family--archivo);
	font-size: var(--wp--preset--font-size--sm);
	font-style: normal;
	font-weight: 700;
	line-height: 1.25;
	color: var(--wp--preset--color--contrast);
}

.pickleball-review-card__meta {
	font-size: var(--wp--preset--font-size--xs);
	line-height: 1.3;
	color: var(--wp--preset--color--contrast-muted);
}

/*
 * FAQ accordion.
 *
 * core/details, so it opens with no JavaScript and the browser's own in-page
 * search can find a closed answer. The rules below are borders and rhythm
 * only; the open and closed behaviour is the element's.
 */
.pickleball-faq__item {
	padding-block: var(--wp--preset--spacing--30);
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.pickleball-faq__item:first-child {
	border-block-start: 1px solid var(--wp--preset--color--line);
}

.pickleball-faq__item>summary {
	cursor: pointer;
	list-style: none;
	display: flex;
	gap: var(--wp--preset--spacing--20);
	align-items: baseline;
	justify-content: space-between;
	font-size: var(--wp--preset--font-size--md);
	font-weight: 700;
	letter-spacing: -0.015em;
}

/* Safari draws its own triangle unless this is removed too. */
.pickleball-faq__item>summary::-webkit-details-marker {
	display: none;
}

/* The chevron is the affordance; it turns when the answer opens. */
.pickleball-faq__item>summary::after {
	content: "";
	flex: 0 0 auto;
	width: 10px;
	height: 10px;
	margin-block-start: 4px;
	border-inline-end: 2px solid var(--wp--preset--color--accent-deep);
	border-block-end: 2px solid var(--wp--preset--color--accent-deep);
	transform: rotate(45deg);
	transition: transform 180ms ease;
}

.pickleball-faq__item[open]>summary::after {
	transform: rotate(-135deg);
}

.pickleball-faq__item>summary:hover {
	color: var(--wp--preset--color--accent-deep);
}

/*
 * Video gallery.
 *
 * core/embed already makes the players responsive; this only stops the
 * figure's default block margin breaking the grid's own spacing.
 */
.pickleball-video {
	margin: 0;
	overflow: hidden;
	border-radius: var(--wp--custom--radius--chip);
	background: var(--wp--preset--color--primary);
}

.pickleball-video iframe {
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	height: auto;
	border: 0;
}

/* Partner logos sit on their own card, so they need room, not a crop. */
.pickleball-partner-card__logo {
	margin: 0;
}

.pickleball-partner-card__logo img {
	width: auto;
	max-width: 100%;
	max-height: 72px;
	object-fit: contain;
}

@media (prefers-reduced-motion: reduce) {
	.pickleball-faq__item>summary::after {
		transition: none;
	}
}

/*
 * Camps hub: the city cards.
 *
 * Two states, because the photography does not exist yet. Without an image the
 * card is typographic and the border and raised background carry it. With one,
 * the copy moves over the photograph. Nothing here reads a page's featured
 * image — see pickleball_camp_cities() for why that fallback would be wrong.
 */
/*
 * padding:0 is load-bearing. Core ships
 * :where(.wp-block-group.has-background){padding:1.25em 2.375em}, and this
 * card has a background, so without this the photograph is laid into a box
 * already inset by 40px a side and sits small in the corner. The card's
 * padding belongs to __body, which is the only part that wants it.
 */
.pickleball-camp-card {
	display: flex;
	flex-direction: column;
	padding: 0;
	overflow: hidden;
	/* So the photograph is clipped by the card's radius. */
}

/*
 * The figure has to be beaten flat: the theme rounds every core/image and
 * core adds its own block margins, which together inset the photograph inside
 * the card and leave a visible gap on three sides. The card owns the radius.
 */
/*
 * width and align-self are both needed. The card is a flex column, and a
 * figure inside one sizes to its content — so the image's width:100% resolved
 * against the figure's own shrink-wrapped width and the photograph sat inset
 * in the corner of a correctly sized card.
 */
.pickleball-camp-card__media {
	width: 100%;
	align-self: stretch;
	margin: 0;
	border-radius: 0;
	overflow: hidden;
}

.pickleball-camp-card__media a {
	display: block;
	width: 100%;
}

/*
 * The ratio sits on the image, not the figure. A percentage height resolves
 * against a definite parent height, and a height that comes from the figure's
 * own aspect-ratio is not definite enough for every engine — which left the
 * photograph floating at its natural size inside a correctly sized box.
 * Several of these are portrait stock shots, so the crop has to be reliable.
 */
.pickleball-camp-card__media img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	border-radius: 0;
	object-fit: cover;
}

.pickleball-camp-card__media img {
	transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
}

.pickleball-camp-card:hover .pickleball-camp-card__media img {
	transform: scale(1.04);
}

/*
 * hero-scrim runs 0.55 at the top to 0.82 at the bottom, so bottom-anchored
 * copy stays legible whatever the stock image turns out to be — which matters
 * precisely because nobody has chosen the images yet.
 */
.pickleball-camp-card--media {
	position: relative;
}

.pickleball-camp-card--media .pickleball-camp-card__body {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	background: var(--wp--preset--gradient--hero-scrim);
}

.pickleball-camp-card--media .pickleball-camp-card__body h3,
.pickleball-camp-card--media .pickleball-camp-card__body h3 a {
	color: var(--wp--preset--color--base);
}

/*
 * !important is the only thing that works here, and not for want of trying
 * specificity first. WordPress emits its preset colour classes as
 * .has-contrast-muted-color{color:...!important}, so the muted grey the card
 * carries for its typographic state cannot be overridden any other way — and
 * grey on a photograph is unreadable. The alternative is to stop emitting the
 * colour class on the media variant, which would mean the pattern branching
 * its markup on whether an image exists.
 */
.pickleball-camp-card--media .pickleball-camp-card__body p.has-text-color {
	color: oklch(1 0 0 / 0.85) !important;
}

@media (prefers-reduced-motion: reduce) {

	.pickleball-camp-card__media img,
	.pickleball-camp-card:hover .pickleball-camp-card__media img {
		transition: none;
		transform: none;
	}
}