/*
 * The About Diana page.
 *
 * The second per-page stylesheet, enqueued only where it is used (plan section
 * 1.1, engineering standards section 7). It loads after components.css and may
 * build on both it and tokens.css; like both of them it declares no colour of
 * its own.
 *
 * MOBILE FIRST, READ BACKWARDS FROM THE MOCKUP. The mockup is authored
 * desktop-first, in `max-width: 920px` blocks. Every one of them appears here as
 * the DEFAULT, with the desktop form restored at 921 px - the same translation
 * components.css performs for the navigation (config/review-rules.md rule 7).
 *
 * WHAT WAS SNAPPED TO THE CANON, and why each one is written down rather than
 * quietly rounded:
 *
 *   RADII. Three bands only - 12-16 for icon boxes, 20-28 for cards, 999 for
 *   pills (sypsena-design SKILL.md, the shapes section), enforced as qa-tokens
 *   T4. This mockup reaches outside them twice: the hero photograph clamps to 32
 *   and the viewer's photograph opens at 10. They move to the nearest value
 *   inside the band - 32 -> 28 and 10 -> 12 - the mapping WPS-020 already used.
 *
 *   SHADOWS. The mockup casts `0 8px 28px rgba(23,28,33,0.05)` under the
 *   qualification cards and `0 10px 26px rgba(23,28,33,0.16)` under a hovered
 *   thumbnail. The first is --shadow-card down to the alpha - the same
 *   0 8px 28px, 0.05 against 0.06 - so only the alpha moves. The second has no
 *   token with that geometry: --shadow-floating (0 12px 32px, 0.18) is the one
 *   carrying the same weight, so the hover lift sits 2 px lower and 6 px softer
 *   than the mockup draws it. The token wins either way, for the reason tokens
 *   exist.
 *
 *   WEIGHTS. The canon names four - 400, 500, 700, 800. The mockup asks for 600
 *   on the hero's role line; it becomes 500, which keeps that line a meta line
 *   instead of promoting it towards the heading above it.
 *
 *   TOUCH TARGETS. The viewer's three round controls are 42 px in the mockup and
 *   44 px here. 44 is the floor invariant I8.2 sets, and a control inside a modal
 *   is not exempt from it.
 */

/* ---------------------------------------------------------------------------
 * Section rhythm
 *
 * Identical to the front page's: no space above, a generous gap below, and the
 * shared 1100 px container. The hero opens the page, so it has space above the
 * fold as well, and the booking block closes it, so its gap is the larger one.
 */

.ap-section {
	padding-block: 0 clamp( 32px, 5vw, 56px );
}

.ap-hero {
	padding-block: clamp( 24px, 4vw, 52px );
}

.ap-booking {
	padding-block: 0 clamp( 40px, 6vw, 72px );
}

/* ---------------------------------------------------------------------------
 * Section heads and shared pieces
 */

.ap-head {
	display: flex;
	flex-direction: column;
	gap: var( --space-2 );
	margin-bottom: clamp( 16px, 2.5vw, 24px );
}

.ap-head .eyebrow,
.ap-head h2 {
	margin: 0;
}

.ap-lead {
	margin: 0;
	line-height: var( --lh-relaxed );
}

/* A reading width the mockup sets on a single paragraph. Deliberately not
 * marked as a container: I11 measures the page's grid, and a paragraph that
 * stops early is a typographic decision rather than a second grid. */
.ap-lead--620 {
	max-width: 620px;
}

/* Trust and location pills. The mint pair measures 4.54:1 and the green pair
 * 5.72:1 - both cleared for text by the 2026-08-13 pass (invariant I15). */

.ap-pills {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var( --space-2 );
	margin: 0;
}

.ap-pill {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 7px 14px;
	border-radius: var( --radius-pill );
	font-size: var( --fs-eyebrow );
	font-weight: var( --fw-bold );
}

/* flex: 0 0 auto on every icon in a flex row, so a narrow phone cannot squeeze
 * a glyph below its declared size (invariant I8.3). */
.ap-pill .material-symbols-outlined {
	flex: 0 0 auto;
	font-size: 15px;
}

.ap-pill--blue {
	background: var( --tint-ice );
	color: var( --color-accent-text );
}

.ap-pill--green {
	background: var( --color-green );
	color: var( --color-green-ink );
}

