/*
Theme Name: Gemstone
Theme URI: https://example.com/gemstone
Author: Gemstone Properties Group
Author URI: https://example.com
Description: Lightweight native WordPress block theme for Gemstone Properties Group. Design tokens live in theme.json; layout lives in templates; shared sections live in patterns. One public page, two hidden funnels. No page builders, no plugins.
Requires at least: 6.5
Tested up to: 7.0
Requires PHP: 8.0
Version: 1.5.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: gemstone
Tags: block-theme, full-site-editing, real-estate, one-column, accessibility-ready
*/

/*
 * ============================================================================
 * Only rules theme.json genuinely cannot express belong here.
 * Every value references a token — never a raw hex, px font size or font name.
 * Mobile-first: base rules are the phone layout, media queries add the desktop.
 * ============================================================================
 *
 * CONTENTS
 * TYPOGRAPHY IS A BRAND RULE, NOT A PREFERENCE.
 *
 * From Vylla's "Font Usage" guide:
 *
 *   Headline      Questrial Regular — REGULAR WEIGHT ONLY, sentence case.
 *                 Never all caps, never another weight.
 *   Sub-headline  Libre Baskerville Regular — never all caps.
 *   Body copy     Roboto Light.
 *   Accent        Roboto Bold in all caps, the alternative sub-headline.
 *
 * theme.json sets weight 400 on the heading ELEMENTS, so h1–h6 are safe. Any
 * other element that borrows the heading family — a step number, an accordion
 * summary, a fieldset legend — inherits the root body weight of 300 instead,
 * which is a brand violation the eye does not reliably catch. Every rule that
 * sets the heading family therefore states `font-weight: 400` explicitly.
 * If you add one, state it there too.
 *
 *   1. Base
 *   2. Utilities        .gem-eyebrow, .gem-measure, .gem-icon-circle
 *   3. Buttons          secondary / outlined / inverted variants
 *   4. Cards
 *   5. Forms            placeholder markup only — real forms are connected in a later phase
 *   6. Accordion        core/details
 *   7. Comparison table responsive reflow, one source of truth
 *   8. Portrait + avatar
 *   9. Header
 *  10. Footer
 *  11. Motion + focus
 */

/* == 1. Base ============================================================== */

/*
 * The public page is a single scrolling page navigated by anchors, so ease the
 * jumps. The reduced-motion block at the end of this file turns this off for
 * anyone who has asked for less movement.
 */
html {
	scroll-behavior: smooth;
}

/* Anchor targets land clear of the section edge rather than flush against it. */
:target {
	scroll-margin-block-start: var(--wp--preset--spacing--40);
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-wrap: pretty;
}

:where(h1, h2, h3) {
	text-wrap: balance;
}

/* Images never overflow their column and never cause layout shift. */
img {
	max-width: 100%;
	height: auto;
}

/*
 * <strong> and <b> must be 700, stated explicitly.
 *
 * The browser default is `font-weight: bolder`, which is RELATIVE, and the CSS
 * spec maps bolder from a 300 parent to 400 — not 700. Body copy here is Roboto
 * Light 300, so every <strong> on the site was computing to 400, and since the
 * theme ships only 300 and 700 the browser substituted the nearest face. The
 * result: emphasis rendered identically to body text, invisibly, everywhere.
 *
 * Roboto Bold is the brand's accent face, so 700 is also the correct answer
 * rather than merely the working one.
 */
strong,
b {
	font-weight: 700;
}

/*
 * STANDFIRST — the supporting line directly under a heading.
 *
 * This is Vylla's "Sub Headline" role, and Libre Baskerville Regular is the
 * face their guide assigns to it. Their own example page shows exactly this
 * shape: Questrial headline, then one serif sentence beneath it, then Roboto
 * Light body underneath that.
 *
 * Never all caps — the guide forbids it for this face specifically.
 *
 * Deliberately scoped to the line under an h1 rather than every intro on the
 * site: a serif on every section standfirst repaints all 13 pages and pulls
 * away from the designer's frames, which show those lines in the sans.
 */
.gem-standfirst {
	font-family: var(--wp--preset--font-family--subhead);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.6;
	text-transform: none;
	color: var(--wp--preset--color--grey);
}

/* == 2. Utilities ========================================================= */

/*
 * Small uppercase label. The single approved use of uppercase — buttons and
 * headings stay sentence case so the tone reads calm rather than shouty.
 */
/*
 * Section eyebrow, marked with the brand facet.
 *
 * The facet is the same rotated square used as the station marker on the steps
 * rail, so the one device recurs wherever the page is announcing a new part of
 * itself. It also gives the eyebrow a foothold: as bare letterspaced grey it
 * was the lightest thing in the section and read as a stray caption above the
 * heading rather than a label belonging to it.
 *
 * Inline-block rather than absolute so it centres with the text on the centred
 * sections and sits flush left on the split ones, with no variant to maintain.
 */
.gem-eyebrow {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--grey);
}

.gem-eyebrow::before {
	content: "";
	display: inline-block;
	inline-size: 0.375rem;
	block-size: 0.375rem;
	margin-inline-end: 0.5rem;
	vertical-align: 0.08em;
	background-color: var(--wp--preset--color--gold);
	transform: rotate(45deg);
}

/*
 * Inline label variant — a field label or a credential line, not a section
 * announcement. The facet marks where a new part of the page begins; on a
 * "Phone" label already sitting beside an icon chip it is one mark too many,
 * and repeating it down a contact list turns a signature into wallpaper.
 */
.gem-eyebrow--plain::before {
	content: none;
}

.gem-eyebrow.has-text-color {
	color: inherit;
}

/*
 * Second sentence of a two-part headline, in gold. Block display keeps the
 * phrase whole instead of letting it break mid-clause — and does it without a
 * hardcoded <br>, which would break at the wrong point on a phone.
 */
.gem-accent {
	display: block;
	color: var(--wp--custom--tint--gold-deep);
}

/* Ebook cover: transparent 3D render, so drop-shadow filter, no radius or box-shadow. */
.gem-ebook {
	max-inline-size: 30rem;
	margin-inline: auto;
}

.gem-ebook img {
	display: block;
	inline-size: 100%;
	block-size: auto;
	filter: drop-shadow(0 18px 28px color-mix(in srgb, var(--wp--preset--color--charcoal) 22%, transparent));
}

/*
 * Guide cover, built from the design system.
 *
 * A proposal alternative to the supplied flat render. Uses the real brand fonts
 * and palette so it cannot drift from the site, stays sharp at any size, and
 * keeps the title as editable text.
 */
.gem-cover {
	position: relative;
	display: block;
	inline-size: 100%;
	max-inline-size: 24rem;
	aspect-ratio: 3 / 4;
	margin-inline: auto;
	border-radius: 2px var(--wp--custom--radius--small) var(--wp--custom--radius--small) 2px;
	background-color: var(--wp--preset--color--cream);
	box-shadow: var(--wp--preset--shadow--lifted);
	overflow: hidden;
}

/* The bound edge — what reads as a book rather than a poster. */
.gem-cover__spine {
	position: absolute;
	inset-block: 0;
	inset-inline-start: 0;
	inline-size: 1.5rem;
	background-color: var(--wp--preset--color--charcoal);
}

.gem-cover__spine::after {
	content: "";
	position: absolute;
	inset-block: 0;
	inset-inline-end: -0.375rem;
	inline-size: 0.375rem;
	background: linear-gradient(
		to right,
		rgba(49, 49, 59, 0.18),
		rgba(49, 49, 59, 0)
	);
}

.gem-cover__face {
	position: absolute;
	inset: 0;
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--40)
		var(--wp--preset--spacing--40) calc(1.5rem + var(--wp--preset--spacing--40));
	display: grid;
	grid-template-rows: auto 1fr auto;
	align-items: center;
	text-align: center;
	container-type: inline-size;
}

/* Title, rule and subtitle are one grid item, centred in the space between. */
.gem-cover__block {
	align-self: center;
}

.gem-cover__eyebrow {
	margin: 0;
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--wp--custom--tint--gold-text);
}

.gem-cover__title {
	margin: 0;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: clamp(1.5rem, 4.4cqi, 2rem);
	line-height: 1.15;
	letter-spacing: -0.01em;
	color: var(--wp--preset--color--charcoal);
	text-wrap: balance;
}

.gem-cover__rule {
	display: block;
	inline-size: 3rem;
	block-size: 2px;
	margin: var(--wp--preset--spacing--30) auto;
	background-color: var(--wp--preset--color--gold);
}

.gem-cover__sub {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
	color: var(--wp--preset--color--grey);
	text-wrap: pretty;
}

.gem-cover__mark {
	display: block;
	margin: 0 auto var(--wp--preset--spacing--30);
	color: var(--wp--custom--tint--gold-deep);
}

.gem-cover__mark svg {
	inline-size: 2rem;
	block-size: 2rem;
}

.gem-cover__foot {
	margin: 0;
	font-size: var(--wp--preset--font-size--label);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--grey);
}

/* Caps line length for comfortable reading of long prose. */
.gem-measure {
	max-width: var(--wp--custom--measure--prose);
	margin-inline: auto;
}

/*
 * Circular icon chip. Icons are inline SVG, not font glyphs — the client's
 * Questrial/Roboto cuts contain no arrow or checkmark glyphs.
 */
.gem-icon-circle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	inline-size: 3.25rem;
	block-size: 3.25rem;
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--custom--tint--gold-subtle);
	color: var(--wp--custom--tint--gold-deep);
	flex: 0 0 auto;
}

.gem-icon-circle svg {
	inline-size: 1.625rem;
	block-size: 1.625rem;
	display: block;
}

/*
 * A soft ring around the chip. Gives the icon presence on a large card without
 * making the gold heavier, which would compete with the call-to-action button.
 */
.gem-cards__item .gem-icon-circle {
	box-shadow: 0 0 0 6px var(--wp--custom--tint--gold-subtle);
}

/* Small check used in benefit lists. Green is reserved for confirmation only. */
.gem-icon-check {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	inline-size: 1.5rem;
	block-size: 1.5rem;
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--custom--tint--gold-soft);
	color: var(--wp--custom--tint--gold-deep);
	flex: 0 0 auto;
	margin-block-start: 0.125rem;
}

.gem-icon-check svg {
	inline-size: 0.875rem;
	block-size: 0.875rem;
	display: block;
}

/*
 * State chips: affirmative and neutral.
 *
 * Greenery is the brand's success colour and this is the one place it belongs —
 * the "keeps your home?" answer a distressed reader scans for. Brand Greenery
 * (#6ABE66) measures only 2.11:1 on a light chip, so as with gold the brand
 * colour tints the fill and a darkened variant draws the mark: green-deep
 * measures 3.74:1, clearing the 3:1 minimum for a graphic.
 *
 * The negative is deliberately neutral, not red. Nothing on these pages should
 * read as an alarm.
 */
.gem-state {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	inline-size: 1.75rem;
	block-size: 1.75rem;
	border-radius: var(--wp--custom--radius--pill);
	flex: 0 0 auto;
}

.gem-state svg {
	inline-size: 1rem;
	block-size: 1rem;
	display: block;
}

.gem-state--yes {
	background-color: var(--wp--custom--tint--green-subtle);
	color: var(--wp--custom--tint--green-deep);
}

.gem-state--no {
	background-color: var(--wp--custom--tint--cream-deep);
	color: var(--wp--preset--color--grey);
}

/* Inline arrow on text links, sized to the surrounding text. */
.gem-arrow svg {
	inline-size: 0.875em;
	block-size: 0.875em;
	vertical-align: -0.0625em;
	margin-inline-start: 0.375em;
}

/*
 * Cards gain a gold edge that draws in on hover. The card already lifts; this
 * gives the movement a direction and ties it to the brand.
 */
.gem-cards__item,
.wp-block-column > .gem-card {
	position: relative;
	overflow: hidden;
}

/* Prose inside an about card, for slots that have been written. Matches the
   card grids elsewhere rather than introducing a third heading scale. */
