/**
 * Parent theme base stylesheet.
 *
 * Brand-agnostic behaviour only: the motion system, carousel mechanics,
 * accordion transitions and the handful of WordPress core classes the
 * editor can emit. All colour, type and spacing lives in the child theme's
 * Tailwind build, which loads after this file.
 *
 * Design tokens are referenced with fallbacks so a child theme that hasn't
 * defined them still gets sane behaviour.
 *
 * Hand-written — not compiled. Keep it small.
 */

/* ---------------------------------------------------------------- motion */

/*
 * Scoped to .js (set inline in <head>) so that if JavaScript never runs,
 * nothing is left invisible.
 */
.js [data-reveal] {
	opacity: 0;
	transform: translateY(16px);
}

.js [data-reveal].is-revealed {
	opacity: 1;
	transform: none;
	transition:
		opacity 700ms var(--ease-lux, cubic-bezier(0.16, 1, 0.3, 1)) var(--reveal-delay, 0ms),
		transform 700ms var(--ease-lux, cubic-bezier(0.16, 1, 0.3, 1)) var(--reveal-delay, 0ms);
}

/*
 * Parallax with zero JavaScript. Browsers without scroll-driven animation
 * support simply render a static image, which is the intended fallback —
 * the styleguide calls for "enough to feel alive, never gimmicky".
 */
@supports (animation-timeline: view()) {
	@media (prefers-reduced-motion: no-preference) {
		[data-parallax] {
			animation: c21-parallax linear both;
			animation-timeline: view();
			animation-range: cover 0% cover 100%;
			will-change: transform;
		}

		@keyframes c21-parallax {
			from { transform: translateY(-7%); }
			to   { transform: translateY(7%); }
		}
	}
}