/* ---------------------------------------------------------------------------
 * Hero
 */

.ap-hero__grid {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( min( 100%, 320px ), 1fr ) );
	align-items: center;
	gap: clamp( 24px, 4vw, 48px );
}

.ap-hero__copy {
	display: flex;
	flex-direction: column;
	gap: var( --space-4 );
}

.ap-hero__title {
	margin: 0;
}

/*
 * The heading keeps base.css's scale rather than the mockup's slightly smaller
 * clamp. One page drawing its own display size is how a type scale stops being
 * one, and the difference is two pixels at the narrow end.
 */

.ap-hero__role {
	margin: 0;
	color: var( --text-meta );
	font-size: var( --fs-sm );
	font-weight: var( --fw-medium );
}

.ap-hero__price {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var( --space-2 );
	margin: 0;
}

.ap-hero__figure {
	color: var( --text-link );
	font-size: var( --fs-price );
	font-weight: var( --fw-black );
}

.ap-hero__unit {
	color: var( --text-meta );
	font-size: var( --fs-caption );
}

/*
 * THE HERO HAS NO CALL TO ACTION ON A PHONE, and here that covers both of them.
 * The sticky bar carries the booking button and the phone call at the bottom of
 * every screen below 921 px, so this row has nothing left to add and would only
 * be the duplicate primary action invariant I12 forbids. The mockup wraps both
 * buttons in .hero-cta itself - this is the page that rule was written for
 * (2026-08-17).
 *
 * The whole row is hidden rather than the buttons inside it: an empty flex row
 * would still spend the column's gap.
 */
.ap-hero__actions {
	display: none;
}

.ap-hero__media {
	position: relative;
}

/*
 * object-position carries the VERTICAL framing only, and after WPS-059 that is
 * the honest description of it.
 *
 * The horizontal half was never adjustable here. Diana's face sits at about
 * 43% of the frame's width, but the file was 1400x1350 against a 494x480 box -
 * near enough the same proportion that `cover` had 3.8px of horizontal travel
 * to give. Every value from 0% to 100% produced the same picture, with her
 * face a good 35px left of the card's centre, which is what Andrius saw on
 * dev. The gallery thumbnails below are unaffected: they are far wider than
 * they are tall, so their own object-position still has real room to move.
 *
 * So the file changed instead: re-cropped from the 2017 original (frame 132,
 * 4016x3871+0+0), right edge trimmed to 3400 so her face lands on the middle,
 * exported at 1185x1349. The whole photograph is still one `git show` and one
 * crop away in assets/ - and, unlike a CSS value, the new file is now taller
 * than the box in proportion, which is what gives the 40% below something to
 * act on at last. docs/fotosesija-2017.md records the new geometry.
 */
.ap-hero__photo {
	width: 100%;
	height: clamp( 320px, 42vw, 480px );
	border-radius: clamp( 20px, 2.5vw, 28px );
	object-fit: cover;
	object-position: 50% 40%;
}

/* ---------------------------------------------------------------------------
 * The founding story
 */

.ap-story__grid {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( min( 100%, 300px ), 1fr ) );
	align-items: start;
	gap: clamp( 20px, 3vw, 40px );
}