.gem-card__title {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.25;
	color: var(--wp--preset--color--charcoal);
}

.gem-card__copy {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.65;
	color: var(--wp--preset--color--grey);
}

.gem-card__copy:last-child {
	margin-block-end: 0;
}

.gem-cards__item::after,
.wp-block-column > .gem-card::after {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	block-size: 2px;
	background-color: var(--wp--preset--color--gold);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 0.25s ease;
}

.gem-cards__item:hover::after,
.wp-block-column > .gem-card:hover::after {
	transform: scaleX(1);
}

@media (prefers-reduced-motion: reduce) {
	.gem-cards__item::after,
	.wp-block-column > .gem-card::after {
		transition: none;
	}
}

/* == 3. Buttons =========================================================== */

/*
 * theme.json styles the primary button. These are the three secondary variants
 * from the design system board, expressed as block styles so authors pick them
 * from the editor rather than writing CSS.
 */

.wp-block-button.is-style-secondary > .wp-block-button__link {
	background-color: var(--wp--custom--tint--cream-deep);
	color: var(--wp--preset--color--charcoal);
	box-shadow: none;
}

.wp-block-button.is-style-secondary > .wp-block-button__link:hover,
.wp-block-button.is-style-secondary > .wp-block-button__link:focus {
	background-color: var(--wp--preset--color--charcoal);
	color: var(--wp--preset--color--cream);
}

.wp-block-button.is-style-inverted > .wp-block-button__link {
	background-color: var(--wp--preset--color--charcoal);
	color: var(--wp--preset--color--cream);
}

.wp-block-button.is-style-inverted > .wp-block-button__link:hover,
.wp-block-button.is-style-inverted > .wp-block-button__link:focus {
	background-color: var(--wp--custom--tint--charcoal-deep);
	color: var(--wp--preset--color--white);
}

.wp-block-button.is-style-outlined > .wp-block-button__link {
	background-color: transparent;
	color: var(--wp--preset--color--charcoal);
	box-shadow: inset 0 0 0 1px var(--wp--custom--line--strong);
}

.wp-block-button.is-style-outlined > .wp-block-button__link:hover,
.wp-block-button.is-style-outlined > .wp-block-button__link:focus {
	background-color: var(--wp--preset--color--charcoal);
	color: var(--wp--preset--color--cream);
	box-shadow: inset 0 0 0 1px var(--wp--preset--color--charcoal);
}

/* Full-width button on small screens — thumb-friendly for QR-code visitors. */
@media (max-width: 599px) {
	.wp-block-buttons:not(.is-nowrap) > .wp-block-button {
		width: 100%;
	}

	.wp-block-buttons:not(.is-nowrap) > .wp-block-button > .wp-block-button__link {
		width: 100%;
		text-align: center;
	}
}

/* == 3a. Layout density =================================================== */

/*
 * HERO — copy left, Gerald right.
 *
 * The section claims most of the fold so it is not a short text column stranded
 * above whitespace, and the two columns centre against each other rather than
 * hanging from the top: at 56/44 the copy stack is shorter than the portrait, and
 * top-aligning left the headline floating beside a chin.
 *
 * Below 782px WordPress stacks the columns and §mobile order below keeps the
 * headline first — a visitor should learn what the page is before meeting a
 * photograph of a stranger.
 */
@media (min-width: 782px) {
	.gem-hero {
		/*
		 * 80vh fills the fold on a normal laptop, but unbounded it also means a
		 * very tall window gets a hero of pure whitespace with the content
		 * stranded in the middle. The cap keeps it generous without running away.
		 */
		min-block-size: min(76vh, 40rem);
		display: flex;
		align-items: center;
	}

	/*
	 * .gem-hero is display:flex for the vertical centring, which makes the body a
	 * flex item that would otherwise size to its CONTENT. Stretching it back to
	 * full width keeps its left edge on the same grid as every section below.
	 */
	.gem-hero > .gem-hero__body.alignwide {
		inline-size: 100%;
	}

	/*
	 * The measure lives on the COPY COLUMN's children, not on the hero body.
	 * When it sat on `.gem-hero__body > *` it capped the columns block itself,
	 * which is the thing that has to stay full width for the portrait to have a
	 * column to sit in at all.
	 */
	.gem-hero__copy > * {
		max-inline-size: 38rem;
	}

	/*
	 * The text leads, 56/44.
	 *
	 * At a straight 50/50 the portrait rendered 612px wide and filled 30% of the
	 * whole hero. A headshot at that scale stops being a welcome and starts being
	 * a stare, and it left the headline looking like a caption to the photograph
	 * rather than the other way round.
	 */
	.gem-hero .wp-block-column:first-child { flex-basis: 56% !important; }
	.gem-hero .wp-block-column:last-child  { flex-basis: 44% !important; }
}

/*
 * THE PORTRAIT AND ITS GOLD PANEL.
 *
 * Built to the client's frame: a square-cornered photograph with a soft shadow,
 * and a flat gold panel offset down and to the right, emerging from behind the
 * lower-right corner. The panel is drawn as a pseudo-element rather than a
 * second image so it costs no request and cannot fall out of alignment.
 *
 * PERCENTAGES INSIDE, REM OUTSIDE. The panel's top and inline-start edges are
 * percentages so the overlap keeps its proportion as the photo scales; the two
 * edges that stick OUT are fixed rem, because an overhang in percent grows with
 * the photo and starts colliding with the copy on a wide screen.
 *
 * The photo is capped at 21rem — 336px at the frame's 1440px width, which is
 * what the frame draws. It is a headshot, not a hero image: past roughly 400px
 * it stops introducing someone and starts looming, which is the exact note that
 * shrank it from 50/50 to 56/44.
 *
 * SQUARE CORNERS ARE DELIBERATE and are the one place on the site that departs
 * from the 8px rounding, because the frame is a rectangle-behind-rectangle
 * composition — rounding either box breaks the offset it is built on.
 */
.gem-hero__figure {
	position: relative;
	display: block;
	margin: 0;
	max-inline-size: 21rem;
}

.gem-hero__figure::before {
	content: "";
	position: absolute;
	inset-block-start: 16%;
	inset-inline-start: 24%;
	inset-block-end: -1.25rem;
	inset-inline-end: -1.25rem;
	background-color: var(--wp--custom--tint--gold-frame);
}

/*
 * z-index on the PHOTO, not a negative one on the panel. `z-index: -1` on the
 * pseudo-element would drop it behind the section's cream background as well as
 * behind the photo, which paints it out of existence.
 */
.gem-hero__figure img {
	position: relative;
	z-index: 1;
	display: block;
	inline-size: 100%;
	block-size: auto;
	box-shadow: var(--wp--custom--shadow--soft);
}

@media (min-width: 782px) {
	/* Sits to the right of its column so the gold overhang lands on the same
	   grid edge the header and the sections below align to. */
	.gem-hero__media .gem-hero__figure {
		margin-inline-start: auto;
		margin-inline-end: 1.25rem;
	}
}

/*
 * On a phone the photo is centred and held well short of full width. Full-bleed
 * it reads as a magazine cover rather than an introduction, and the overhang
 * needs room on both sides or it hits the section padding.
 */
@media (max-width: 781px) {
	.gem-hero__figure {
		max-inline-size: min(18rem, 68vw);
		margin-inline: auto;
		/*
		 * Centres the COMPOSITION, not the photograph. auto margins centre the
		 * photo, but the panel only sticks out on one side, so the pair reads as
		 * sitting left of centre. Half the overhang back the other way fixes the
		 * optics; transform, so it costs nothing in layout.
		 */
		transform: translateX(-0.375rem);
	}

	.gem-hero__figure::before {
		inset-block-end: -0.75rem;
		inset-inline-end: -0.75rem;
	}
}

/*
 * Mobile order: headline first, portrait second.
 *
 * The portrait used to be pulled above the text. The reasoning was that a face
 * is a fast trust signal — but on a phone it meant a reader met a photograph of
 * a stranger before learning what the page was. The header already carries the
 * Gemstone mark, so identity is established; what the visitor needs next is
 * "trusted real estate guidance in Houston", then the face, then the action.
 *
 * It also puts the DOM order and the visual order back in agreement, which is
 * what a screen reader and a keyboard follow.
 */
@media (max-width: 781px) {
	.gem-hero .wp-block-columns {
		display: flex;
		flex-direction: column;
	}
}

/*
 * CARD GRIDS — 3 across at desktop, 2 at tablet, 1 on a phone.
 *
 * WordPress columns collapse straight from N to 1 at 782px, which wastes the
 * tablet range. This overrides that with a wrapping flex row so the count steps
 * down properly, and lets every card grow to fill its track.
 */
.gem-grid-3 > .wp-block-columns,
.wp-block-columns.gem-grid-3 {
	flex-wrap: wrap !important;
}

@media (min-width: 600px) and (max-width: 1023px) {
	.gem-grid-3.wp-block-columns > .wp-block-column {
		flex-basis: calc(50% - var(--wp--preset--spacing--30)) !important;
		flex-grow: 1;
	}
}

@media (max-width: 599px) {
	.gem-grid-3.wp-block-columns > .wp-block-column {
		flex-basis: 100% !important;
	}
}

/*
 * Two-column content blocks (About, hero, contact) left-align their text.
 * Centred text belongs to single-column intro headers only.
 */
.gem-split .wp-block-column > * {
	text-align: start;
}

/* == 3b. Section rhythm =================================================== */

/*
 * VERTICAL RHYTHM — owned here, not by each pattern.
 *
 * Every section used to declare its own padding inline. Four different values
 * drifted into use plus two asymmetric sections, so the gap between one pair of
 * sections was 56px and the next was 96px, with no rule behind the difference.
 * Padding is now a property of the section system, and a pattern cannot set it.
 *
 * There are exactly two rhythms and two joins:
 *
 *   .gem-section              96px — the default, anything with a heading and body
 *   .gem-section--band        56px — slim single-purpose strips with one idea
 *   .gem-section--leads       tight bottom, for a section that flows into the next
 *   .gem-section--continues   no top, for the section that continues the previous
 *
 * A leads/continues pair reads as one unit from outside — 96px above, 96px
 * below — with a closer 40px join in the middle.
 */
.gem-section {
	padding-block: var(--wp--preset--spacing--60);
}

.gem-section--band {
	padding-block: var(--wp--preset--spacing--50);
}

.gem-section--leads {
	padding-block-end: var(--wp--preset--spacing--40);
}

.gem-section--continues {
	padding-block-start: 0;
}

/*
 * SURFACE CADENCE
 *
 * The page alternates between two surfaces so each section reads as its own
 * band: cream (the brand background) and white (where cards need to lift off
 * the page). The gold tint is reserved for the closing CTA so it keeps its
 * signal value, and charcoal is the footer alone.
 *
 * Each pattern declares its own surface, which means a reordering can put two
 * identical surfaces side by side — the sections then merge into one
 * undifferentiated block. Rather than rely on authors remembering the cadence,
 * these rules repair a collision automatically: a section that would repeat the
 * previous surface flips to the other one.
 *
 * `.gem-section--continues` opts out, for the case where two sections are
 * deliberately one unit — a page intro and the table it introduces should share
 * a surface, not alternate.
 *
 * THE REPAIR IS ONE DEEP, AND CANNOT CHAIN. These selectors match the class a
 * section DECLARES, and CSS gives no way to match what a previous rule painted
 * it. So cream+cream+white left the flipped second section rendering white
 * directly against a third that declared white, and the two merged into a
 * single undifferentiated block — which is precisely the fault the cadence
 * exists to prevent. It put ~190px of empty white between the service cards and
 * the FAQ on the home page, and the same again on the pre-foreclosure funnel.
 *
 * The fix is that every composition in bin/provision.php now alternates by
 * construction; this stays as a net for a single accidental collision, not as
 * the mechanism. When adding a section to a page, check the surface it declares
 * against its new neighbours rather than assuming this will sort it out.
 *
 * `!important` is required because WordPress emits its own
 * `.has-*-background-color{background-color:…!important}` presets; the extra
 * class in these selectors is what wins the specificity tie.
 */

