/* ==========================================================================
   Palm Estate - shared page sections
   --------------------------------------------------------------------------
   Sections that appear on more than one page: the homepage and About both
   carry the stats band and the team grid, the homepage and the contact page
   the contact block. Enqueued on those pages only (see functions.php). Built
   for the homepage and moved here unchanged when other pages came to reuse
   them.

   01 Stats band
   02 The team
   03 Contact block
   ========================================================================== */


/* 01 Stats band ============================================================ */

.stats,
.stats__outro {
	/* The depth of the band's arcs, in and out (see .stats__arc). */
	--stats-arc-h: clamp(1.25rem, 1.75vw, 2.75rem);
	/* The room between the figures and each curve, measured where the curves
	   are deepest, in the middle of the page. The same on both sides, so the
	   figures sit in the middle of the band; proportional, like the band. */
	--stats-gap: clamp(var(--space-lg), 6.6vw, 7rem);
}

.stats {
	background-color: var(--pe-bg-dark);
	color: var(--pe-text-on-dark);
	/* No top padding of its own: the Cream sweep inside the band supplies the
	   space above the columns, and the connector's dot lands on it. Below,
	   the arc out bulges down by its own depth before the Cream begins, so
	   the padding is the gap less that depth: Forest ends the same distance
	   under the figures as it begins above them. */
	padding-block: 0 calc(var(--stats-gap) - var(--stats-arc-h));
}

/* Only the arc INTO the band: the arc out of it (in .stats__outro) shares
   the class for its shallow height, and a margin there would collapse out of
   its wrapper and push whatever follows down by the same amount. */
.stats > .stats__arc {
	margin-bottom: var(--stats-gap);
}

/*
 * The band's arcs are shallow: a wide, gentle sweep as the design shows. The
 * homepage's market edge sets the same height on its own arcs so the two
 * read as one family. The footer keeps the component's deeper default.
 */
.stats__arc {
	--divider-h: var(--stats-arc-h);
}

/*
 * Three columns with hairline Bronze rules between them only, never outside:
 * the rule is a border on every item after the first, so nothing hangs off
 * either end.
 *
 * Each item reads numeral, figure, label down the column. The numerals are
 * decorative ordinals rather than content, so they are a CSS counter: add or
 * remove a stat in the template and they renumber themselves.
 */
.stats__list {
	counter-reset: stat;
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-xl);
	margin: 0;
}

.stats__item {
	counter-increment: stat;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-sm);
	text-align: center;
}

/* 01 / 02 / 03, above the figure: serif oldstyle numerals in Bronze, as the
   design draws them. Bronze reads at 7.45:1 on Forest. */
.stats__item::before {
	content: counter(stat, decimal-leading-zero);
	order: 1;
	color: var(--pe-accent);
	font-family: var(--font-display);
	font-size: var(--fs-md);
	font-weight: 400;
	line-height: 1;
	font-variant-numeric: oldstyle-nums;
	font-feature-settings: "onum" 1;
}

.stats__value {
	order: 2;
	margin: 0;
	font-family: var(--font-display);
	/* Two steps under the section titles, as the design has it: about 40px
	   at 1440. */
	font-size: clamp(1.75rem, 1.2rem + 1.6vw, 2.5rem);
	font-weight: 400;
	line-height: 1;
	letter-spacing: var(--ls-tight);
	/* Oldstyle figures where the face has them; ignored where it does not. */
	font-variant-numeric: oldstyle-nums;
	font-feature-settings: "onum" 1;
}

/* Cream caps beneath the figure, lighter and larger than the small caps
   elsewhere, as the design sets them; the Bronze is spent on the numeral. */
.stats__label {
	order: 3;
	color: var(--pe-text-on-dark);
	font-size: var(--fs-sm);
	font-weight: 400;
	letter-spacing: 0.12em;
}

@media (min-width: 768px) {
	/* The three columns sit inside the content, not edge to edge. */
	.stats__list {
		grid-template-columns: repeat(3, 1fr);
		gap: 0;
		max-width: 85%;
		margin-inline: auto;
	}

	.stats__item {
		padding-inline: var(--space-lg);
	}

	.stats__item + .stats__item {
		border-left: var(--hairline) solid var(--pe-rule-accent);
	}
}

/* The arc out, for a page with nothing beneath to draw its own: Forest
   sweeping down into the Cream that follows. */
.stats__outro {
	background-color: var(--pe-bg);
}


/* 02 The team ============================================================== */

/*
 * Cream section, three columns of arched portraits. Continues the Cream that
 * the market edge arcs up into, so it paints the same ground rather than
 * relying on the section above to extend.
 */