.ap-story__copy {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.ap-story__copy .eyebrow,
.ap-story__copy h2 {
	margin: 0;
}

.ap-story__text {
	margin: 0;
	color: var( --text-body );
	line-height: var( --lh-body );
}

/*
 * The voice panel. Centred with a reading width on the quotation, which is what
 * the twenty-third wave settled: a quotation that runs the full width of a mint
 * card stops reading as speech.
 */
.ap-story__panel {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 14px;
	margin: 0;
	padding: clamp( 24px, 3.5vw, 40px );
	background: var( --color-mint );
	border-radius: var( --radius-2xl );
	text-align: center;
}

.ap-story__quote {
	max-width: 460px;
	margin: 0;
	color: var( --text-heading );
	font-size: clamp( 18px, 2.2vw, 23px );
	font-style: italic;
	font-weight: var( --fw-medium );
	line-height: var( --lh-snug );
	text-wrap: pretty;
}

.ap-story__sign {
	margin: 0;
	color: var( --color-mint-ink );
	font-size: clamp( 22px, 3vw, 27px );
	line-height: var( --lh-tight );
}

.ap-visit__quote {
	margin: 4px 0;
}

/* ---------------------------------------------------------------------------
 * Photographs from work
 *
 * The mockup's own track, transferred as written. It was worth checking rather
 * than assuming, because the front page needed hand-computed breakpoints for its
 * three-card rows (876 and 944) and this looked like the same shape: an odd item
 * left over on the last row. It is not. A grid item occupies ONE track, so the
 * fourth photograph between roughly 675 and 905 px sits alone at the width of
 * its neighbours rather than stretching across the row - measured against the
 * mockup at nine widths from 390 to 1440, where the two agree on the column
 * count everywhere. The front page's problem was a flex fallback, which is what
 * actually stretches.
 */

/*
 * THREE ACROSS, AND THE ODD ROW CENTRED (Andrius, 2026-08-29).
 *
 * With a fifth photograph the auto-fit grid put four on the first row and left
 * the fifth alone at the left edge - a long row and a stub, with the whole
 * right-hand side of the second row empty. Three and two fills the space and
 * reads as a block.
 *
 * FLEX RATHER THAN GRID, and only for this reason: a grid item always occupies
 * one track, so a short last row stays left-aligned and no `justify-content`
 * on the container moves it. Flex items are laid out along the line, so the
 * line itself can be centred. This is the same construction the mockups' own
 * `.g3-center` uses for exactly this case.
 *
 * The gap is named once and reused inside the basis: three columns need the
 * row's width minus two gaps, divided by three. Written any other way the two
 * numbers drift and the third card wraps.
 */
.ap-gallery__grid {
	--ap-gallery-gap: clamp( 10px, 1.5vw, 16px );

	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( min( 100%, 200px ), 1fr ) );
	gap: var( --ap-gallery-gap );
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * 700px is where three 200px cards plus their two gaps genuinely fit inside the
 * gutters, so below it the auto-fit grid above keeps deciding for itself - one
 * column on a phone, two on a large one. Measured rather than rounded: at this
 * width the content box is 700 - 2 * 28 = 644, and three cards need
 * 3 * 200 + 2 * 16 = 632.
 */
@media ( min-width: 700px ) {

	.ap-gallery__grid {
		display: flex;
		flex-wrap: wrap;
		justify-content: center;
	}

	.ap-gallery__item {
		flex: 0 0 calc( ( 100% - 2 * var( --ap-gallery-gap ) ) / 3 );
	}
}

.ap-shot {
	position: relative;
	display: block;
	overflow: hidden;
	background: var( --tint-panel );
	border-radius: clamp( 14px, 1.8vw, 20px );
	cursor: zoom-in;
	transition: box-shadow var( --dur ) var( --ease );
}

.ap-shot:hover {
	box-shadow: var( --shadow-floating );
}

.ap-shot__image {
	width: 100%;
	height: clamp( 150px, 19vw, 220px );
	object-fit: cover;
}

/*
 * One modifier per photograph. The crop belongs in the stylesheet rather than in
 * a style attribute, and the files hold the whole frame, so a portrait shot can
 * sit in a landscape strip and still open uncropped (docs/fotosesija-2017.md).
 */

.ap-shot__image--welcome {
	object-position: 50% 42%;
}

.ap-shot__image--treatment {
	object-position: 50% 38%;
}

.ap-shot__image--advice {
	object-position: 50% 45%;
}

.ap-shot__image--handpiece {
	object-position: 50% 55%;
}

/* Measured in the browser, not guessed - see the note on the hero above. */
.ap-shot__image--model {
	object-position: 50% 12%;
}

.ap-shot__zoom {
	position: absolute;
	right: var( --space-2 );
	bottom: var( --space-2 );
	display: flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	/* White at 92 % over the photograph, as drawn. */
	background: rgba( 255, 255, 255, 0.92 );
	border-radius: 50%;
	color: var( --text-heading );
	font-size: 16px;
}

/* ---------------------------------------------------------------------------
 * The full-screen viewer
 *
 * z-index 95, which is the mockup's own number and the only one that works: the
 * sticky bar sits at 60 and the header at 50, so anything lower would open
 * behind them, and the skip link at 100 has to stay reachable above everything.
 */

.ap-viewer {
	position: fixed;
	z-index: 95;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: clamp( 12px, 3vw, 32px );
	/* The ink token at 86 %, which is what the mockup paints. Written as rgba
	 * because a custom property cannot be given an alpha without a channel
	 * token, and the same three numbers are --color-ink. */
	background: rgba( 23, 28, 33, 0.86 );
	backdrop-filter: blur( 4px );
	cursor: zoom-out;
}

/* display:flex above would otherwise beat the hidden attribute's own
 * display:none, and the viewer would be open on every page load. */
.ap-viewer[hidden] {
	display: none;
}

.ap-viewer__dialog {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var( --space-3 );
	width: 100%;
	max-width: 1000px;
	cursor: auto;
}

.ap-viewer__image {
	max-width: 100%;
	max-height: 78vh;
	border-radius: clamp( 12px, 1.4vw, 16px );
	object-fit: contain;
}

.ap-viewer__controls {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0;
}

.ap-viewer__nav,
.ap-viewer__close {
	display: flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	cursor: pointer;
	transition: background var( --dur ) var( --ease );
}

.ap-viewer__nav {
	/* White at 14 % over the scrim: a control surface rather than text, so the
	 * 3:1 rule applies to the glyph on it, which is full white. */
	background: rgba( 255, 255, 255, 0.14 );
	color: var( --color-surface );
}

.ap-viewer__nav:hover {
	background: rgba( 255, 255, 255, 0.26 );
}

.ap-viewer__nav .material-symbols-outlined,
.ap-viewer__close .material-symbols-outlined {
	font-size: 22px;
}

.ap-viewer__counter {
	min-width: 52px;
	margin: 0;
	/* White at 78 % over the composited scrim. The scrim is translucent, so the
	 * ratio follows the page behind it: sampled from the render it runs 7.6:1
	 * near the top of the page and 7.7:1 further down, clear of the 4.5:1 floor
	 * either way. */
	color: rgba( 255, 255, 255, 0.78 );
	font-size: var( --fs-meta );
	text-align: center;
}

/*
 * Fixed to the viewport rather than to the dialog. The dialog's height follows
 * the photograph, and a portrait frame and a landscape frame would put the close
 * button in two different places (docs/design-zurnalas.md, wave 27).
 */
.ap-viewer__close {
	position: fixed;
	top: clamp( 10px, 2vw, 22px );
	right: clamp( 10px, 2vw, 22px );
	background: rgba( 255, 255, 255, 0.92 );
	color: var( --text-heading );
}

.ap-viewer__close:hover {
	background: var( --color-surface );
}

/* Set on <body> while the viewer is open, so the page underneath cannot be
 * scrolled away from behind it. */
.ap-viewer-open {
	overflow: hidden;
}

/* ---------------------------------------------------------------------------
 * Qualifications
 */

.ap-quals__pair {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( min( 100%, 280px ), 1fr ) );
	gap: clamp( 14px, 2vw, 20px );
}