/*
 * Sections must butt directly against each other.
 *
 * WordPress applies a block gap to every child of a constrained layout, so two
 * adjacent full-bleed sections were separated by a ~20px gap that let the body
 * background show through as a thin cream stripe across the page. It looked
 * like a rendering fault rather than spacing, and appeared between almost every
 * section on every page.
 *
 * Each section owns its own vertical padding, so the gap has nothing to do.
 * Two classes deep to outrank WordPress's `:root :where(.is-layout-constrained) > *`.
 */
.gem-section + .gem-section,
.wp-site-blocks .gem-section {
	margin-block-start: 0;
	margin-block-end: 0;
}

/*
 * Same at the page level: the header, main and footer are siblings inside
 * .wp-site-blocks and were each picking up the block gap, which left the same
 * cream stripe directly under the header and directly above the footer.
 * All three own their padding.
 */
.wp-site-blocks > * {
	margin-block-start: 0;
	margin-block-end: 0;
}

.gem-section.has-cream-background-color
	+ .gem-section.has-cream-background-color:not(.gem-section--continues) {
	background-color: var(--wp--preset--color--white) !important;
}

.gem-section.has-white-background-color
	+ .gem-section.has-white-background-color:not(.gem-section--continues) {
	background-color: var(--wp--preset--color--cream) !important;
}

/*
 * A section directly after the accent band must not repeat cream, or the band
 * loses its edge on the lower side.
 */
.gem-section--accent + .gem-section.has-cream-background-color:not(.gem-section--continues) {
	background-color: var(--wp--preset--color--white) !important;
}

/* == 4. Cards ============================================================= */

/*
 * A card carries a hairline as well as its shadow.
 *
 * The surface cadence puts card grids on white as often as on cream, and a
 * white card on a white section had only a 6%-opacity ambient shadow to define
 * it — at a glance the grid read as loose text rather than a set of objects.
 * The inset hairline gives every card an actual edge on either surface without
 * resorting to a heavier shadow, which would look pressed onto the page.
 */
.gem-card {
	background-color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--medium);
	box-shadow: var(--wp--preset--shadow--soft), var(--wp--preset--shadow--inset-hairline);
	transition: box-shadow 0.2s ease, transform 0.2s ease;
}

/*
 * Equal-height cards in a columns block.
 *
 * WordPress stretches the column wrappers to match the tallest, but the card
 * inside keeps its own content height — so a card with two lines of copy sits
 * shorter than its neighbour with three. Making the column a flex container and
 * letting the card grow fixes the ragged bottom edge without touching markup.
 */
.wp-block-columns:not(.is-not-stacked-on-mobile) > .wp-block-column,
.wp-block-columns > .wp-block-column {
	display: flex;
	flex-direction: column;
}

.wp-block-column > .gem-card {
	flex: 1 1 auto;
}

/* Only cards that are themselves links get the lift. */
a.gem-card:hover,
.gem-card:has(> a:hover) {
	/* Restate the hairline — a bare `lifted` would drop the edge on hover. */
	box-shadow: var(--wp--preset--shadow--lifted), var(--wp--preset--shadow--inset-hairline);
	transform: translateY(-2px);
}

/*
 * Auto-fitting card grid. Cards claim a minimum comfortable width and the
 * browser decides the column count — three across on desktop, two on tablet,
 * one on a phone — with no breakpoint to maintain when items are added.
 */
.gem-grid {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: var(--wp--preset--spacing--30);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}

.gem-grid__item {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--30);
}

.gem-grid__title {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.3;
	margin: 0 0 0.375rem;
	color: var(--wp--preset--color--charcoal);
}

.gem-grid__copy {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--grey);
}

/* == 4b. Section components =============================================== */

/*
 * Shared auto-fitting grid. Cards claim a comfortable minimum and the browser
 * picks the column count — three at desktop, two at tablet, one on a phone —
 * with no breakpoint to maintain when an item is added or removed.
 */
.gem-cards,
.gem-steps,
.gem-signs,
.gem-check,
.gem-creds {
	list-style: none;
	margin: 0;
	padding: 0;
}

.gem-cards {
	display: grid;
	gap: var(--wp--preset--spacing--30);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
}

.gem-cards__item {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30);
}

/* Seven cards: last one spans the row on two columns, centres on three. */
@media (min-width: 42rem) {
	.gem-cards--seven {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.gem-cards--seven > :last-child {
		grid-column: 1 / -1;
	}
}

@media (min-width: 64rem) {
	.gem-cards--seven {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.gem-cards--seven > :last-child {
		grid-column: 2;
	}
}

.gem-cards__title {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--x-large);
	line-height: 1.3;
	color: var(--wp--preset--color--charcoal);
	margin: 0;
}

.gem-cards__copy {
	margin: 0;
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--grey);
}

/*
 * NUMBERED STEPS — a progression rail, not three columns of text.
 *
 * These are genuinely ordered, so the structure should say so. Previously each
 * step carried its own short hairline, which left three disconnected blocks
 * floating in the section with nothing tying them together. Each step now hangs
 * from a gold track with a facet marker at its station, so the eye travels
 * along one line from first to last.
 *
 * The marker is a rotated square rather than a dot: it echoes the Gemstone mark
 * and reads as a fixed point on a route instead of a bullet.
 *
 * At three columns the track bridges the grid gap so the line runs unbroken
 * across the row. Below that the grid wraps, and a bridged track would overhang
 * the end of a row into empty space, so each step keeps its own segment.
 */
.gem-steps {
	--gem-steps-gap: var(--wp--preset--spacing--40);
	--gem-steps-marker: 0.625rem;

	display: grid;
	gap: var(--wp--preset--spacing--50) var(--gem-steps-gap);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}

.gem-steps__item {
	position: relative;
	padding-block-start: var(--wp--preset--spacing--40);
}

.gem-steps__item::before {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	inline-size: 100%;
	block-size: 2px;
	background-color: var(--wp--custom--tint--gold-soft);
}

/* Centred on the 2px track: half the marker up, plus half the track down. */
.gem-steps__item::after {
	content: "";
	position: absolute;
	inset-block-start: calc((var(--gem-steps-marker) / -2) + 1px);
	inset-inline-start: 0;
	inline-size: var(--gem-steps-marker);
	block-size: var(--gem-steps-marker);
	background-color: var(--wp--preset--color--gold);
	transform: rotate(45deg);
}

@media (min-width: 64rem) {
	.gem-steps__item:not(:last-child)::before {
		inline-size: calc(100% + var(--gem-steps-gap));
	}
}

.gem-steps__num {
	display: block;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--xx-large);
	line-height: 1;
	color: var(--wp--custom--tint--gold-deep);
	margin-block-end: var(--wp--preset--spacing--20);
}

.gem-steps__title {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--x-large);
	line-height: 1.3;
	color: var(--wp--preset--color--charcoal);
	margin: 0 0 0.5rem;
}

.gem-steps__copy {
	margin: 0;
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--grey);
}

/*
 * VERTICAL TIMELINE — the foreclosure stages.
 *
 * The same rail and facet marker as .gem-steps, turned through 90°. A
 * horizontal rail cannot carry this content: each stage needs several lines of
 * explanation plus a statement of what the reader can still do. Vertical also
 * means the phone layout is the desktop layout with less width, which matters
 * on the one page most likely to be read standing at a front door.
 *
 * The rail is drawn between markers rather than behind them: it starts below
 * each marker and runs into the gap, so the last stage terminates the line
 * instead of trailing off into empty space.
 */
.gem-timeline {
	--gem-timeline-marker: 0.625rem;
	--gem-timeline-gap: var(--wp--preset--spacing--50);

	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: var(--gem-timeline-gap);
}

.gem-timeline__item {
	/* No rail and no marker: the frame runs the stages as plain left-aligned
	   blocks flush with the column, so there is nothing left to indent past.
	   The gold stage label is what carries the sequence now. */
	position: relative;
	padding-inline-start: 0;
}

.gem-timeline__stage {
	display: block;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wp--custom--tint--gold-text);
	margin-block-end: 0.375rem;
}

.gem-timeline__title {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--x-large);
	line-height: 1.3;
	color: var(--wp--preset--color--charcoal);
	margin: 0 0 var(--wp--preset--spacing--20);
}

.gem-timeline__points {
	list-style: none;
	margin: 0 0 var(--wp--preset--spacing--20);
	padding: 0;
	display: grid;
	gap: 0.5rem;
	color: var(--wp--preset--color--grey);
	font-size: var(--wp--preset--font-size--medium);
}

.gem-timeline__points li {
	position: relative;
	padding-inline-start: 1.125rem;
}

/* Round bullets, as the frame draws them. */
.gem-timeline__points li::before {
	content: "";
	position: absolute;
	inset-inline-start: 0.125rem;
	inset-block-start: 0.62em;
	inline-size: 0.3125rem;
	block-size: 0.3125rem;
	border-radius: 50%;
	background-color: var(--wp--custom--line--strong);
}

/*
 * "Where you stand" — the answer to the question the reader actually has.
 * Cream rather than gold: this is orientation, not an alert, and a warm filled
 * panel at every stage would turn a calm page into seven warnings.
 */
.gem-timeline__standing {
	margin: 0;
	background-color: var(--wp--preset--color--cream);
	border-radius: var(--wp--custom--radius--medium);
	box-shadow: var(--wp--preset--shadow--inset-hairline);
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--charcoal);
}

.gem-timeline__standing span {
	display: block;
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--custom--tint--gold-text);
	margin-block-end: 0.25rem;
}

.gem-section.has-cream-background-color .gem-timeline__standing {
	background-color: var(--wp--preset--color--white);
}

/*
 * Warning signs — informative, not alarming.
 *
 * No red, no filled alert block, no icon that reads as a stop sign. Charcoal
 * text on cream with a gold shield marker, at the same visual weight as any
 * other section. The reader is already frightened; the styling should not add
 * to it.
 */
.gem-signs {
	display: grid;
	gap: var(--wp--preset--spacing--30);
}

.gem-signs__item {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--30);
	background-color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--small);
	border-inline-start: 3px solid var(--wp--preset--color--gold);
	padding: var(--wp--preset--spacing--30);
}

.gem-signs__marker {
	display: inline-flex;
	color: var(--wp--custom--tint--gold-deep);
	flex: 0 0 auto;
	margin-block-start: 0.125rem;
}

.gem-signs__marker svg {
	inline-size: 1.375rem;
	block-size: 1.375rem;
	display: block;
}

.gem-signs__title {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.35;
	color: var(--wp--preset--color--charcoal);
	margin: 0 0 0.375rem;
}

.gem-signs__copy {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--grey);
}

/*
 * Confirmation checklist — the one correct home for Greenery.
 *
 * Each assurance sits on its own cream tile in a two-up grid. As a bare list it
 * was four short lines stacked down the middle of a full-width white section,
 * which read as an afterthought; these are the four things the reader most
 * needs to believe before making contact, so they are given the weight of
 * objects. The surface stays neutral and only the tick is green — four green
 * panels would read as a stack of alerts, which is the opposite of the intent.
 */
.gem-check {
	display: grid;
	gap: var(--wp--preset--spacing--20);
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

/*
 * Standing notice — the "not legal advice" line, made unskippable.
 *
 * At the foot of the page in small grey type this was doing nothing for a
 * reader who arrives mid-page from a search result, which is exactly who the
 * disclosure exists for. It now sits directly under the h1 on the legal pages.
 *
 * Gold-subtle with a shield, never a red or amber alert block: the reader is
 * already frightened and this is a scope statement, not a warning.
 */
.gem-notice {
	/* border-box so `inline-size: 100%` means the column width, not the column
	   width plus padding — it was rendering 48px wider than its container. */
	box-sizing: border-box;
	display: flex;
	align-items: flex-start;
	gap: 0.625rem;
	/* Full width of the intro column, not a centred pill: the frame shows a
	   rectangle spanning the measure, which reads as a standing notice rather
	   than a badge. */
	inline-size: 100%;
	margin-block-start: var(--wp--preset--spacing--30);
	background-color: var(--wp--custom--tint--gold-subtle);
	border-radius: var(--wp--custom--radius--medium);
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--charcoal);
	text-align: start;
}