.team {
	background-color: var(--pe-bg);
	color: var(--pe-text);
	/* The room above the header is proportional, as the design draws it:
	   about 6% of the viewport, capped where the fixed scale would have it. */
	padding-block: clamp(var(--space-xl), 6vw, var(--space-3xl)) var(--space-4xl);
}

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

/* Heading left, note top right; they stack on narrow screens. */
.team__header {
	display: flex;
	flex-direction: column;
	gap: var(--space-lg);
	margin-bottom: clamp(var(--space-xl), 6vw, var(--space-3xl));
}

/* A short Bronze rule leads into the eyebrow, as a dash would. */
.team__eyebrow {
	display: flex;
	align-items: center;
	gap: var(--space-2xs);
	color: var(--pe-accent-on-light);
}

.team__eyebrow::before {
	content: "";
	width: var(--space-md);
	height: var(--hairline);
	background-color: var(--pe-accent);
}

.team__title {
	margin-top: var(--space-sm);
	font-size: var(--fs-3xl);
	line-height: var(--lh-snug);
}

.team__title em {
	font-style: italic;
}

.team__note {
	max-width: 30ch;
	color: var(--pe-text-muted);
	font-size: var(--fs-sm);
	line-height: var(--lh-loose);
}

@media (min-width: 768px) {
	.team__header {
		flex-direction: row;
		align-items: flex-start;
		justify-content: space-between;
	}

	.team__note {
		text-align: right;
	}
}

/* Grid --------------------------------------------------------------------- */