.ap-quals__pair--wide {
	grid-template-columns: repeat( auto-fit, minmax( min( 100%, 300px ), 1fr ) );
	margin-top: clamp( 14px, 2vw, 20px );
}

/* Two items per row and never an odd one, so auto-fit is safe here in a way it
 * is not in the gallery above. */

.ap-fact {
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding: clamp( 20px, 2.6vw, 26px );
	background: var( --surface-card );
	border-radius: var( --radius-lg );
	box-shadow: var( --shadow-card );
}

.ap-fact__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 46px;
	height: 46px;
	margin: 0;
	border-radius: 50%;
}

.ap-fact__icon--green {
	background: var( --color-green );
	color: var( --color-green-ink );
}

.ap-fact__icon--blue {
	background: var( --tint-ice );
	color: var( --color-accent-text );
}

.ap-fact__icon .material-symbols-outlined {
	font-size: 24px;
}

.ap-fact__label {
	margin: 0;
	color: var( --text-meta );
	font-size: var( --fs-eyebrow );
	font-weight: var( --fw-bold );
	letter-spacing: var( --ls-label );
	text-transform: uppercase;
}

.ap-fact__title {
	margin: 0;
	color: var( --text-heading );
	font-weight: var( --fw-black );
}

/* The licence number cannot break across lines. At 390 px it split through its
 * own hyphen - "BPL-" above and "06771" below - which is AS-69. */