.gem-notice > span {
	display: inline-flex;
	flex: 0 0 auto;
	color: var(--wp--custom--tint--gold-deep);
	margin-block-start: 0.0625rem;
}

.gem-notice svg {
	inline-size: 1.125rem;
	block-size: 1.125rem;
	display: block;
}

/*
 * ABOUT — THE ONE DARK SECTION ON THE PUBLIC PAGE.
 *
 * The page ran cream / white / cream / white / cream / white: six sections with
 * effectively no difference in value between any of them, which is why two
 * passes of purely typographic fixes here both failed. Charcoal is already in
 * the system as the footer surface, so this borrows it rather than inventing a
 * seventh colour, and spends it at the one point where Gerald speaks in the
 * first person.
 *
 * EVERY COLOUR IN HERE IS MEASURED AGAINST #31313B. The default grey body token
 * lands at 2.12:1 on this surface and must never appear — that is the trap a
 * dark section sets, and it is why the prose gets its own on-dark token.
 */
.gem-about {
	--gem-about-rule: var(--wp--custom--line--on-dark);
}

/* 11.86:1 on charcoal. */
.gem-about .gem-statement {
	margin: 0;
	max-inline-size: 20ch;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--hero);
	line-height: 1.15;
	letter-spacing: -0.015em;
	color: var(--wp--preset--color--cream);
	text-wrap: balance;
}

/* 6.97:1 on charcoal. Held to a measure so the lines stay readable. */
.gem-about__prose {
	max-inline-size: var(--wp--custom--measure--prose);
	color: var(--wp--custom--tint--on-dark-muted);
}

/* The eyebrow's facet stays gold — 7.02:1, and it is the only warm note here. */
.gem-about .gem-eyebrow {
	color: var(--wp--custom--tint--on-dark-muted);
}

/*
 * Footing — credentials across the full width, under a hairline.
 *
 * In the previous pass these sat in a side column and left roughly 200px of
 * dead space beneath them, which was most of what made the section read as
 * unfinished. Run as a footing they close the band instead of hanging in it.
 */
.gem-footing {
	margin-block-start: var(--wp--preset--spacing--50);
	padding-block-start: var(--wp--preset--spacing--40);
	border-block-start: 1px solid var(--gem-about-rule);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
}

.gem-footing__brokerage {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
}

.gem-footing__brokerage img {
	inline-size: 100%;
	max-inline-size: 5.5rem;
	block-size: auto;
	display: block;
}

@media (max-width: 600px) {
	/* Stacked, the space-between gap collapses and the two blocks touch. */
	.gem-footing {
		justify-content: flex-start;
	}
}

/*
 * "Ask" panel — sits beside the FAQ accordion.
 *
 * Sticky on desktop so it stays with the reader as they open answers down a
 * long list; the offer is least useful at the moment it scrolls away. Static
 * below the breakpoint, where it simply follows the questions.
 */
.gem-ask {
	background-color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--large);
	box-shadow: var(--wp--preset--shadow--soft), var(--wp--preset--shadow--inset-hairline);
	padding: var(--wp--preset--spacing--40);
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
	align-items: flex-start;
}

.gem-ask__title {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--x-large);
	line-height: 1.3;
	color: var(--wp--preset--color--charcoal);
	margin: 0;
}

.gem-ask__copy {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--grey);
}

.gem-ask__action {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
}

@media (min-width: 62rem) {
	.gem-ask {
		position: sticky;
		/* Clears the fixed header, plus a breath. */
		inset-block-start: calc(var(--wp--custom--header--height) + var(--wp--preset--spacing--30));
	}
}

/*
 * Guide panel — the cover alongside the offer.
 *
 * The cover is artwork on its own backdrop, so it is treated as a photograph
 * rather than a cut-out: rounded, shadowed, and capped in width so it stays a
 * supporting element. Without the cap it grew to the full column and outweighed
 * the text it is meant to introduce.
 */
.gem-guide__cover {
	display: block;
	inline-size: 100%;
	max-inline-size: 14rem;
	block-size: auto;
}

@media (max-width: 781px) {
	/* Centred above the copy once the columns stack, rather than stranded left. */
	.gem-guide__cover {
		margin-inline: auto;
		max-inline-size: 11rem;
	}
}

/*
 * Definition panel — a lone explanation with no siblings to sit beside.
 *
 * "What is probate?" is the one block on that page that defines the subject,
 * and it was centred prose floating in a full-width band with nothing holding
 * it, which read as a caption. Given its own surface it reads as a definition
 * worth stopping at. Use sparingly: a page with two of these has a card grid,
 * not a definition.
 */
.gem-define {
	background-color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--large);
	box-shadow: var(--wp--preset--shadow--soft), var(--wp--preset--shadow--inset-hairline);
	padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40);
}

/* Inverse fill wherever the surrounding section is already white. */
.gem-section.has-white-background-color .gem-define {
	background-color: var(--wp--preset--color--cream);
}

.gem-check__item {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--charcoal);
	background-color: var(--wp--preset--color--cream);
	border-radius: var(--wp--custom--radius--medium);
	box-shadow: var(--wp--preset--shadow--inset-hairline);
	padding: var(--wp--preset--spacing--30);
}

/* On a cream section the tiles need the inverse fill to stay distinguishable. */
.gem-section.has-cream-background-color .gem-check__item {
	background-color: var(--wp--preset--color--white);
}

/*
 * Short accent rule under a section heading — an accent, not a divider.
 *
 * Currently unused; the About section it was built for is now .gem-about.
 * Kept because it is a reasonable utility, but FIXED: it never actually worked.
 * WordPress centres constrained-layout children with `margin-left: auto
 * !important`, so the original two-classes-deep logical-property version lost
 * silently and the rule sat centred under the heading for weeks. Specificity
 * cannot beat `!important`, so the override below carries one too.
 */
.wp-block-group .gem-rule,
.wp-block-column .gem-rule {
	inline-size: 3.5rem;
	block-size: 2px;
	border: 0;
	margin-left: 0 !important;
	margin-right: auto !important;
}

/* A form sitting directly on a card needs the card's padding. */
.gem-form-card {
	padding: var(--wp--preset--spacing--40);
}

/* Booking card on Home. Button is a disabled placeholder until Calendly (M2). */
/* Block flow, not grid: constrained-layout children carry auto side margins. */
.gem-book {
	padding: var(--wp--preset--spacing--40);
}

.gem-book > * + * {
	margin-block-start: var(--wp--preset--spacing--30);
}

.gem-book > .gem-book__note {
	margin-block-start: var(--wp--preset--spacing--20);
}

/* Figma px sizes as rem, specific to this card. */
.gem-book__title {
	margin: 0;
	text-align: center;
	font-size: 1.75rem;          /* 28px */
	line-height: 1.25;
	padding-block-end: var(--wp--preset--spacing--20);
	border-block-end: 1px solid var(--wp--custom--tint--cream-deep);
}

.gem-book > .gem-book__lede {
	margin-block-start: var(--wp--preset--spacing--20);
	text-align: center;
	font-size: 0.875rem;         /* 14px */
	line-height: 1.6;
	color: var(--wp--preset--color--grey);
}

.gem-book__list {
	list-style: none;
	padding: 0;
	display: grid;
	gap: var(--wp--preset--spacing--30);
}

.gem-book > .gem-book__list {
	margin: var(--wp--preset--spacing--40) 0 0;
}

.gem-book__item {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	font-size: 0.875rem;         /* 14px */
	color: var(--wp--preset--color--grey);
}

.gem-book__cta {
	inline-size: 100%;
	font-size: 0.875rem;         /* 14px */
}

.gem-book__cta:disabled {
	opacity: 1;
	cursor: default;
}

/* The lock line: small, grey, centred, icon inline with the text. */
.gem-book__note {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--grey);
	text-align: center;
	padding-block-end: var(--wp--preset--spacing--30);
	border-block-end: 1px solid var(--wp--custom--tint--cream-deep);
}

.gem-book__note svg {
	inline-size: 1.125rem;
	block-size: 1.125rem;
	flex: 0 0 auto;
}

/* Who you will be talking to: a compact version of the trust strip. */
.gem-book__who {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
}

.gem-book__who > .gem-avatar {
	flex: 0 0 5.5rem;
	inline-size: 5.5rem;
}

.gem-book__who-body > * {
	margin: 0;
}

.gem-book__who-body > * + * {
	margin-block-start: 0.125rem;
}

.gem-book__name {
	font-size: 0.875rem;         /* 14px */
	color: var(--wp--preset--color--charcoal);
}

/* Specified at 500; the brand kit has no Roboto Medium, so Bold 700 stands in. */
.gem-book__role {
	font-family: var(--wp--preset--font-family--body);
	font-size: 1rem;             /* 16px */
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--wp--custom--tint--gold-text);
}

.gem-book__tagline {
	font-size: 0.6875rem;        /* 11px */
	color: var(--wp--preset--color--grey);
}

/* Contact column labels: 16px charcoal, lightly tracked, over a 16px grey value. */
.gem-contact__label {
	font-size: 1rem;
	letter-spacing: 0.04em;
	color: var(--wp--preset--color--charcoal);
}

/* 48px in the Figma frame, which is larger than every other section heading. */
.gem-contact__heading {
	font-size: 3rem;
}

/* Phone sizes, matching the rest of the site's fluid presets. */
@media (max-width: 599px) {
	.gem-contact__heading {
		font-size: 2rem;
	}

	.gem-contact__label {
		font-size: var(--wp--preset--font-size--label);
		letter-spacing: 0.1em;
	}

	#contact .gem-icon-circle {
		inline-size: 2.75rem;
		block-size: 2.75rem;
	}

	.gem-book__title {
		font-size: 1.375rem;
	}

	.gem-book > .gem-book__lede,
	.gem-book__item,
	.gem-book__cta,
	.gem-book__note,
	.gem-book__name {
		font-size: 0.8125rem;
	}

	.gem-book__role {
		font-size: 0.875rem;
	}

	.gem-book__item .gem-icon-circle {
		inline-size: 2.75rem;
		block-size: 2.75rem;
	}

	/* Keeps the label on one line down to 320px. */
	.gem-book__cta {
		padding: 0.6875rem 0.875rem;
		font-size: 0.8125rem;
	}

	/* Room for the email address on a 320px screen. */
	.gem-contact__label + p {
		font-size: 0.9375rem;
	}

	.gem-book__item .gem-icon-circle svg {
		inline-size: 1.375rem;
		block-size: 1.375rem;
	}
}

@media (max-width: 599px) {
	.gem-book {
		padding: var(--wp--preset--spacing--30);
	}

	.gem-book__who {
		align-items: flex-start;
	}

	.gem-book__who > .gem-avatar {
		flex-basis: 4rem;
		inline-size: 4rem;
	}
}

/* Contact details beside a form: icon chip, label, value. */
.gem-contact {
	list-style: none;
	margin: var(--wp--preset--spacing--30) 0 0;
	padding: 0;
	display: grid;
	gap: var(--wp--preset--spacing--30);
}

.gem-contact__item {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
}

.gem-contact__body {
	display: flex;
	flex-direction: column;
	gap: 0.125rem;
}

.gem-contact__value {
	color: var(--wp--preset--color--charcoal);
}

/*
 * MULTISTEP FORM — step markers, fieldsets, and a submit that is honestly off.
 *
 * The markers carry the sequence without JavaScript. All three steps render at
 * once now, so the markers describe the shape of what is coming
 * rather than pretending to be a working switcher.
 */