.team__grid {
	counter-reset: member;
	display: grid;
	grid-template-columns: 1fr;
	/* The gaps are a share of the content width, as the design draws them
	   (about a tenth), so the grid keeps its air at any size. */
	gap: clamp(var(--space-2xl), 6.75vw, 8rem) clamp(var(--space-xl), 6.75vw, 8rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 640px) {
	.team__grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 1024px) {
	.team__grid {
		grid-template-columns: repeat(3, 1fr);
	}
}

.team__member {
	counter-increment: member;
}

/* Portrait ----------------------------------------------------------------- */

/*
 * The arch: square at the foot, semicircular over the top. The vertical
 * radius is half the frame's width expressed against its height, which for a
 * 4:5 frame is 40% - so the curve is a true half-circle rather than an
 * ellipse, at any size.
 *
 * The offset shadow is a hard one, down and to the right, so the arch reads
 * as lifted off the Cream rather than blurred into it.
 */
.team__portrait {
	--team-arch: 50% 50% 0 0 / 40% 40% 0 0;

	position: relative;
	margin: 0;
	overflow: hidden;
	aspect-ratio: 4 / 5;
	background-color: var(--pe-surface-dark);
	background-image: linear-gradient(160deg, var(--pe-pine), var(--pe-deep));
	border-radius: var(--team-arch);
	box-shadow: var(--space-2xs) var(--space-2xs) 0 color-mix(in srgb, var(--pe-ink) 8%, transparent);
}

/* Desaturated and soft, cropped the same way on every member: the frame is
   4:5 and the crop sits high, where faces are. */
.team__image {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 20%;
	filter: grayscale(0.9) sepia(0.12) contrast(0.92);
}

/* Meta --------------------------------------------------------------------- */

.team__meta {
	margin-top: var(--space-md);
}

/* 01-06, above the name. Decorative, so it is a counter rather than content;
   it still takes the accessible accent since it is small text on Cream. */
.team__meta::before {
	content: counter(member, decimal-leading-zero);
	display: block;
	margin-bottom: var(--space-2xs);
	color: var(--pe-accent-on-light);
	font-family: var(--font-body);
	font-size: var(--fs-3xs);
	font-weight: 500;
	letter-spacing: var(--ls-caps);
	line-height: 1;
}

.team__name {
	margin: 0;
	font-family: var(--font-display);
	font-size: var(--fs-lg);
	font-weight: 400;
	line-height: var(--lh-snug);
	letter-spacing: var(--ls-normal);
}

.team__role {
	margin-top: var(--space-3xs);
	color: var(--pe-accent-on-light);
}


/* 03 Contact block =============================================================== */

/*
 * Private appointments: the Phase 08 block, on the homepage after the CTA
 * band and on the contact page after its page band. Forest, and no arc of its
 * own at the foot: the footer opens with a Forest arc down into Deep
 * (footer.php), which is the curve the design shows here.
 *
 * The note beneath the button is --pe-text-muted-on-dark, 6.12:1 on Forest.
 * The fields' own colours are measured in components.css.
 */
.contact {
	--contact-body: color-mix(in srgb, var(--pe-cream) 80%, transparent);

	background-color: var(--pe-bg-dark);
	color: var(--pe-text-on-dark);
	/* The footer's arc adds its own depth below, so the foot needs little. */
	padding-block: var(--space-section) var(--space-2xl);
}

/* Straight after the CTA band the two are one stretch of Forest, and the CTA
   already ends in generous space, so the top padding would double it. After a
   page band, the same: the band supplies the room. Tied to the neighbour
   rather than assumed, so the block keeps its breathing room anywhere else. */
.cta + .contact {
	padding-top: 0;
}

.page-band + .contact {
	padding-top: var(--space-xl);
}

.contact__inner {
	display: grid;
	gap: var(--space-2xl);
}

/* Two columns once there is room for four choices and a comfortable field
   width side by side: about 40 / 60. */
@media (min-width: 1024px) {
	.contact__inner {
		grid-template-columns: 2fr 3fr;
		column-gap: var(--space-3xl);
	}
}

/* Left: the invitation ---------------------------------------------------- */

/* A column that fills the row, so the details can drop to its foot. */
.contact__intro {
	display: flex;
	flex-direction: column;
}

.contact__title {
	margin-top: var(--space-md);
	/* Proportional to the viewport rather than the fixed scale: the column
	   it sits in is 40% of a 71% container, and at 56px "No obligation"
	   broke across two lines. About 3.4% of the viewport, capped where the
	   scale caps. */
	font-size: clamp(2rem, 0.6rem + 2.7vw, 3.5rem);
	font-weight: 300;
	line-height: var(--lh-snug);
}

/* Each line is a short phrase; it never breaks mid-phrase. */
.contact__title-light,
.contact__title-bold {
	white-space: nowrap;
}

/* Same size as the light line, only heavier. Until the display serif is
   delivered this falls back to Georgia, which has no light cut, so the light
   line renders at regular weight: the contrast is regular against bold. */
.contact__title-bold {
	font-weight: 700;
}

/* The short Bronze rule beneath the heading. Decoration, so a pseudo-element
   rather than an <hr> that would announce a break. */
.contact__title::after {
	content: "";
	display: block;
	width: var(--space-xl);
	height: var(--hairline);
	margin-top: var(--space-md);
	background-color: var(--pe-accent);
}

.contact__body {
	margin-top: var(--space-md);
	max-width: 40ch;
	color: var(--contact-body);
	line-height: var(--lh-loose);
	text-wrap: pretty;
}

.contact__details {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
	gap: var(--space-lg);
	margin-top: var(--space-xl);
}

@media (min-width: 1024px) {
	.contact__details {
		margin-top: auto;
		padding-top: var(--space-xl);
	}
}

.contact__details dd {
	margin-top: var(--space-2xs);
	color: var(--pe-text-on-dark);
	line-height: var(--lh-base);
}

.contact__details dd + dt {
	margin-top: var(--space-md);
}

.contact__details address {
	font-style: normal;
}

.contact__details a {
	color: inherit;
	text-decoration: none;
}

.contact__details a:hover {
	color: var(--pe-accent);
	text-decoration: underline;
}

/* Right: the form --------------------------------------------------------- */

/* The fields, underlines and choice boxes are the shared form components in
   components.css; this only lays them out. */
.contact__form {
	display: grid;
	gap: var(--space-xl);
	align-content: start;
}

/* Submit ------------------------------------------------------------------ */

/* Left-aligned and only as wide as its label. */
.contact__submit {
	justify-self: start;
}

.contact__button {
	min-height: 2.75rem;
	padding-inline: var(--space-lg);
}

.contact__button[aria-busy="true"] {
	cursor: progress;
	opacity: 0.6;
}

.contact__note {
	margin-top: var(--space-sm);
	color: var(--pe-text-muted-on-dark);
	font-size: var(--fs-sm);
	line-height: var(--lh-snug);
}

/* Kept in the page even when empty - never display:none - because a live
   region that only appears at the moment it has something to say is often
   not announced. It sits inside .contact__submit, so while empty it takes no
   room in the form's grid. */
.contact__status {
	color: var(--pe-text-on-dark);
	line-height: var(--lh-base);
}

.contact__status:not(:empty) {
	margin-top: var(--space-md);
}

.contact__status--invalid,
.contact__status--expired,
.contact__status--failed {
	color: var(--pe-error-on-dark);
}

.contact__status:focus {
	outline: none;
}

/* Honeypot: off-screen for people, hidden from screen readers by
   aria-hidden, skipped by tab order. Not display:none, which some bots
   check for. */
.contact__trap {
	position: absolute;
	left: -10000px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}