.ap-fact__title span {
	white-space: nowrap;
}

.ap-fact__meta {
	margin: 0;
	color: var( --text-meta );
	font-size: var( --fs-caption );
}

.ap-card {
	padding: clamp( 20px, 2.6vw, 28px );
	background: var( --surface-card );
	border-radius: var( --radius-lg );
	box-shadow: var( --shadow-card );
}

.ap-card__title {
	margin: 0 0 18px;
	color: var( --text-heading );
	font-size: var( --fs-body );
	font-weight: var( --fw-black );
}

/* ---------------------------------------------------------------------------
 * Experience
 */

.ap-track__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.ap-track__item {
	position: relative;
	padding: 0 0 20px 22px;
	border-left: 2px solid var( --border-hairline );
}

/* The last entry keeps the indent but drops the line, so the timeline ends at
 * its last dot instead of trailing past it. */
.ap-track__item:last-child {
	padding-bottom: 0;
	border-left-color: transparent;
}

.ap-track__item::before {
	content: "";
	position: absolute;
	top: 2px;
	left: -7px;
	width: 12px;
	height: 12px;
	background: var( --tint-ice );
	border: 2px solid var( --surface-card );
	border-radius: 50%;
}

.ap-track__item--current::before {
	background: var( --color-accent );
}

.ap-track__period {
	margin: 0;
	color: var( --text-meta );
	font-size: var( --fs-eyebrow );
	font-weight: var( --fw-bold );
}

.ap-track__item--current .ap-track__period {
	color: var( --text-link );
}

.ap-track__place {
	margin: 0;
	color: var( --text-heading );
	font-size: var( --fs-sm );
	font-weight: var( --fw-bold );
}

.ap-track__role {
	margin: 0;
	color: var( --text-meta );
	font-size: var( --fs-meta );
}

/* ---------------------------------------------------------------------------
 * Courses
 */

.ap-courses {
	display: flex;
	flex-direction: column;
}

/*
 * The first course row carries 12 px of padding above its text and the first
 * experience entry carries none, so the mockup pairs this title with 8 px where
 * the other gets 18 and the two lists start level with each other. Sharing the
 * 18 px pushed the course list 10 px below where it was drawn.
 */
.ap-courses .ap-card__title {
	margin-bottom: var( --space-2 );
}

.ap-courses__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.ap-courses__item {
	display: flex;
	align-items: center;
	gap: var( --space-3 );
	padding: var( --space-3 ) 0;
	border-bottom: 1px solid var( --tint-panel-cool );
}

.ap-courses__item .material-symbols-outlined {
	flex: 0 0 auto;
	color: var( --text-link );
	font-size: 20px;
}

.ap-courses__name {
	flex: 1;
	color: var( --text-heading );
	font-size: var( --fs-caption );
	line-height: 1.35;
}

.ap-courses__year {
	flex: 0 0 auto;
	color: var( --text-meta );
	font-size: var( --fs-meta );
	font-weight: var( --fw-bold );
}

/*
 * The collapsed state is applied by main.js, never by this file on its own.
 * Printed without JavaScript the list stays whole and the control stays hidden,
 * which is the only arrangement in which a visitor without JavaScript is not
 * left reading half a list with no way to the rest.
 */
.ap-courses__list[ data-collapsed="true" ] .ap-courses__item--extra {
	display: none;
}

/* 12 px of padding above and below a 20 px line makes a 44 px target out of a
 * control that only looks like 20 px, and the negative margin gives the extra
 * space back to the layout (invariant I8.2). */
.ap-courses__toggle {
	display: inline-flex;
	align-self: flex-start;
	align-items: center;
	gap: 6px;
	margin: 2px 0 -12px;
	padding: var( --space-3 ) 0;
	background: none;
	border: 0;
	color: var( --text-link );
	font-family: var( --font-sans );
	font-size: var( --fs-caption );
	font-weight: var( --fw-bold );
	cursor: pointer;
}

.ap-courses__toggle[hidden] {
	display: none;
}

.ap-courses__toggle .material-symbols-outlined {
	flex: 0 0 auto;
	font-size: 18px;
}

/* ---------------------------------------------------------------------------
 * What the visit looks like
 */