.gem-steps-nav {
	list-style: none;
	margin: 0 0 var(--wp--preset--spacing--30);
	padding: 0 0 var(--wp--preset--spacing--30);
	border-block-end: 1px solid var(--wp--custom--line--subtle);
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
}

.gem-steps-nav__item {
	display: flex;
	align-items: baseline;
	gap: 0.5rem;
	color: var(--wp--preset--color--grey);
	font-size: var(--wp--preset--font-size--small);
}

.gem-steps-nav__num {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--custom--tint--gold-deep);
}

.gem-steps-nav__item.is-current .gem-steps-nav__label {
	color: var(--wp--preset--color--charcoal);
	font-weight: 700;
}

.gem-fieldset {
	border: 0;
	margin: 0 0 var(--wp--preset--spacing--30);
	padding: 0;
}

.gem-fieldset__legend {
	padding: 0;
	margin-block-end: var(--wp--preset--spacing--20);
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--large);
	color: var(--wp--preset--color--charcoal);
}

/*
 * A disabled submit must LOOK disabled. Nothing is wired up yet, and a
 * full-strength gold button that silently does nothing is worse than no button
 * — a distressed reader would assume they had asked for help and wait.
 */
.gem-form__submit[disabled] {
	inline-size: 100%;
	cursor: not-allowed;
	opacity: 0.55;
	filter: grayscale(0.35);
}

/*
 * Designation seals.
 *
 * Sized by height rather than width so three seals of different aspect ratios
 * (SFR is 3.6:1, CPE 1.6:1, CPRES square) sit on one optical baseline. Matching
 * their widths instead makes the square seal tower over the wordmarks.
 *
 * Each is captioned with the designation spelled out — an uncaptioned seal is
 * decoration, and almost no reader knows what CPRES stands for.
 */
.gem-seals {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
}

/* Two subgrid rows per seal: logos share a baseline, text blocks start on one line. */
.gem-seals__item {
	grid-row: span 2;
	display: grid;
	grid-template-rows: subgrid;
	justify-items: center;
	gap: var(--wp--preset--spacing--20);
	min-inline-size: 0;
	text-align: center;
}

.gem-seals__img {
	display: block;
	align-self: end;
	block-size: auto;
	max-block-size: 5.5rem;
	inline-size: auto;
	/* Width cap evens out the wide wordmarks; badges are height-bound. */
	max-inline-size: min(100%, 14rem);
}

/* Wide marks with taller artwork (C-REPS): kept near SFR and PSA height. */
.gem-seals__img--short {
	max-block-size: 4.25rem;
}

/* Round and portrait badges need height to stay legible; the nudge is optical. */
.gem-seals__img--tall {
	max-block-size: 8rem;
	transform: translateY(2px);
}

.gem-seals__text {
	display: flex;
	flex-direction: column;
	align-items: center;
	align-self: start;
	gap: var(--wp--preset--spacing--10);
	margin-block-end: var(--wp--preset--spacing--30);
}

.gem-seals__label {
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.35;
	color: var(--wp--preset--color--charcoal);
}

/* What the designation means: secondary to the label, never competing with it. */
.gem-seals__desc {
	max-inline-size: 36ch;
	font-size: var(--wp--preset--font-size--label);
	font-weight: 400;
	line-height: 1.55;
	color: var(--wp--preset--color--grey);
}

/* Desktop: six tracks, two per seal, so a short last row centres. */
@media (min-width: 1101px) {
	.gem-seals {
		grid-template-columns: repeat(6, minmax(0, 1fr));
		column-gap: var(--wp--preset--spacing--50);
	}

	.gem-seals__item {
		grid-column: span 2;
	}

	.gem-seals__item:nth-child(3n+1):nth-last-child(2) {
		grid-column: 2 / span 2;
	}

	.gem-seals__item:nth-child(3n+1):last-child {
		grid-column: 3 / span 2;
	}
}

/* Tablet and phone: two columns; an odd or moved-last seal centres alone. */
@media (max-width: 1100px) {
	.gem-seals__img {
		transform: none;
	}

	.gem-seals__item:last-child:nth-child(odd) {
		grid-column: 1 / -1;
	}

	.gem-seals__item--small-last {
		order: 1;
		grid-column: 1 / -1;
	}

	.gem-seals:has(.gem-seals__item--small-last) .gem-seals__item:last-child:not(.gem-seals__item--small-last) {
		grid-column: auto;
	}
}

/* Phone: smaller marks so two sit side by side. */
@media (max-width: 600px) {
	.gem-seals__img {
		max-block-size: 3rem;
	}

	.gem-seals__img--tall {
		max-block-size: 5rem;
	}
}

/*
 * Free-help band: wide enough for the heading to set on one line, but the prose
 * under it held to a readable measure rather than running the full 1040px.
 */
.gem-help > p:not(.gem-eyebrow) {
	max-inline-size: 46rem;
	margin-inline: auto;
}

/*
 * Privacy policy body. Long-form legal prose, so it gets a tighter measure and
 * clear separation between sections — this is a page people scan for one
 * paragraph rather than read start to finish.
 */
.gem-policy__section + .gem-policy__section {
	margin-block-start: var(--wp--preset--spacing--40);
}

.gem-policy__heading {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--x-large);
	line-height: 1.3;
	color: var(--wp--preset--color--charcoal);
	margin: 0 0 var(--wp--preset--spacing--20);
}

.gem-policy p {
	margin: 0 0 var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--grey);
}

.gem-policy p:last-child {
	margin-block-end: 0;
}

/*
 * IN-SECTION NAVIGATION — wayfinding, in the footer's register.
 *
 * A row of links under an eyebrow, below the closing CTA so it takes nothing
 * from the primary action, behind a hairline so it reads as its own zone.
 *
 * LINKS STAY UNDERLINED AT REST. An earlier pass held the underline back for
 * hover, on the theory that seven underlined items in a row read as unstyled
 * text. That was designer logic: it left the only interactive elements in the
 * block as plain grey words with no affordance at all, and a visitor has no
 * reason to hover something that does not look hoverable. Discoverability beats
 * tidiness here — the underline is the affordance and it does not come off.
 *
 * THE CURRENT PAGE IS THEREFORE NOT UNDERLINED, and that now carries real
 * meaning: in this row, underline means "goes somewhere". It is marked by a
 * soft gold chip instead of a rule, because a rule under text is exactly what
 * the links beside it wear.
 *
 * MOBILE: the row STACKS rather than wrapping into ragged columns. Seven links
 * squeezed across 390px is unreadable and a half-width second column reads as a
 * layout fault. Full-width rows with dividers and a chevron are the tap
 * convention, so the underline comes off there and the chevron takes over.
 */
.gem-sectionnav {
	border-block-start: 1px solid var(--wp--custom--line--subtle);
	padding-block-start: var(--wp--preset--spacing--30);
}

.gem-sectionnav__label {
	margin: 0 0 var(--wp--preset--spacing--20);
}

.gem-sectionnav__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.25rem var(--wp--preset--spacing--20);
	/* Cancels the shared inline padding below so the first item aligns to the
	   eyebrow rather than sitting a chip's width to the right of it. */
	margin-inline-start: -0.75rem;
}

/*
 * BOTH SELECTORS, ALWAYS.
 *
 * The current page is a <span>, not an <a> — see
 * gemstone_mark_current_section_link(). A size rule that named only `a` left it
 * inheriting the full body size, so the one item meant to recede into the row
 * was the largest thing in it. Anything setting the shared shape of these items
 * has to name both.
 */
.gem-sectionnav__list a,
.gem-sectionnav__list [aria-current="page"] {
	display: inline-block;
	position: relative;
	/*
	 * Without this the mobile rows below add their padding OUTSIDE a full-width
	 * block, overflowing the container by the full inline padding — the row ran
	 * to the very edge of a 390px viewport with no right margin, and the chevron
	 * anchored to its inline end was pushed off-screen where it could not be
	 * seen at all.
	 */
	box-sizing: border-box;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.4;
	padding: 0.35rem 0.75rem;
	border-radius: var(--wp--custom--radius--small);
}

.gem-sectionnav__list a {
	color: var(--wp--preset--color--grey);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-decoration-color: var(--wp--custom--line--strong);
	text-underline-offset: 0.25em;
	transition: color 0.15s ease, background-color 0.15s ease, text-decoration-color 0.15s ease;
}

.gem-sectionnav__list a:hover,
.gem-sectionnav__list a:focus-visible {
	color: var(--wp--preset--color--charcoal);
	background-color: var(--wp--custom--tint--gold-subtle);
	text-decoration-color: var(--wp--preset--color--gold);
}

/*
 * YOU-ARE-HERE — a chip, not a rule.
 *
 * Three signals that do not depend on colour alone: it is the only item with a
 * filled background, the only one in charcoal, and the only one without an
 * underline. The brand facet was tried here and dropped — the eyebrow directly
 * above already carries one, and a second a few pixels below read as two
 * bullets rather than as hierarchy.
 */
.gem-sectionnav__list [aria-current="page"] {
	color: var(--wp--preset--color--charcoal);
	background-color: var(--wp--custom--tint--gold-soft);
	text-decoration: none;
}

/*
 * MOBILE: ONE LIST CARD, NOT SEVEN LOOSE LINES.
 *
 * Two faults were reported against the earlier stacked version and both are
 * fixed here rather than traded off against each other:
 *
 * 1. THE ROWS DID NOT LOOK TAPPABLE. Underline comes off on mobile (the row is
 *    the target, not the words), which left grey 300-weight text and a hairline
 *    chevron — indistinguishable from a plain list of headings. The fix is to
 *    make the whole thing read as a control: a bordered, rounded, white card
 *    with divided rows, charcoal text rather than grey, a gold chevron, and a
 *    pressed state on :active so a tap is acknowledged before the page changes.
 *    Contained rows are what a phone user already reads as "these are rows you
 *    press"; a bare stack is not.
 *
 * 2. CURRENT vs REST WAS TOO LOUD. gold-soft (#FFEFCC) against untinted rows
 *    made the current page the single heaviest object on the screen — it read
 *    as the call to action rather than as wayfinding, directly below an actual
 *    CTA. It drops to gold-subtle (#FFF8EA): still the only filled row, still
 *    the only one with the gold bar and without a chevron, but now a whisper.
 *    Three redundant signals survive, so nothing depends on the fill alone.
 *
 * Row text is charcoal at 300, current included. Weight is NOT used to separate
 * them — only 300 and 700 Roboto are self-hosted, and 700 here would rebuild
 * exactly the shouting this pass removed.
 */
@media (max-width: 781px) {
	.gem-sectionnav__list {
		display: grid;
		grid-template-columns: 1fr;
		gap: 0;
		margin-inline-start: 0;
		background-color: var(--wp--preset--color--white);
		border: 1px solid var(--wp--custom--line--subtle);
		border-radius: var(--wp--custom--radius--medium);
		/* Clips the first and last row's fill to the card's corners — without it
		   the current-page tint squares off the rounding it sits inside. */
		overflow: hidden;
	}

	.gem-sectionnav__list li + li {
		border-block-start: 1px solid var(--wp--custom--line--subtle);
	}

	.gem-sectionnav__list a,
	.gem-sectionnav__list [aria-current="page"] {
		/*
		 * min-block-size rather than padding alone: padding of 0.75rem around a
		 * clamped small font measured 42px, quietly under the 44px minimum this
		 * comment used to claim.
		 */
		display: flex;
		align-items: center;
		min-block-size: 3rem;
		padding: 0.625rem 2.25rem 0.625rem 1rem;
		border-radius: 0;
		color: var(--wp--preset--color--charcoal);
	}

	/* The row is the target, so the underline comes off and the chevron says
	   "tappable" instead. */
	.gem-sectionnav__list a {
		text-decoration: none;
	}

	.gem-sectionnav__list a::after {
		content: "";
		position: absolute;
		inset-inline-end: 1rem;
		inset-block-start: 50%;
		inline-size: 0.45rem;
		block-size: 0.45rem;
		border-block-start: 1.75px solid var(--wp--custom--tint--gold-deep);
		border-inline-end: 1.75px solid var(--wp--custom--tint--gold-deep);
		transform: translateY(-50%) rotate(45deg);
	}

	/* Touch has no hover, so :active is the only feedback a tap can get. The
	   same tint as the current row: pressing a row previews becoming it. */
	.gem-sectionnav__list a:hover,
	.gem-sectionnav__list a:focus-visible,
	.gem-sectionnav__list a:active {
		color: var(--wp--preset--color--charcoal);
		background-color: var(--wp--custom--tint--gold-subtle);
	}

	/*
	 * The chip becomes a full-width tinted row with a gold bar at the inline
	 * start — the same "selected row" convention a phone list already uses.
	 */
	.gem-sectionnav__list [aria-current="page"] {
		background-color: var(--wp--custom--tint--gold-subtle);
		border-inline-start: 3px solid var(--wp--preset--color--gold);
		padding-inline-start: calc(1rem - 3px);
	}
}

