/*
Theme Name: El Desierto Casa Estudio
Theme URI: https://eldesierto.mx
Author: Built for Daniel Bitran Arizpe
Description: Bespoke theme for El Desierto Casa Estudio — black canvas, Archivo Condensed, album carousel. Bilingual via Polylang.
Version: 1.0.0
Requires at least: 6.0
Requires PHP: 8.0
License: GPL-2.0-or-later
Text Domain: eldesierto
*/

/* ---------------------------------------------------------------------------
   Fonts — Archivo variable, self-hosted. The design uses Archivo Condensed,
   which is this variable face at font-stretch 75%.
   --------------------------------------------------------------------------- */

@font-face {
	font-family: 'Archivo';
	font-style: normal;
	font-weight: 100 900;
	font-stretch: 62% 125%;
	font-display: swap;
	src: url('assets/fonts/archivo-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Archivo';
	font-style: normal;
	font-weight: 100 900;
	font-stretch: 62% 125%;
	font-display: swap;
	src: url('assets/fonts/archivo-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Archivo';
	font-style: italic;
	font-weight: 100 900;
	font-stretch: 62% 125%;
	font-display: swap;
	src: url('assets/fonts/archivo-italic-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Archivo';
	font-style: italic;
	font-weight: 100 900;
	font-stretch: 62% 125%;
	font-display: swap;
	src: url('assets/fonts/archivo-italic-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------------------------
   Tokens
   --------------------------------------------------------------------------- */

:root {
	--ink: #ffffff;
	--paper: #000000;
	--muted: rgba(255, 255, 255, 0.55);

	--font: 'Archivo', 'Archivo Narrow', 'Helvetica Neue', Arial, sans-serif;
	--condensed: 75%;

	/* Fluid gutter: tracks the design's generous margins but never crowds mobile. */
	--gutter: clamp(1.25rem, 5.5vw, 6.25rem);
	/* Vertical rhythm is budgeted, not decorative: header + main padding +
	   footer have to leave the tallest page (Nosotros) enough room to land the
	   footer above the fold on a laptop. Loosen any of these and the
	   "Contáctanos" line drops off a 800px-tall window again. */
	--header-top: clamp(1rem, 3vh, 2.75rem);

	--logo-w: clamp(112px, 10vw, 176px);

	--nav-size: clamp(0.95rem, 1.15vw, 1.28rem);
	--body-size: clamp(1rem, 1.18vw, 1.32rem);
	--list-size: clamp(1rem, 1.22vw, 1.4rem);
	--caption-size: clamp(0.9rem, 1.02vw, 1.16rem);

	/* Target number of covers visible across. The height cap below can still
	   shrink them further on short windows so every row stays on screen —
	   at which point more than this will fit, which is preferable to clipping
	   the footer. */
	--carousel-cols: 6;
	--carousel-rows: 2;
	--carousel-gap: clamp(0.6rem, 1.1vw, 1.1rem);

	/* Vertical room the carousel actually has, once header, footer and padding
	   are accounted for. Re-measured at 1600x900 after the rhythm was tightened
	   to fit Nosotros on one screen: header 233 + footer 75 + main padding 40 =
	   347px (21.7rem), down from 403px.

	   The constant stays at 26rem on purpose rather than tracking that. Chrome
	   is clamped, so it plateaus around 411px (~25.7rem) on a 2560x1300 window
	   while staying near 280px on a 1280x700 one. A fixed rem has to cover the
	   worst case or the cap lets covers grow taller than the tall-window layout
	   can actually seat, and the footer goes off screen. The cost is that short
	   windows reserve more than they need — smaller covers there, which is the
	   trade this file already makes deliberately.

	   --cover-cap is derived from this on .carousel itself (see below), not
	   here — a custom property resolves var() against the element it is
	   declared on, so computing it at :root would ignore a per-carousel row
	   override. */
	--carousel-chrome: 26rem;
}

/* ---------------------------------------------------------------------------
   Reset
   --------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
	margin: 0;
	background: var(--paper);
	color: var(--ink);
	font-family: var(--font);
	font-stretch: var(--condensed);
	font-weight: 500;
	font-size: var(--body-size);
	line-height: 1.32;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
}

img { max-width: 100%; height: auto; display: block; }

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

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* Visible focus for keyboard users — the design is all-black, so make it obvious. */
a:focus-visible,
button:focus-visible {
	outline: 2px solid var(--ink);
	outline-offset: 3px;
}

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

.skip-link {
	position: absolute; left: -9999px; top: 0;
	background: var(--ink); color: var(--paper);
	padding: 0.6rem 1rem; z-index: 100;
}
.skip-link:focus { left: 0; }

/* ---------------------------------------------------------------------------
   Header — logo left, nav right. Identical on every page.
   --------------------------------------------------------------------------- */

.site-header {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 1.5rem;
	padding: var(--header-top) var(--gutter) 0;
	flex: 0 0 auto;
}

.site-logo { display: block; width: var(--logo-w); flex: 0 0 auto; }
.site-logo img { width: 100%; }

.site-nav {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 0.18em;
	font-size: var(--nav-size);
	font-weight: 500;
	letter-spacing: 0.005em;
	text-transform: uppercase;
	white-space: nowrap;
}

.site-nav ul { list-style: none; margin: 0; padding: 0; }
.site-nav li { display: block; text-align: right; }

/* The leading "+" is decoration, not content — keep it out of the link text
   so the underline sits under the word only, as in the design.
   Scoped to menu links (not every <a>) so the language switcher gets exactly
   one "+", and uses a non-breaking space because HTML would eat a plain one. */
.site-nav ul a::before,
.lang-switch::before {
	content: '+\00a0';
	text-decoration: none;
	display: inline-block;
}

.site-nav a { display: inline-block; padding: 0.06em 0; }
.site-nav a > span { text-underline-offset: 0.16em; text-decoration-thickness: from-font; }
.site-nav a:hover > span,
.site-nav a:focus-visible > span { text-decoration: underline; }
.site-nav .is-active > span { text-decoration: underline; }

.lang-switch { display: block; text-align: right; }
.lang-switch a { display: inline-block; }
.lang-switch .is-active { font-weight: 700; }
.lang-switch a:hover { text-decoration: underline; text-underline-offset: 0.16em; }
.lang-switch .sep { display: inline-block; }

/* ---------------------------------------------------------------------------
   Layout shell
   --------------------------------------------------------------------------- */

.site-main {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	justify-content: center;
	min-height: 0;
	padding: clamp(0.875rem, 2.2vh, 2.25rem) 0;
}

.site-footer {
	flex: 0 0 auto;
	padding: 0 var(--gutter) clamp(1.25rem, 3.5vh, 2.75rem);
	display: flex;
	justify-content: flex-end;
	gap: clamp(1.5rem, 5vw, 4.5rem);
	font-size: var(--caption-size);
	text-align: right;
}

.site-footer .label { display: block; font-weight: 500; }
.site-footer a { text-decoration: underline; text-underline-offset: 0.16em; }
.site-footer a:hover { text-decoration-thickness: 2px; }

/* ---------------------------------------------------------------------------
   Inicio — album carousel
   --------------------------------------------------------------------------- */

.carousel {
	position: relative;
	display: flex;
	align-items: center;
	gap: clamp(0.5rem, 1.6vw, 1.75rem);
	padding: 0 clamp(0.75rem, 2.2vw, 2.5rem);

	/* Declared here so a per-carousel --carousel-rows (Elementor widget or
	   shortcode attribute) is taken into account when capping cover height. */
	--carousel-space: calc(100svh - var(--carousel-chrome));
	/* Rows need more air between them than covers need beside them: a caption
	   carrying two title lines and two artist lines fills its box, so at the
	   plain --carousel-gap the text under row 1 lands ~10px off row 2's covers.
	   Declared here rather than at :root for the same reason as --cover-cap. */
	--carousel-row-gap: calc(var(--carousel-gap) + 0.45rem);
	/*
	 * Height reserved for .album__meta, and *the same variable* the caption box
	 * is sized with — the two cannot drift apart because there is only one of
	 * them. It was previously 5.7em here against height: 5em there, which looks
	 * like it is in step and is not: em on .carousel resolves against
	 * --body-size while em on .album__meta resolves against the caption size, so
	 * the reservation ran ~24px per row heavier than the box it stood in for and
	 * the covers paid for it twice over.
	 *
	 * Deliberately rem, not em: --cover-cap must not depend on the caption font
	 * size, because the caption font size now depends on the cover width, which
	 * depends on --cover-cap. rem breaks that cycle.
	 *
	 * 4.9rem is the budget at the caption's ceiling: padding (0.62em) plus four
	 * clamped lines (4 × 1.2em) is 5.42em, and at the 0.88rem ceiling that is
	 * 4.77rem. Raise the ceiling and this has to follow.
	 */
	--caption-block: 4.9rem;
	--cover-cap: calc(
		(var(--carousel-space) - (var(--carousel-rows) - 1) * var(--carousel-row-gap))
		/ var(--carousel-rows) - var(--caption-block)
	);
	/* Final cover width: the smaller of "fit --carousel-cols across" and
	   "keep every row on screen". */
	--cover-w: min(
		calc((100% - (var(--carousel-cols) - 1) * var(--carousel-gap)) / var(--carousel-cols)),
		var(--cover-cap)
	);
}

.carousel__nav {
	flex: 0 0 auto;
	font-size: clamp(1.1rem, 1.7vw, 1.9rem);
	font-weight: 500;
	line-height: 1;
	padding: 0.5rem 0.35rem;
	transition: opacity 0.15s ease;
}
.carousel__nav:disabled { opacity: 0.18; cursor: default; }
.carousel__nav:not(:disabled):hover { opacity: 0.65; }

/*
 * Each row is its own clipped viewport with its own track, so rows can cycle
 * independently and in opposite directions. carousel.js clones each track's
 * covers until it is at least twice the row width, then translates it; when a
 * full set has scrolled past it wraps by exactly one set, which is seamless
 * because the next set is pixel-identical.
 */
.carousel__rows {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	/* Vertical only — covers still sit --carousel-gap apart horizontally.
	   Kept in step with the --cover-cap formula above. */
	gap: var(--carousel-row-gap);
}

.carousel__row {
	overflow: hidden;
	min-width: 0;
}

/*
 * Deliberately NOT width: max-content. The track must keep a definite width
 * (that of the row) so the percentage inside --cover-w resolves against it;
 * with max-content the percentage has nothing to resolve against and the
 * covers collapse to a fraction of their size. Items simply overflow the
 * track and are clipped by .carousel__row.
 */
.carousel__track {
	display: flex;
	flex-wrap: nowrap;
	gap: var(--carousel-gap);
	align-items: flex-start;
	will-change: transform;
}

/* Before JS runs (and if it never does) the row is still usable: it simply
   scrolls horizontally instead of cycling. */
.no-js .carousel__row,
.carousel__row:not([data-ready]) {
	overflow-x: auto;
	scrollbar-width: none;
}
.carousel__row::-webkit-scrollbar { display: none; }

/* A query container so the caption below can be sized as a share of *this
   cover's* width (cqw) rather than of the viewport. --cover-w cannot be used in
   a font-size directly: it is a min() containing a percentage, and a percentage
   in font-size means "of the parent font size", so it would silently compute
   something entirely unrelated to the cover. Safe to containerise — .album's
   inline size comes from --cover-w, never from its contents, and nothing inside
   is positioned against it. */
.album {
	display: block;
	flex: 0 0 var(--cover-w);
	width: var(--cover-w);
	min-width: 0;
	container-type: inline-size;
}

.album__cover {
	position: relative;
	aspect-ratio: 1 / 1;
	overflow: hidden;
	background: #1a1a1a;
}
.album__cover img {
	width: 100%; height: 100%;
	object-fit: cover;
	transition: opacity 0.2s ease;
}
.album:hover .album__cover img { opacity: 0.82; }

/*
 * Fixed height so every row lines up regardless of how long the album and
 * artist names are — the same --caption-block that --cover-cap reserves.
 *
 * The size is a share of the cover, not of the viewport, and that is the whole
 * point. --cover-w is min(width-share, height-cap), so on a short window the
 * height cap wins and the covers collapse — 141px tall at 1440x900, but 81px at
 * 1440x780 — while a viewport-derived --caption-size barely moved. The caption
 * stayed nearly full size against a cover half the width, which is what pushed
 * "Vendrán Suaves Lluvias" past two lines and into an ellipsis. At 11cqw the
 * caption shrinks exactly as fast as the cover it sits under, so the longest
 * title in the discography ("¿Dónde Bailarán Las Niñas?") keeps fitting.
 *
 * The 0.88rem ceiling is what makes it "a bit smaller" on roomy windows too: it
 * replaces --caption-size, whose own ceiling was 1.16rem. Raising it means
 * raising --caption-block to match, or the fourth line is clipped.
 */
.album__meta {
	padding-top: 0.62em;
	font-size: clamp(0.56rem, 11cqw, 0.88rem);
	line-height: 1.2;
	height: var(--caption-block);
	overflow: hidden;
}
/* Two classes deep for the same reason as .about__follow above. */
.album__meta .album__title,
.elementor .album__title {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	font-weight: 700;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 0.16em;
}
/* Wraps and clamps exactly like the title above it, so "Natalia Lafourcade"
   breaks over two lines instead of being cut to "Natalia Lafou…". */
.album__artist {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	font-weight: 700;
	/* Only bites on short viewports, where the height cap shrinks covers below
	   the width of a single long name ("Lafourcade", "Siddhartha"). Without it
	   such a word is sliced mid-glyph with no ellipsis to signal the cut. */
	overflow-wrap: break-word;
}

.carousel__empty { padding: 2rem 0; color: var(--muted); }

/* ---------------------------------------------------------------------------
   Nosotros — text left, photo bleeding off the right edge
   --------------------------------------------------------------------------- */

.about {
	display: grid;
	/*
	 * The left column is a share of the width, not half of it. With `1fr 1fr`
	 * it was 691px at 1440 while the text only ever fills --about-measure
	 * (357px there), so most of the space before the photo was dead column, not
	 * `gap` — turning `gap` down moved almost nothing. At 0.6fr the band
	 * between paragraph and photo is roughly halved across the desktop range.
	 * The minmax floor keeps the measure intact just above the 860px
	 * breakpoint, where the text needs nearly the whole column; the +4vw on the
	 * floor stops the paragraph ending up flush against the photo there. Above
	 * ~1100px the 0.6fr is always the larger of the two and the floor is moot.
	 */
	--about-measure: 46ch;
	grid-template-columns: minmax(calc(var(--about-measure) + 4vw), 0.6fr) minmax(0, 1fr);
	align-items: center;
	gap: clamp(1.5rem, 4vw, 4.5rem);
}

.about__text {
	padding-left: var(--gutter);
	max-width: var(--about-measure);
	font-size: var(--body-size);
	line-height: 1.34;
}
.about__text p { margin: 0 0 1.35em; }
.about__text p:last-child { margin-bottom: 0; }
.about__text strong { font-weight: 700; }
.about__text em { font-style: italic; }

/*
 * Elementor's frontend.css declares `.elementor a { text-decoration: none }`
 * (specificity 0-1-1), which outranks a single class no matter which sheet
 * loads last. The design depends on these underlines, so the selectors below
 * are deliberately two classes deep (0-2-0) to win inside and outside Elementor.
 */
.about__text .about__follow,
.elementor .about__follow {
	display: inline-block;
	margin-top: 1.9em;
	font-weight: 700;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 0.16em;
}

.about__photo { min-width: 0; margin: 0; }
.about__photo img {
	width: 100%;
	/* Sized so the photo, not the text column, is what has to fit: below about
	   56vh the text becomes the taller of the two and shrinking this further
	   buys nothing. */
	height: clamp(260px, 56vh, 700px);
	object-fit: cover;
	filter: grayscale(1);
}
/* A nested <figure> can arrive from the block editor when the photo is lifted
   out of the page content; flatten it so it does not add its own spacing. */
.about__photo figure { margin: 0; }
.about__photo figcaption { display: none; }

.about__photo--color img { filter: none; }

/* No photo set: let the text use the full width rather than leaving a gap. */
.about--no-photo { grid-template-columns: 1fr; }
.about--no-photo .about__text { max-width: 60ch; }

/* ---------------------------------------------------------------------------
   Artistas — centred column of names
   --------------------------------------------------------------------------- */

.roster {
	padding: 0 var(--gutter);
	display: flex;
	justify-content: center;
}

/* The roster is a single centred column in the design, but it now carries ~140
   names — one column of those is five screens of scrolling. So it flows into as
   many ~15rem columns as the width allows: one on a phone, two on a tablet,
   three on a laptop. column-width does that on its own, with no breakpoints to
   keep in step.

   The Elementor "Columns" control writes column-count over the top when a fixed
   count is wanted. That still reads as a maximum, not a minimum — with both
   properties set the browser uses whichever yields fewer columns — so pinning 3
   here cannot force three columns onto a phone. */
.roster__inner {
	width: min(100%, 62rem);
	font-size: var(--list-size);
	font-weight: 500;
	line-height: 1.5;
	columns: 15rem;
	column-gap: clamp(1.5rem, 4vw, 3.5rem);
}

/* A name that wraps to two lines must not straddle a column break. */
.roster__inner p,
.roster__inner li { margin: 0; break-inside: avoid; }
.roster__inner ul,
.roster__inner ol { list-style: none; margin: 0; padding: 0; }

/* ---------------------------------------------------------------------------
   Reservaciones — the booking enquiry, one question at a time

   The design borrows the header's own idiom rather than inventing a second one:
   options are a "+" list that underlines when chosen, exactly like the nav.
   --------------------------------------------------------------------------- */

.booking {
	--booking-measure: 46rem;
	display: flex;
	justify-content: flex-start;
	padding: 0 var(--gutter);
}

.booking__form {
	width: min(100%, var(--booking-measure));
	/*
	 * .site-main centres its content, so a short question followed by a tall one
	 * would slide the whole block up and down the screen between steps. Holding a
	 * floor under the form keeps the question line still while the answer area
	 * changes shape beneath it.
	 */
	min-height: clamp(17rem, 42vh, 26rem);
}

/* Only the active step is in the flow; the rest are out of the document so they
   cannot be tabbed into or read aloud. */
.bstep { display: none; }
.bstep.is-active {
	display: block;
	animation: bstep-in 0.42s ease both;
}

@keyframes bstep-in {
	from { opacity: 0; transform: translateY(0.5rem); }
	to   { opacity: 1; transform: none; }
}

.bstep__num,
.bstep__eyebrow {
	margin: 0 0 1.1rem;
	font-size: var(--caption-size);
	font-weight: 500;
	letter-spacing: 0.18em;
	color: var(--muted);
}
.bstep__num:empty { display: none; }

.bstep__q {
	margin: 0 0 0.75rem;
	font-size: clamp(1.5rem, 3.1vw, 2.6rem);
	font-weight: 700;
	line-height: 1.08;
	text-transform: uppercase;
	text-wrap: balance;
}
.bstep__q:focus-visible { outline: 2px solid var(--ink); outline-offset: 6px; }

.bstep__optional {
	font-weight: 500;
	text-transform: none;
	color: var(--muted);
	white-space: nowrap;
}

.bstep__note {
	margin: 0 0 1.6rem;
	max-width: 52ch;
	font-size: var(--caption-size);
	line-height: 1.35;
	color: var(--muted);
}
.bstep__note--intro {
	font-size: var(--body-size);
	max-width: 46ch;
	color: var(--ink);
}

/* --- Written answers --- */

.bstep__field { margin-bottom: 0.4rem; }

.bstep__field input,
.bstep__field textarea {
	width: 100%;
	padding: 0.35em 0 0.5em;
	background: transparent;
	border: 0;
	border-bottom: 1px solid var(--ink);
	border-radius: 0;
	outline: none;
	color: var(--ink);
	font-family: var(--font);
	font-stretch: var(--condensed);
	font-weight: 500;
	font-size: clamp(1.15rem, 2vw, 1.6rem);
	line-height: 1.3;
}
.bstep__field textarea {
	font-size: var(--body-size);
	line-height: 1.4;
	min-height: 5em;
	resize: vertical;
}
.bstep__field input::placeholder,
.bstep__field textarea::placeholder {
	color: rgba(255, 255, 255, 0.3);
	font-style: italic;
}
.bstep__field input:focus,
.bstep__field textarea:focus { border-bottom-width: 2px; }

/* Safari paints date inputs light-on-light on a dark page unless told otherwise,
   and leaves the picker icon black on black. */
.bstep__field input[type="date"] { color-scheme: dark; }

/* --- Chosen answers: the nav's "+" idiom --- */

.bopts {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.1em;
	margin-bottom: 0.5rem;
}

.bopt {
	display: flex;
	align-items: baseline;
	gap: 0.45em;
	padding: 0.16em 0;
	font-size: var(--list-size);
	font-weight: 500;
	line-height: 1.3;
	text-align: left;
	color: var(--muted);
	transition: color 0.15s ease;
}
.bopt__mark { flex: 0 0 auto; }

/* Two classes deep on purpose. Elementor's frontend.min.css carries
   `.elementor a { text-decoration: none }` at specificity 0-1-1, which beats a
   single class whatever the load order; the same trap that flattened the album
   titles and the "Síguenos" link. */
.bopt .bopt__label,
.elementor .bopt__label { text-underline-offset: 0.16em; }

.bopt:hover { color: var(--ink); }
.bopt[aria-checked="true"] { color: var(--ink); }
.bopt[aria-checked="true"] .bopt__label,
.elementor .bopt[aria-checked="true"] .bopt__label {
	font-weight: 700;
	text-decoration: underline;
}

.bopts__other { margin: 0.6rem 0 0; }
.bopts__other input {
	width: min(100%, 26rem);
	padding: 0.2em 0 0.35em;
	background: transparent;
	border: 0;
	border-bottom: 1px solid var(--muted);
	border-radius: 0;
	outline: none;
	color: var(--ink);
	font-family: var(--font);
	font-stretch: var(--condensed);
	font-size: var(--body-size);
}
.bopts__other input:focus { border-bottom-color: var(--ink); }

/* --- Moving between questions --- */

.bstep__error {
	margin: 0.7rem 0 0;
	min-height: 1.3em;
	font-size: var(--caption-size);
	font-style: italic;
	color: var(--ink);
}
.bstep.has-error .bstep__field input,
.bstep.has-error .bstep__field textarea { border-bottom-color: var(--ink); border-bottom-width: 2px; }

.bstep__actions {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 0.6em 1.8em;
	margin-top: 1.9rem;
}

.bstep__next,
.bstep__back {
	font-size: var(--nav-size);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.005em;
}

/* The primary action reads like an active nav item: "+" prefix, underlined.
   The "+" itself stays out of the underline, as in the header. display:
   inline-block is what does it — an atomic inline does not inherit the parent's
   text decoration, whereas `text-decoration: none` alone cannot undo it. */
.bstep__next::before {
	content: '+\00a0';
	text-decoration: none;
	display: inline-block;
}
.bstep .bstep__next,
.elementor .bstep__next {
	font-weight: 700;
	text-decoration: underline;
	text-underline-offset: 0.16em;
	text-decoration-thickness: from-font;
}
.bstep__next:hover { text-decoration-thickness: 2px; }
.bstep__next:disabled { color: var(--muted); cursor: default; text-decoration-thickness: from-font; }

.bstep__back { color: var(--muted); order: -1; }
.bstep__back:hover { color: var(--ink); }
.bstep__back[hidden] { display: none; }

.bstep__hint {
	margin-left: auto;
	font-size: var(--caption-size);
	font-style: italic;
	color: var(--muted);
}
.bstep__hint[hidden] { display: none; }

/* --- The opening notice (booking closed) --- */

/* Set off by a rule rather than a coloured box: the design has one ink and one
   ground, and inventing a "warning yellow" for this would be the only colour on
   the site. */
.booking__notice {
	margin: 0 0 1.9rem;
	max-width: 46ch;
	padding-left: 1rem;
	border-left: 2px solid var(--ink);
	font-size: var(--caption-size);
	line-height: 1.4;
	color: var(--muted);
}

/* --- Sent --- */

.bstep--done .bstep__q { margin-bottom: 1rem; }

/* --- Housekeeping --- */

/* The honeypot must be reachable to a bot filling the DOM and invisible to
   everyone else — so it is moved off screen rather than display:none, which
   the better bots know to skip. */
.booking__hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.booking__legal {
	margin: 2.6rem 0 0;
	max-width: 44ch;
	font-size: 0.78rem;
	line-height: 1.4;
	color: var(--muted);
}
.booking .booking__legal a,
.elementor .booking__legal a {
	text-decoration: underline;
	text-underline-offset: 0.16em;
}

/* Google's badge is hidden, which their terms allow only while the attribution
   line above is shown. Remove one and remove the other. */
.grecaptcha-badge { visibility: hidden; }

.booking__preamble { margin-bottom: clamp(1.5rem, 4vh, 3rem); }

@media (max-width: 860px) {
	.booking { padding: 0 var(--gutter); }
	.booking__form { min-height: 0; }
	.bstep__actions { gap: 0.6em 1.4em; }
	.bstep__hint { margin-left: 0; flex-basis: 100%; }
}

@media (prefers-reduced-motion: reduce) {
	.bstep.is-active { animation: none; }
}

/* ---------------------------------------------------------------------------
   Generic page fallback (also what Elementor renders into)
   --------------------------------------------------------------------------- */

.page-body {
	padding: 0 var(--gutter);
	max-width: 60rem;
	margin-inline: auto;
}
.page-body h1, .page-body h2, .page-body h3 { font-weight: 700; text-transform: uppercase; }
.page-body a { text-decoration: underline; text-underline-offset: 0.16em; }

/* ---------------------------------------------------------------------------
   Responsive
   --------------------------------------------------------------------------- */

@media (max-width: 1400px) {
	:root { --carousel-cols: 5; }
}

@media (max-width: 1100px) {
	:root { --carousel-cols: 4; }
}

@media (max-width: 860px) {
	.site-header { align-items: center; }
	.site-nav { font-size: clamp(0.9rem, 2.6vw, 1.1rem); }

	.about {
		grid-template-columns: 1fr;
		gap: clamp(1.5rem, 6vw, 3rem);
	}
	.about__text { padding-left: var(--gutter); padding-right: var(--gutter); max-width: none; }
	.about__photo { order: -1; }
	.about__photo img { height: clamp(220px, 42vh, 420px); }

	.site-footer { justify-content: flex-start; padding-left: var(--gutter); text-align: left; }
}

@media (max-width: 620px) {
	:root {
		--carousel-cols: 2;
		--carousel-rows: 2;
		/* Smaller logo and stacked footer mean less chrome to reserve. */
		--carousel-chrome: 21rem;
	}
	.site-main { justify-content: flex-start; }
	.carousel { padding: 0 0.5rem; }
	.carousel__nav { padding: 0.5rem 0.15rem; }
	.site-footer { flex-direction: column; gap: 0.5rem; }
}

@media (prefers-reduced-motion: reduce) {
	.carousel__viewport { scroll-behavior: auto; }
	* { transition-duration: 0.01ms !important; }
}

/* Print — nobody will, but a black page eats a cartridge. */
@media print {
	body { background: #fff; color: #000; }
	.site-nav, .carousel__nav { display: none; }
}