@media (prefers-reduced-motion: reduce) {
	.js [data-reveal],
	.js [data-reveal].is-revealed {
		opacity: 1;
		transform: none;
		transition: none;
	}

	[data-parallax] {
		animation: none;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* --------------------------------------------------- text over photos */

/*
 * The muted text colour is a device for flat surfaces. Over a photograph it
 * collapses: measured against a real hero image, muted body text reached a
 * contrast ratio of 2.2 where WCAG AA wants 4.5, and even a heavy 55%
 * darkening overlay only got it to 3.3.
 *
 * So inside a section whose text sits on an image, the muted register is
 * folded into the full foreground colour and hierarchy is carried by size
 * and spacing instead. Applied by the section template, not by hand.
 */
.c21-on-photo {
	--ink-muted: var(--ink);
}

/* ----------------------------------------------------- image focal point */

/*
 * Which part of a cropped photograph stays in frame, chosen per section by
 * the content manager.
 *
 * An attribute rather than an `object-{position}` utility, for the same
 * reason spacing and column counts are attributes: the value is editorial,
 * so the class name would only ever exist as a runtime-composed string that
 * Tailwind's scanner cannot see, and the utility would be missing from the
 * build. Lives here rather than in the child theme because it is behaviour,
 * not brand.
 */
[data-focus="top"]    { object-position: top; }
[data-focus="center"] { object-position: center; }
[data-focus="bottom"] { object-position: bottom; }
[data-focus="left"]   { object-position: left; }
[data-focus="right"]  { object-position: right; }

/* ------------------------------------------------- card collections */

/*
 * One columns setting drives both layouts.
 *
 * The section writes --cols-xs/sm/md/lg as inline custom properties; each
 * breakpoint then rebinds a single --cols, which grid and carousel both
 * read. That means the per-breakpoint choice never appears as a class
 * string, so Tailwind needs no safelist for it — the old v3 config carried
 * ~120 entries to solve exactly this.
 */
.c21-cards {
	--cols: var(--cols-xs, 1);
	--card-gap: 1.5rem;
	/* A sliver of the next card on small screens signals that it scrolls. */
	--peek: 0.88;
}

@media (min-width: 40rem) {
	.c21-cards { --cols: var(--cols-sm, 2); --peek: 1; --card-gap: 2rem; }
}

@media (min-width: 48rem) {
	.c21-cards { --cols: var(--cols-md, 3); }
}

@media (min-width: 64rem) {
	.c21-cards { --cols: var(--cols-lg, 3); }
}

.c21-cards[data-layout="grid"] {
	display: grid;
	gap: var(--card-gap);
	grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
}

.c21-cards[data-layout="carousel"] {
	display: flex;
	gap: var(--card-gap);
	/*
	 * Both axes are stated. A scroll container may not have one axis
	 * `visible` and the other not, so `overflow-x: auto` alone makes the
	 * browser compute overflow-y to `auto` as well — and the cards' own
	 * [data-reveal] start position (translateY(16px)) is enough vertical
	 * overflow to make the strip scroll up and down under the cursor.
	 * Measured on the homepage testimonials: scrollHeight 1328 vs
	 * clientHeight 1312, exactly the 16px of the reveal offset.
	 */
	overflow: auto hidden;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	overscroll-behavior-x: contain;
	/* Let cards bleed to the viewport edge while staying aligned. */
	scroll-padding-inline-start: 0;
}

.c21-cards[data-layout="carousel"]::-webkit-scrollbar {
	display: none;
}

.c21-cards[data-layout="carousel"] > * {
	flex: 0 0 calc((100% - (var(--cols) - 1) * var(--card-gap)) / var(--cols) * var(--peek));
	scroll-snap-align: start;
}

/* -------------------------------------------------------------- carousel */

[data-carousel-track] {
	display: flex;
	/* Cross axis locked — see the note on .c21-cards[data-layout="carousel"]. */
	overflow: auto hidden;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	overscroll-behavior-x: contain;
}

[data-carousel-track]::-webkit-scrollbar {
	display: none;
}

[data-carousel-track] > * {
	flex: 0 0 auto;
	scroll-snap-align: start;
}

/* Controls are dead weight until the script wires them up. */
[data-carousel] [data-carousel-controls] {
	display: none;
}

[data-carousel].is-interactive [data-carousel-controls] {
	display: flex;
}

[data-carousel-prev][disabled],
[data-carousel-next][disabled] {
	opacity: 0.3;
	pointer-events: none;
}

/* ------------------------------------------------------------- accordion */

/*
 * The FAQ is a native <details name="..."> group: exclusive open/close with
 * no JavaScript. These rules add the smooth height transition where the
 * browser supports it.
 */
@supports (interpolate-size: allow-keywords) {
	:root {
		interpolate-size: allow-keywords;
	}

	details::details-content {
		block-size: 0;
		overflow: hidden;
		transition:
			block-size 400ms var(--ease-lux, cubic-bezier(0.16, 1, 0.3, 1)),
			content-visibility 400ms allow-discrete;
	}

	details[open]::details-content {
		block-size: auto;
	}
}

details > summary {
	cursor: pointer;
	list-style: none;
}

details > summary::-webkit-details-marker {
	display: none;
}

/* "+" becomes "×" on open — a rotation, not an icon swap. */
.c21-accordion__icon {
	display: inline-block;
	font-size: 1.25rem;
	line-height: 1;
	transition: transform 400ms var(--ease-lux, cubic-bezier(0.16, 1, 0.3, 1));
}

details[open] > summary .c21-accordion__icon {
	transform: rotate(45deg);
}

/* ----------------------------------------------------------- wp core bits */

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.screen-reader-text:focus {
	position: static;
	width: auto;
	height: auto;
	margin: 0;
	clip-path: none;
}

.alignleft  { float: left;  margin-inline-end: 1.5rem; }
.alignright { float: right; margin-inline-start: 1.5rem; }
.aligncenter { display: block; margin-inline: auto; }

.wp-caption { max-width: 100%; }

.wp-caption-text,
figcaption {
	font-size: 0.875rem;
	color: var(--ink-muted, #8C8378);
}