/*
 * Document list — paperwork available on request.
 *
 * Deliberately NOT styled as download links. Nothing is uploaded and nothing is
 * linked, so anything that looks clickable would be a lie; these read as a list
 * of what exists, which is what the offer actually is.
 */
.gem-docs {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: var(--wp--preset--spacing--20);
}

.gem-docs__item {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--20);
	background-color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--medium);
	box-shadow: var(--wp--preset--shadow--inset-hairline);
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--charcoal);
	font-size: var(--wp--preset--font-size--small);
}

.gem-docs__icon {
	display: inline-flex;
	flex: 0 0 auto;
	color: var(--wp--custom--tint--gold-deep);
	margin-block-start: 0.0625rem;
}

.gem-docs__icon svg {
	inline-size: 1.25rem;
	block-size: 1.25rem;
	display: block;
}

.gem-section.has-white-background-color .gem-docs__item {
	background-color: var(--wp--preset--color--cream);
}

/* Credentials — the verified facts, and nothing unverified. */
.gem-creds {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
}

/*
 * Stacked variant: one fact per line, anchoring a narrow column under a
 * heading. Wrapping is off because at 38% of the grid the flex row broke
 * "Licensed Texas real estate professional" across two lines and left the icon
 * orphaned above its own text.
 */
/*
 * On-dark variant, for the charcoal About band. Must sit AFTER the base
 * .gem-creds: that rule centres the list, and at equal specificity the later
 * declaration wins. Placed earlier in the file it was silently overridden and
 * the credentials centred themselves on a phone.
 */
.gem-creds--ondark {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
	justify-content: flex-start;
}

.gem-creds--ondark .gem-creds__item {
	color: var(--wp--preset--color--cream);
}

.gem-creds--ondark .gem-creds__icon {
	color: var(--wp--preset--color--gold);
}

.gem-creds--stack {
	flex-direction: column;
	flex-wrap: nowrap;
	align-items: flex-start;
	justify-content: flex-start;
	gap: var(--wp--preset--spacing--20);
	margin-block-start: var(--wp--preset--spacing--30);
}

.gem-creds--stack .gem-creds__item {
	align-items: flex-start;
}

.gem-creds--stack .gem-creds__icon {
	margin-block-start: 0.0625rem;
}

/* Inline variant: sits at the foot of a text column, left-aligned and tighter. */
.gem-creds--inline {
	justify-content: flex-start;
	gap: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
	margin-block-start: var(--wp--preset--spacing--30);
	padding-block-start: var(--wp--preset--spacing--30);
	border-block-start: 1px solid var(--wp--custom--line--subtle);
}

.gem-creds__item {
	display: flex;
	align-items: center;
	gap: 0.625rem;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--charcoal);
}

.gem-creds__icon {
	display: inline-flex;
	color: var(--wp--custom--tint--gold-deep);
}

.gem-creds__icon svg {
	inline-size: 1.25rem;
	block-size: 1.25rem;
	display: block;
}
/* == 5. Forms ============================================================= */

/*
 * These are static placeholders. Real forms replace them in
 * a later phase — keep the class names so the styling survives the swap.
 */

/*
 * Form controls need an explicit border-box. WordPress does not normalise
 * box-sizing on inputs, so `inline-size: 100%` plus padding plus border made
 * every field overflow its card to the right and clip.
 */
.gem-form,
.gem-form *,
.gem-field__input,
.gem-form button {
	box-sizing: border-box;
}

.gem-field {
	display: block;
	margin-block-end: var(--wp--preset--spacing--20);
}

.gem-field__label {
	display: block;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--grey);
	margin-block-end: 0.375rem;
}

.gem-field__input {
	display: block;
	inline-size: 100%;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 300;
	color: var(--wp--preset--color--charcoal);
	background-color: var(--wp--custom--field--background);
	border: 1px solid var(--wp--custom--field--border);
	border-radius: var(--wp--custom--field--radius);
	padding: var(--wp--custom--field--padding-y) var(--wp--custom--field--padding-x);
	/* 16px minimum prevents iOS Safari zooming the page on focus. */
	min-block-size: 2.875rem;
}

textarea.gem-field__input {
	min-block-size: 6rem;
	resize: vertical;
}

.gem-field__input::placeholder {
	color: var(--wp--preset--color--grey);
	opacity: 0.7;
}

.gem-field__input:focus {
	outline: 2px solid var(--wp--preset--color--gold);
	outline-offset: 1px;
	border-color: transparent;
}

/* Fields are disabled while they are previews — keep them legible, not greyed out. */
.gem-field__input:disabled,
.gem-form button:disabled {
	opacity: 1;
	cursor: default;
}

.gem-field__optional {
	font-weight: 300;
	text-transform: none;
	letter-spacing: 0;
}

/*
 * Reset the paragraph margins WordPress gives these <p> wrappers, then restate
 * the field rhythm at equal specificity. Previously `.gem-form p` outranked
 * `.gem-field`, which silently cancelled every field margin and left the submit
 * button flush against the last input.
 */
.gem-form p {
	margin: 0;
}

.gem-form .gem-field {
	margin-block-end: var(--wp--preset--spacing--30);
}

.gem-form .gem-field:last-of-type {
	margin-block-end: 0;
}

.gem-form__note {
	margin-block-start: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--grey);
	text-align: center;
}

/*
 * Status line. Quiet, but present on every placeholder form, so
 * nobody wonders why the button does nothing. Remove it with the placeholder
 * markup when the real forms land.
 */
.gem-form__status {
	display: inline-block;
	margin-block-start: 0.375rem;
	font-size: var(--wp--preset--font-size--label);
	letter-spacing: 0.04em;
	color: var(--wp--custom--tint--gold-text);
}

@media (max-width: 599px) {
	.gem-field__input {
		font-size: 1rem;
	}
}

/* == 6. Accordion (core/details) ========================================== */

/*
 * ANSWERS OPEN ON A HEIGHT TRANSITION RATHER THAN SNAPPING.
 *
 * `<details>` was never animatable: the answer had no box of its own to
 * transition, and `block-size: auto` was not an interpolable end point. Both
 * gaps are now closed by the standard — `::details-content` addresses
 * everything after the summary, and `interpolate-size: allow-keywords` makes
 * `auto` a legal target for a height transition.
 *
 * Both are feature-queried, so where either is missing the answer simply
 * appears the way it always did. That is why this needs no JavaScript and no
 * polyfill, which matters against the contractual PageSpeed budget.
 *
 * `transition-behavior: allow-discrete` is what keeps the CLOSING direction
 * animating. Without it `content-visibility` flips to hidden on the first
 * frame and the answer disappears before the height has moved at all.
 */

.wp-block-details {
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--custom--line--subtle);
	border-radius: var(--wp--custom--radius--medium);
	padding: var(--wp--preset--spacing--30);
	transition: border-color 0.28s ease, box-shadow 0.28s ease;
}

.wp-block-details:hover {
	border-color: var(--wp--custom--line--strong);
}

/* The open answer is the one being read, so give it a quiet edge — gold at
   tint strength, never a fill, which would read as an alert on these pages. */
.wp-block-details[open] {
	border-color: var(--wp--custom--tint--gold-soft);
	box-shadow: var(--wp--preset--shadow--soft);
}

.wp-block-details + .wp-block-details {
	margin-block-start: var(--wp--preset--spacing--20);
}

.wp-block-details summary {
	cursor: pointer;
	position: relative;
	list-style: none;
	padding-inline-end: 2rem;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.35;
	color: var(--wp--preset--color--charcoal);
}

.wp-block-details summary::-webkit-details-marker {
	display: none;
}

/* Chevron drawn in CSS — no icon font, no extra request. */
.wp-block-details summary::after {
	content: "";
	position: absolute;
	inset-inline-end: 0.25rem;
	inset-block-start: 0.45em;
	inline-size: 0.5rem;
	block-size: 0.5rem;
	border-inline-end: 2px solid var(--wp--preset--color--grey);
	border-block-end: 2px solid var(--wp--preset--color--grey);
	transform: rotate(45deg);
	transform-origin: center;
	transition: transform 0.32s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.32s ease;
}

.wp-block-details[open] summary::after {
	transform: rotate(-135deg);
	border-color: var(--wp--custom--tint--gold-deep);
}

/*
 * Spacing above the answer lives on the answer, not as a margin under the
 * summary. A margin would appear the instant `open` is set and snap the layout
 * open before the height had begun to move; inside the clipped box it is
 * revealed by the same transition as the text.
 */
.wp-block-details[open] summary {
	margin-block-end: var(--wp--preset--spacing--20);
}

@supports (interpolate-size: allow-keywords) {
	:root {
		interpolate-size: allow-keywords;
	}
}

@supports selector(::details-content) {
	.wp-block-details[open] summary {
		margin-block-end: 0;
	}

	.wp-block-details::details-content {
		block-size: 0;
		overflow: hidden;
		opacity: 0;
		transition:
			block-size 0.32s cubic-bezier(0.4, 0, 0.2, 1),
			opacity 0.24s ease,
			padding-block-start 0.32s cubic-bezier(0.4, 0, 0.2, 1),
			content-visibility 0.32s;
		transition-behavior: allow-discrete;
	}

	.wp-block-details[open]::details-content {
		block-size: auto;
		opacity: 1;
		padding-block-start: var(--wp--preset--spacing--20);
	}
}

/* == 7. Comparison table ================================================== */

/*
 * ONE source of truth. A real <table> on desktop; the same rows reflow into
 * stacked cards below 900px, labelled from each cell's data-label attribute.
 * No duplicated markup, no JavaScript, and it stays a table for screen readers.
 */

.gem-compare {
	background-color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--medium);
	box-shadow: var(--wp--preset--shadow--soft);
	overflow: hidden;
}

.gem-compare table {
	inline-size: 100%;
	border-collapse: collapse;
	font-size: var(--wp--preset--font-size--small);
}

.gem-compare th,
.gem-compare td {
	text-align: start;
	vertical-align: top;
	padding: var(--wp--preset--spacing--30);
}

.gem-compare thead th {
	background-color: var(--wp--preset--color--charcoal);
	color: var(--wp--preset--color--cream);
	font-family: var(--wp--preset--font-family--body);
	font-weight: 700;
	font-size: var(--wp--preset--font-size--small);
}

.gem-compare tbody tr + tr {
	border-block-start: 1px solid var(--wp--custom--line--subtle);
}

.gem-compare .gem-compare__option {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--x-large);
	color: var(--wp--preset--color--charcoal);
	display: block;
}

.gem-compare .gem-compare__badge {
	display: inline-block;
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	/* Small bold text: gold-deep measures 3.21:1 here, gold-text 4.83:1. */
	color: var(--wp--custom--tint--gold-text);
	background-color: var(--wp--custom--tint--gold-soft);
	border-radius: var(--wp--custom--radius--small);
	padding: 0.125rem 0.5rem;
	margin-block-end: 0.375rem;
}

.gem-compare .gem-compare__badge.is-exit {
	color: var(--wp--preset--color--grey);
	background-color: var(--wp--custom--tint--cream-deep);
}