.ap-visit__grid {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( min( 100%, 300px ), 1fr ) );
	align-items: start;
	gap: clamp( 20px, 3vw, 36px );
}

.ap-visit__copy {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.ap-visit__copy .eyebrow,
.ap-visit__copy h2 {
	margin: 0;
}

.ap-visit__text {
	margin: 0;
	color: var( --text-body );
	line-height: var( --lh-body );
}

.ap-visit__card {
	display: flex;
	flex-direction: column;
	gap: 14px;
	padding: clamp( 20px, 3vw, 28px );
	background: var( --surface-card );
	border-radius: var( --radius-xl );
	box-shadow: var( --shadow-card );
}

.ap-visit__title {
	margin: 0;
	color: var( --text-heading );
	font-size: var( --fs-lead );
	font-weight: var( --fw-bold );
}

.ap-visit__list {
	display: flex;
	flex-direction: column;
	gap: 14px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ap-visit__list li {
	display: flex;
	align-items: flex-start;
	gap: var( --space-3 );
}

.ap-visit__list .material-symbols-outlined {
	flex: 0 0 auto;
	color: var( --text-link );
	font-size: 22px;
}

/* The second child of each row: either one line of text, or a term with a
 * description under it. One rule covers both. */
.ap-visit__list li > span:last-child {
	display: flex;
	flex-direction: column;
	gap: 2px;
	color: var( --text-body );
	font-size: var( --fs-caption );
	line-height: 1.5;
}

.ap-visit__term {
	color: var( --text-heading );
	font-weight: var( --fw-bold );
	line-height: 1.4;
}

.ap-visit__desc {
	color: var( --text-meta );
	font-size: var( --fs-meta );
	line-height: 1.5;
}

.ap-visit__more {
	margin: -10px 0 -12px;
}

/*
 * An inline link inside a paragraph, given its target height by padding. The
 * negative margins on the paragraph hand the extra space back, so the card's
 * rhythm is unchanged (invariant I8.2).
 */
.ap-visit__more a {
	display: inline-flex;
	align-items: center;
	gap: var( --space-2 );
	padding: var( --space-3 ) 0;
	font-size: var( --fs-caption );
	font-weight: var( --fw-bold );
	text-decoration: none;
}

.ap-visit__more .material-symbols-outlined {
	flex: 0 0 auto;
	font-size: 18px;
}

/* ---------------------------------------------------------------------------
 * Booking
 *
 * The same block the front page carries, and deliberately the same values: both
 * mockups draw one panel, and two pages drifting apart on it would be visible
 * the moment a visitor moves between them.
 */

.ap-booking__panel {
	display: grid;
	grid-template-columns: 1fr;
	align-items: center;
	gap: clamp( 24px, 4vw, 48px );
	padding: clamp( 24px, 4vw, 48px );
	background: var( --surface-inverse );
	border-radius: clamp( 20px, 2.5vw, 28px );
}

.ap-booking__copy {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.ap-booking__eyebrow {
	margin: 0;
	color: var( --color-surface );
	font-size: var( --fs-eyebrow );
	font-weight: var( --fw-bold );
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.ap-booking__title {
	margin: 0;
	color: var( --color-surface );
}

/* White at 65 % over the ink panel: 7.9:1, measured against the composited
 * value rather than against white. */
.ap-booking__lead {
	margin: 0;
	color: rgba( 255, 255, 255, 0.65 );
	font-size: var( --fs-sm );
	line-height: var( --lh-body );
}

.ap-booking__card {
	display: flex;
	flex-direction: column;
	gap: var( --space-4 );
	padding: clamp( 18px, 3vw, 26px );
	background: var( --surface-card );
	border-radius: var( --radius-xl );
}

/* ---------------------------------------------------------------------------
 * The desktop form
 */

@media ( min-width: 921px ) {

	.ap-hero__actions {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: var( --space-3 );
		margin: 0;
	}

	/*
	 * The panel becomes two columns only here. An auto-fit grid would already
	 * have split it around 700 px, and the design forbids exactly that: when one
	 * half of a two-column section is a working widget, the widget needs the
	 * width (the mockups' .rez-grid rule).
	 */
	.ap-booking__panel {
		grid-template-columns: repeat( auto-fit, minmax( min( 100%, 300px ), 1fr ) );
	}
}