.gem-compare td p {
	margin: 0;
	color: var(--wp--preset--color--grey);
}

.gem-compare .gem-compare__keeps {
	text-align: center;
}

/*
 * Column widths. Without these the option names wrap to two lines and every row
 * grows taller than it needs to be. `table-layout: fixed` makes the browser
 * honour them instead of sizing to content.
 */
@media (min-width: 900px) {
	.gem-compare table {
		table-layout: fixed;
	}

	.gem-compare thead th:nth-child(1) { width: 20%; }
	.gem-compare thead th:nth-child(2) { width: 31%; }
	.gem-compare thead th:nth-child(3) { width: 34%; }
	.gem-compare thead th:nth-child(4) { width: 15%; }
}

/* Mobile: reflow every row into its own card. */
@media (max-width: 899px) {
	.gem-compare {
		background: none;
		box-shadow: none;
		border-radius: 0;
	}

	/*
	 * Drop table layout entirely. Without this the <table> keeps its column
	 * sizing algorithm even when the cells are display:block, so the widest
	 * cell forces the table past the viewport and the text clips off-screen.
	 * The ARIA roles in the markup preserve table semantics through this.
	 */
	.gem-compare table,
	.gem-compare tbody {
		display: block;
		inline-size: 100%;
	}

	.gem-compare thead {
		/* Column headers become the per-cell data-labels below. */
		position: absolute;
		inline-size: 1px;
		block-size: 1px;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
	}

	.gem-compare tbody tr {
		display: block;
		background-color: var(--wp--preset--color--white);
		border-radius: var(--wp--custom--radius--medium);
		box-shadow: var(--wp--preset--shadow--soft);
		padding: var(--wp--preset--spacing--30);
	}

	.gem-compare tbody tr + tr {
		border-block-start: 0;
		margin-block-start: var(--wp--preset--spacing--20);
	}

	/* The option cell is a <th scope="row"> — it must stack like the others. */
	.gem-compare tbody th,
	.gem-compare tbody td {
		display: block;
		padding: 0;
	}

	.gem-compare tbody tr > * + * {
		margin-block-start: var(--wp--preset--spacing--20);
	}

	/* Surface the column name the cell belongs to. */
	.gem-compare td[data-label]::before {
		content: attr(data-label);
		display: block;
		font-size: var(--wp--preset--font-size--label);
		font-weight: 700;
		letter-spacing: 0.08em;
		text-transform: uppercase;
		color: var(--wp--preset--color--grey);
		margin-block-end: 0.25rem;
	}

	.gem-compare .gem-compare__keeps {
		text-align: start;
	}

	.gem-compare .gem-compare__keeps > * {
		display: inline-flex;
		vertical-align: middle;
	}
}

/* == 8. Portrait and avatar =============================================== */

.gem-avatar img {
	border-radius: var(--wp--custom--radius--pill);
	aspect-ratio: 1;
	object-fit: cover;
	display: block;
	inline-size: 100%;
}

/*
 * Trust strip: portrait beside the quote on desktop, stacked on a phone.
 * The block layout is set to nowrap so the two never wrap unevenly at mid
 * widths; this handles the deliberate stack instead.
 */
/* Hold the portrait at its full size — as a flex item it otherwise shrinks. */
.gem-trust > .gem-avatar {
	flex: 0 0 8.5rem;
}

@media (max-width: 599px) {
	.gem-trust {
		flex-direction: column;
		align-items: flex-start;
	}

	.gem-trust > .gem-avatar {
		flex: 0 0 6rem;
		inline-size: 6rem;
	}
}

/*
 * On a phone the column is full width, so ease the crop rather than keeping the
 * tall 4/5 — a full-width 4/5 portrait would fill most of a phone screen.
 *
 * Crop note for whoever replaces this photograph: the supplied headshot is
 * tightly framed, with the top of Gerald's head only 3.2% down the source. Any
 * crop must start above that or it eats the forehead — the original 4/3 at
 * `object-position 50% 22%` began 9.6% down and cut his head off. Re-measure
 * against the new file before changing these numbers.
 */
@media (max-width: 781px) {

	/* The offset block reads as clutter at phone width. */
}

/* == 9. Header ============================================================ */

.gem-header {
	border-block-end: 1px solid var(--wp--custom--line--subtle);
	position: relative;
	z-index: 10;
}

/*
 * ONE logo size on every page. The public header used to render the mark larger
 * than the funnel headers, so the logo appeared to change size as you moved
 * between pages. The funnel sizing was the correct one; it is now the only one.
 *
 * The public header still carries navigation and the funnel headers do not —
 * that difference is deliberate, and is what keeps funnel URLs off the nav.
 */
.gem-header__logo img {
	display: block;
	block-size: auto;
	inline-size: clamp(9rem, 20vw, 12rem);
}

/* A button label must never break mid-word. */
.gem-header .wp-block-button__link {
	white-space: nowrap;
}

/*
 * On a phone the public header keeps the logo and the one action. The About and
 * Services links are same-page anchors on a short scrolling page, so dropping
 * them costs nothing and avoids a two-row header or a burger menu that would
 * need JavaScript.
 */
@media (max-width: 599px) {
	/*
	 * Two classes deep on purpose. WordPress emits its own
	 * `.wp-container-core-group-is-layout-*{display:flex}` rule for this group
	 * in an inline <style> that loads after this file, so a single-class
	 * selector loses on source order.
	 */
	.gem-header .gem-header__nav {
		display: none;
	}
}

/* == 10. Footer =========================================================== */

.gem-footer__logo img {
	display: block;
	block-size: auto;
	inline-size: clamp(8.75rem, 18vw, 11.25rem);
}

.gem-footer__brokerage img {
	display: block;
	block-size: auto;
	inline-size: clamp(5.5rem, 12vw, 7rem);
}

/*
 * Secondary text on the charcoal footer.
 *
 * The grey token is a cream-background colour: #626267 on #31313B measures
 * 2.12:1, far under the 4.5:1 minimum. This muted cream measures 6.97:1 while
 * still reading as clearly secondary. Never set `grey` on a dark surface.
 */
.gem-footer .has-grey-color {
	color: var(--wp--custom--tint--on-dark-muted) !important;
}

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

.gem-footer a:hover,
.gem-footer a:focus-visible {
	text-decoration: underline;
	color: var(--wp--preset--color--gold);
}

/* Fixed-basis columns must shrink on phones or the page scrolls sideways. */
.gem-footer__col {
	max-inline-size: 100%;
}

/* Brokerage identity: the client's two lines, each phrase kept whole. */
.gem-footer__identity {
	margin: var(--wp--preset--spacing--30) 0 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.6;
	color: var(--wp--preset--color--cream);
}

.gem-footer__identity-line {
	display: block;
}

.gem-footer__identity-line > span {
	white-space: nowrap;
}

/* Lines may break after a pipe only. Specificity matches the rule above. */
.gem-footer__identity-line > .gem-footer__identity-sep {
	white-space: normal;
	color: var(--wp--custom--tint--on-dark-muted);
}

/* Phones: drop the first pipe so the name and title each take a line. */
@media (max-width: 480px) {
	.gem-footer__identity-line:first-child > .gem-footer__identity-sep {
		display: none;
	}

	.gem-footer__identity-line:first-child > span {
		display: block;
	}
}

.gem-footer__identity-name {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--medium);
}

.gem-footer__identity sup,
.gem-section--band sup {
	font-size: 0.6em;
	line-height: 0;
	vertical-align: super;
}

.gem-footer__fair-housing {
	margin-block-start: var(--wp--preset--spacing--20);
}

/* Per-page disclaimer band, text chosen by patterns/footer-disclaimer.php. */
.gem-footer .gem-footer__notice > * {
	margin-block: 0;
}

.gem-footer .gem-footer__notice > .gem-eyebrow {
	margin-block-end: var(--wp--preset--spacing--20);
}

.gem-footer__legal p {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.6;
	color: var(--wp--custom--tint--on-dark-muted);
}

.gem-footer__legal p + p {
	margin-block-start: var(--wp--preset--spacing--20);
}

/*
 * "Educational information, not legal advice." belongs only where educational
 * content exists. That is the single line that differs between the public page
 * and the funnels, and it is driven by the .gem-funnel body class rather than by
 * keeping a second copy of the entire footer — which is how the two footers
 * drifted apart and left the TREC links off the public page.
 */
.gem-footer__disclaimer {
	display: none;
}

.gem-funnel .gem-footer__disclaimer {
	display: block;
}

/*
 * Compliance marks in the footer — the finished layout is two small marks
 * side by side, so the placeholders occupy that shape and that footprint.
 *
 * Stacked full-width boxes made the pending state look like two-thirds of the
 * footer was missing, and had the client approving a layout that would change
 * the moment the real files arrived. A placeholder should stand in for the
 * thing, at the size of the thing.
 */
.gem-marks {
	list-style: none;
	/* Breathing room under the FAIR HOUSING eyebrow. The eyebrow's own bottom
	   margin is tuned for text, and reads tight against artwork. */
	margin: var(--wp--preset--spacing--20) 0 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
}

.gem-marks__item {
	/*
	 * border-box, or max-inline-size does not bind: .gem-slot's padding sits
	 * outside the content box, so a 136px max rendered at 154px, and two of
	 * those plus the gap overflowed the column and wrapped to a stack.
	 */
	box-sizing: border-box;
	/*
	 * Was `flex: 1 1 0` with a 9rem cap, sized for the dashed placeholder boxes
	 * that used to sit here. With real artwork in, that stretched each item to
	 * 9rem and centred a much narrower image inside it, which read as a large
	 * indent from the footer's left edge. The artwork sizes its own box now.
	 */
	flex: 0 0 auto;
	min-inline-size: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	line-height: 1.4;
}

.gem-marks__item em {
	font-style: normal;
	text-transform: none;
	letter-spacing: normal;
	opacity: 0.7;
}

/* Marked slot for an asset the client has not supplied yet. */
.gem-slot {
	border: 1px dashed var(--wp--custom--line--on-dark);
	border-radius: var(--wp--custom--radius--small);
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--label);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	/* Sits on charcoal — the grey token would measure 2.12:1 here. */
	color: var(--wp--custom--tint--on-dark-muted);
	text-align: center;
}

/*
 * Light-background variant of the marked slot.
 *
 * The original .gem-slot sits on the charcoal footer and uses the on-dark line
 * and text tokens, which measure about 2:1 on cream. This is the same idea for
 * a content area: a block that is unmistakably not finished copy.
 *
 * Used on the two About pages, where every sentence would otherwise be an
 * invented claim about a licensed agent. An empty marked slot is the honest
 * state of that content, and it cannot be mistaken for approved copy the way
 * plausible filler prose can.
 */
.gem-slot--light {
	border-color: var(--wp--custom--line--strong);
	color: var(--wp--preset--color--grey);
	text-align: start;
	padding: var(--wp--preset--spacing--30);
	letter-spacing: 0.06em;
}

.gem-slot--light strong {
	display: block;
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: normal;
	text-transform: none;
	color: var(--wp--preset--color--charcoal);
	margin-block-start: 0.5rem;
	/* 300, not 400: the intent is 'not bold', and 400 is a weight this theme
	   does not ship — it would substitute an unpredictable face. */
	font-weight: 300;
}

/* == 11. Motion and focus ================================================= */

:where(a, button, summary, .wp-block-button__link, .gem-field__input):focus-visible {
	outline: 2px solid var(--wp--preset--color--gold);
	outline-offset: 2px;
	border-radius: var(--wp--custom--radius--small);
}

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

/* Skip link for keyboard users. */
.gem-skip-link {
	position: absolute;
	inset-inline-start: var(--wp--preset--spacing--30);
	inset-block-start: -100%;
	z-index: 100;
	background-color: var(--wp--preset--color--charcoal);
	color: var(--wp--preset--color--cream);
	padding: 0.75rem 1.25rem;
	border-radius: var(--wp--custom--radius--small);
	text-decoration: none;
}

.gem-skip-link:focus {
	inset-block-start: var(--wp--preset--spacing--20);
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* == 14. Long-form articles ============================================== */

/*
 * ARTICLE BODY.
 *
 * Set to the prose measure, not the page's 760px content width — long-form
 * reading is the one place on this site where line length matters more than
 * matching the surrounding rhythm.
 *
 * All type here inherits the theme's body face and weight. Nothing in this
 * block names a family, a size in pixels or a colour outside the tokens.
 */
.gem-article {
	max-inline-size: var(--wp--custom--measure--prose);
	margin-inline: auto;
}

.gem-article p {
	margin: 0 0 var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--grey);
}

.gem-article p:last-child {
	margin-block-end: 0;
}

/*
 * h2 inside the body, because the article title is the page h1. The article
 * pattern emits these directly, so the size is stated here rather than relying
 * on a block attribute.
 */
.gem-article__h2 {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--x-large);
	color: var(--wp--preset--color--charcoal);
	margin: var(--wp--preset--spacing--50) 0 var(--wp--preset--spacing--20);
}

.gem-article__h2:first-child {
	margin-block-start: 0;
}

.gem-article__list {
	list-style: none;
	margin: 0 0 var(--wp--preset--spacing--30);
	padding: 0;
	display: grid;
	gap: var(--wp--preset--spacing--20);
}

.gem-article__list li {
	position: relative;
	padding-inline-start: 1.5rem;
	color: var(--wp--preset--color--grey);
}

/* The same facet the eyebrows use, so a list marker reads as part of the brand
   rather than as a browser default. */
.gem-article__list li::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	inset-block-start: 0.55em;
	inline-size: 0.375rem;
	block-size: 0.375rem;
	background-color: var(--wp--preset--color--gold);
	transform: rotate(45deg);
}

/*
 * Pull-aside. A practical instruction the reader should not lose in the prose —
 * marked by a gold rule at the inline start rather than a tinted box, because a
 * filled panel on a page about losing your home reads as an alert.
 */
.gem-article__aside {
	border-inline-start: 3px solid var(--wp--preset--color--gold);
	padding-inline-start: var(--wp--preset--spacing--30);
	margin: var(--wp--preset--spacing--40) 0;
}

.gem-article__aside p {
	margin: 0;
	color: var(--wp--preset--color--charcoal);
}

.gem-article__back {
	/* Same 62ch box as .gem-article, so the link lines up with the text. Font
	   size lives on the <a>: ch scales with the element's own font size. */
	max-inline-size: var(--wp--custom--measure--prose);
	margin: var(--wp--preset--spacing--50) auto 0;
}

.gem-article__back a {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--grey);
	text-underline-offset: 0.25em;
}

.gem-article__back a:hover,
.gem-article__back a:focus-visible {
	color: var(--wp--preset--color--charcoal);
}

/*
 * ARTICLE INDEX.
 *
 * The whole card is one anchor: a larger tap target on a phone, and one stop
 * per card for keyboard and screen-reader users instead of a separate "read
 * more" link doubling every entry.
 */
.gem-artlist {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: var(--wp--preset--spacing--30);
}

.gem-artlist__item {
	display: flex;
}

.gem-artlist__link {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	padding: var(--wp--preset--spacing--40);
	border: 1px solid var(--wp--custom--line--subtle);
	border-radius: var(--wp--custom--radius--small);
	background-color: var(--wp--preset--color--white);
	text-decoration: none;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.gem-artlist__link:hover,
.gem-artlist__link:focus-visible {
	border-color: var(--wp--preset--color--gold);
	box-shadow: var(--wp--custom--shadow--soft);
}

.gem-artlist__title {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--wp--preset--font-size--x-large);
	color: var(--wp--preset--color--charcoal);
	margin: 0 0 var(--wp--preset--spacing--20);
}

.gem-artlist__copy {
	margin: 0 0 var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--grey);
	font-size: var(--wp--preset--font-size--small);
}

.gem-artlist__more {
	margin-block-start: auto;
	font-family: var(--wp--preset--font-family--body);
	font-weight: 700;
	font-size: var(--wp--preset--font-size--label);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--charcoal);
}

@media (min-width: 782px) {
	.gem-artlist {
		/* minmax(0, 1fr): a plain 1fr lets a long unbreakable word widen its column. */
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/*
 * NOT-FOUND PAGE.
 *
 * Given real vertical presence so the footer does not ride up under a short
 * message. Before this the 404 rendered an empty post query, and the page was
 * one grey sentence floating above the footer.
 */
.gem-404 {
	display: flex;
	align-items: center;
	min-block-size: min(60vh, 30rem);
}

/* == 15. Probate concierge referral graphic ============================== */

/*
 * TEMPORARY, TWO VARIANTS. Gerald has not chosen between the radial hub and the
 * flat layout, so both are styled. Delete the losing half, and section 15
 * entirely if he drops the idea.
 *
 * Every colour here is a theme.json token. The supplied previews used hardcoded
 * hex and a Google Fonts link; the hex values already matched the brand palette
 * exactly, so the swap was one for one, and the four faces are the theme's own
 * self hosted files rather than a third party request.
 */

.gem-concierge {
	--gem-hub-size: 560px;
}

/* --- shared ------------------------------------------------------------- */

.gem-concierge__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background-color: var(--wp--preset--color--cream);
	box-shadow: 0 4px 10px -4px rgba(49, 49, 59, 0.25);
	flex: 0 0 auto;
}

.gem-concierge__icon svg {
	inline-size: 24px;
	block-size: 24px;
}

/* --- hub variant -------------------------------------------------------- */

/*
 * FLUID, NOT FIXED.
 *
 * The canvas is square and never wider than the 560px it was designed at, but
 * below that it simply shrinks. Node positions are percentages and the SVG
 * lines live in a viewBox, so the whole diagram scales as one piece.
 *
 * container-type makes cqw units resolve against this box rather than the
 * viewport, so the icons and labels shrink in step with the circle instead of
 * with the browser window.
 */
.gem-concierge__hub {
	/*
	 * The colour the labels use to mask the connector lines behind them. It has
	 * to match the section this diagram sits on, so if the section background
	 * ever changes, change this with it.
	 */
	--gem-concierge-bg: var(--wp--preset--color--white);
	position: relative;
	inline-size: min(var(--gem-hub-size), 100%);
	aspect-ratio: 1;
	block-size: auto;
	margin-inline: auto;
	container-type: inline-size;
}

.gem-concierge__lines {
	position: absolute;
	inset: 0;
	inline-size: 100%;
	block-size: 100%;
}

/*
 * The connector colour is the theme's own hairline token rather than the
 * preview's #e3ddd4, which was a one off tone that appeared nowhere else.
 */
.gem-concierge__lines line {
	stroke: var(--wp--custom--line--strong);
	stroke-width: 2;
}

.gem-concierge__centre {
	position: absolute;
	inset-inline-start: 50%;
	inset-block-start: 50%;
	transform: translate(-50%, -50%);
	/* diameter comes from the pattern so it always matches where the
	   connector lines begin; see patterns/probate-concierge.php */
	inline-size: var(--gem-centre-size, 30.7%);
	block-size: var(--gem-centre-size, 30.7%);
	border-radius: 50%;
	background-color: var(--wp--preset--color--white);
	border: 1px solid var(--wp--custom--line--subtle);
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: var(--wp--custom--shadow--soft);
	z-index: 5;
}

.gem-concierge__centre img {
	inline-size: 64%;
	block-size: auto;
	object-fit: contain;
}

.gem-concierge__nodes {
	list-style: none;
	margin: 0;
	padding: 0;
}

.gem-concierge__node {
	position: absolute;
	/* translate centres the node on its computed point, so the percentage
	   coordinates need no icon-radius subtraction and stay correct at any size */
	transform: translate(-50%, -50%);
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 4;
}

.gem-concierge__node .gem-concierge__icon {
	inline-size: max(38px, 9.2857cqw);
	block-size: max(38px, 9.2857cqw);
}

.gem-concierge__node .gem-concierge__icon svg {
	inline-size: 46.1538%;
	block-size: 46.1538%;
}

.gem-concierge__node .gem-concierge__label {
	position: absolute;
	inset-block-start: 100%;
	inset-inline-start: 50%;
	transform: translateX(-50%);
	margin-block-start: 8px;
	inline-size: max(78px, 19.6429cqw);
	font-family: var(--wp--preset--font-family--body);
	/* floors at 10px so the labels stay legible when the circle is small */
	font-size: max(10px, 2.0571cqw);
	line-height: 1.4;
	color: var(--wp--preset--color--charcoal);
	text-align: center;
	/*
	 * Every spoke runs from the hub to the centre of its icon, and for the nodes
	 * above the hub that path crosses the label on the way. The lines already
	 * paint underneath, but with nothing behind the type they read straight
	 * through it.
	 *
	 * The background is painted per text line rather than as one block, so it
	 * hugs the words instead of stamping a rectangle over the diagram. The line
	 * is interrupted only where there is actually something to read.
	 */
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

.gem-concierge__node .gem-concierge__label span {
	background-color: var(--gem-concierge-bg);
	/*
	 * Horizontal padding only. A spread shadow or vertical padding reaches into
	 * the line above and paints out its descenders, which clipped the g in
	 * "Moving" and "Accounting" on a phone, where the labels wrap most.
	 */
	padding: 0 4px;
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

/* --- flat variant ------------------------------------------------------- */

.gem-concierge__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: var(--wp--preset--spacing--30);
}

.gem-concierge__list li {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--charcoal);
}

.gem-concierge__icon--flat {
	inline-size: 44px;
	block-size: 44px;
}

@media (min-width: 782px) {
	.gem-concierge__list {
		grid-template-columns: repeat(2, 1fr);
		gap: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	}
}

/*
 * MOBILE: THE SAME DIAGRAM, SMALLER.
 *
 * Everything above is proportional, so the radial layout survives down to a
 * phone without a separate list version. What changes here is only breathing
 * room: the labels get a touch tighter so ten of them fit around a smaller
 * circumference without colliding.
 *
 * The earlier attempt at this failed because the node coordinates were absolute
 * pixels for a 560px canvas: shrinking the container left them where they were
 * and they escaped the section entirely. Percentages fixed that at the source.
 */
@media (max-width: 640px) {
	.gem-concierge__node .gem-concierge__label {
		margin-block-start: 6px;
		inline-size: max(66px, 18cqw);
		line-height: 1.2;
	}
}

/* Hero portrait caption: the brokerage attribution, moved here at the client's
   request so it reads as a credit under the photo rather than a standfirst. */
.gem-hero__caption {
	/* Outside the figure: the gold panel overhangs the figure by 1.25rem and
	   would paint over a caption placed inside it. */
	margin-block-start: var(--wp--preset--spacing--40);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
	color: var(--wp--preset--color--grey);
	text-align: center;
	/* Same box as .gem-hero__figure, so the caption centres on the photograph
	   rather than on the column, which is wider and pushed it left. */
	max-inline-size: 21rem;
	margin-inline: auto;
}

@media (min-width: 782px) {
	.gem-hero__caption {
		margin-inline-start: auto;
		margin-inline-end: 1.25rem;
	}
}

@media (max-width: 781px) {
	.gem-hero__caption {
		max-inline-size: min(18rem, 68vw);
		transform: translateX(-0.375rem);
	}
}

/*
 * The two required marks, now supplied. Both are white artwork on transparent.
 *
 * Sized by HEIGHT, not width: the two files have different aspects (300x320 and
 * 275x320) and a shared width would render them at visibly different scales.
 *
 * 4.5rem, not the 3.25rem this started at. The Equal Housing artwork carries the
 * words "EQUAL HOUSING OPPORTUNITY" inside the image, and below roughly this
 * height they stop resolving at all. This is the floor for a legible mark.
 */
.gem-marks__img {
	display: block;
	inline-size: auto;
	block-size: auto;
	max-inline-size: 100%;
	max-block-size: 4.5rem;
}
