/*
Theme Name:   Diana Anna
Theme URI:    https://diana-anna.ch
Author:       Maksim Volkmann
Author URI:   https://volkmann.lt
Description:  One-page theme for Diana Anna, pianist.
Version:      0.12.4
Requires at least: 6.0
Requires PHP: 7.4
License:      GNU General Public License v2 or later
License URI:  https://www.gnu.org/licenses/gpl-2.0.html
Text Domain:  diana-anna
Domain Path:  /languages
*/

/* Fonts: self-hosted in assets/fonts/ (from the @fontsource npm packages, SIL Open Font
   License, see the OFL-*.txt files there), so nothing loads from Google's servers.
   Only what the theme uses: Cormorant Garamond 400, Jost 400 and 400 italic.
   Each in two files: latin (includes German umlauts and ß) and latin-ext (other accented
   letters); the browser only downloads latin-ext if the page contains such a letter
   (unicode-range). The latin files of the two regular faces are preloaded (functions.php). */
@font-face {
	font-family: "Cormorant Garamond";
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url("assets/fonts/cormorant-garamond-latin-400-normal.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: "Cormorant Garamond";
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url("assets/fonts/cormorant-garamond-latin-ext-400-normal.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: "Jost";
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url("assets/fonts/jost-latin-400-normal.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: "Jost";
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url("assets/fonts/jost-latin-ext-400-normal.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: "Jost";
	font-style: italic;
	font-weight: 400;
	font-display: swap;
	src: url("assets/fonts/jost-latin-400-italic.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: "Jost";
	font-style: italic;
	font-weight: 400;
	font-display: swap;
	src: url("assets/fonts/jost-latin-ext-400-italic.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;
}

:root {
	/* Palette */
	--cream: #FCF3EC;
	--pink: #F4DCE2;
	--pink-pale: #FAE9E8;
	--text: #2E201F;
	--text-muted: #896F69;
	--accent: #83151C;

	/* Fonts (@font-face above), with fallbacks while they load or if they fail */
	--font-heading: "Cormorant Garamond", Georgia, serif;
	--font-body: "Jost", system-ui, sans-serif;

	/* Height of the WordPress admin bar; 0 when it is not shown (see below). */
	--admin-bar: 0px;
}

/* Logged-in visitors see the admin bar: WordPress adds .admin-bar to <body> and pushes
   the page down (html { margin-top }). Full-height layout subtracts --admin-bar and
   everything fixed to the top moves down by it. Sizes match WordPress's own CSS.
   Up to 600px wide WordPress makes the bar absolute (it scrolls away); fixed items still
   start below it, so they are never hidden under it at the top of the page. */
body.admin-bar {
	--admin-bar: 32px;
}

@media (max-width: 782px) {
	body.admin-bar {
		--admin-bar: 46px;
	}
}


/* Base */

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

body {
	margin: 0;
	background: var(--cream);
	color: var(--text);
	font-family: var(--font-body);
	font-size: 1.0625rem;
	line-height: 1.7;
}

h1,
h2,
h3,
h4 {
	font-family: var(--font-heading);
	font-weight: 400;
	line-height: 1.15;
}

a {
	color: var(--accent);
}

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

:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 3px;
}

/* Visually hidden, still read by screen readers. */
.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.skip-link:focus {
	position: fixed;
	top: calc(1rem + var(--admin-bar));
	left: 1rem;
	z-index: 100;
	width: auto;
	height: auto;
	margin: 0;
	padding: 0.75rem 1.25rem;
	clip: auto;
	background: var(--cream);
	color: var(--text);
}

@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

/* Layout: fixed photo left, panel right (title, menu, content area, footer) */

.site {
	display: grid;
	grid-template-columns: 1fr 1fr;
	height: calc(100vh - var(--admin-bar));
	height: calc(100dvh - var(--admin-bar)); /* dvh excludes mobile browser bars where supported. */
}

.site-photo {
	position: relative;
	overflow: hidden;
	background: var(--pink); /* Shown if there is no photo at all. */
}

.site-photo__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center bottom;
}

/* A column: header and footer keep their size, the content area takes the rest.
   Positioned, so the page dots and the back button can sit on its right edge.
   --panel-pad-bottom and --footer-line are shared with the back button, which sits just
   above the footer line. */
.site-panel {
	--panel-pad-bottom: clamp(0.75rem, 1.5vh, 1.25rem);
	--footer-line: 1.125rem; /* The footer's one line: 0.75rem × line-height 1.5. */
	position: relative;
	display: flex;
	flex-direction: column;
	min-height: 0;
	overflow: hidden;
	padding: clamp(2rem, 5vh, 4.5rem) clamp(2rem, 6vw, 6rem) var(--panel-pad-bottom);
}

.site-header {
	flex: none;
}

.site-title {
	margin: 0;
	font-family: var(--font-heading);
	font-size: clamp(2rem, 3.4vw, 3.25rem);
	font-weight: 400;
	line-height: 1.1;
	letter-spacing: 0.12em;
}

.site-title a {
	color: var(--text);
	text-decoration: none;
}

.site-tagline {
	margin: 0.5rem 0 0;
	color: var(--text-muted);
	font-size: 0.925rem; /* 14.8px: at 12.8px Windows snapped some stems to the pixel grid (uneven letters). */
	letter-spacing: 0.3em;
	text-transform: uppercase;
}

.site-nav {
	margin-top: clamp(1.5rem, 4vh, 3rem);
}

.site-nav .menu {
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-nav a {
	display: inline-block;
	padding: 0.15rem 0;
	border-bottom: 1px solid transparent;
	color: var(--text);
	font-size: 0.85rem;
	letter-spacing: 0.18em;
	text-decoration: none;
	text-transform: uppercase;
}

.site-nav a:hover {
	border-bottom-color: currentColor;
}

.site-nav a[aria-current] {
	color: var(--accent);
}

/* Menu item classes (Appearance → Menus → CSS Classes). Each changes one thing,
   so they combine: "prime italic" gives both. */
.site-nav .prime > a {
	color: var(--accent);
}

.site-nav .italic > a {
	font-style: italic;
}

.menu-toggle {
	display: none;
}

/* EN | DE switcher (diana_the_language_switcher()): small and quiet, top right of the
   right panel, above the title. On phones it floats beside the hamburger button. */
.lang-switch {
	flex: none;
	margin-bottom: 0.75rem;
	font-size: 0.75rem;
	letter-spacing: 0.18em;
	line-height: 1;
}

.lang-switch ul {
	display: flex;
	justify-content: flex-end;
	margin: 0;
	padding: 0;
	list-style: none;
}

.lang-switch li {
	display: flex;
	align-items: center;
}

.lang-switch a,
.lang-switch__current {
	display: inline-block;
	padding: 0.35rem 0.3rem; /* Enough to be a comfortable click target. */
}

.lang-switch a {
	color: var(--text);
	text-decoration: none;
}

.lang-switch a:hover {
	color: var(--accent);
}

.lang-switch__current {
	color: var(--accent);
}

.lang-switch__sep {
	color: var(--text-muted);
}

/* Content area: scrolls on its own (e.g. Privacy Policy page). */
.site-main {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	margin-top: clamp(1.5rem, 4vh, 3rem);
}

.site-footer {
	flex: none;
	margin-top: 1.25rem;
	color: var(--text-muted);
	font-size: 0.75rem;
	line-height: 1.5;
	text-align: center; /* Under the centred menu. */
}

.site-footer p {
	margin: 0;
}

.site-footer__sep {
	margin: 0 0.5em;
}

/* Small text: the link in --text (--text-muted is below 4.5:1 there). */
.site-footer a {
	color: var(--text);
	text-decoration: none;
}

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

/* Page content */

.panel__title,
.entry__title {
	margin: 0 0 1.25rem;
	font-size: clamp(1.75rem, 2.6vw, 2.5rem);
}

/* Page content (.content): what the client writes with native blocks, on every page.
   Built for long reference lists such as the repertoire: quiet headings, tight lists. */

.content {
	overflow-wrap: break-word; /* Long unbroken strings wrap instead of overflowing. */
}

.content > :first-child {
	margin-top: 0;
}

.content > :last-child {
	margin-bottom: 0;
}

.content p {
	margin: 0 0 1rem;
}

/* h2, a category (e.g. Solo Works): a small spaced-out label like the menu items,
   with a pink hairline. Smaller than the page title, so it structures without shouting.
   --text, not --text-muted: muted is 4.2:1 on cream, below AA for text this small. */
.content h2 {
	margin: 2.75rem 0 1rem;
	padding-bottom: 0.4rem;
	border-bottom: 1px solid var(--pink);
	font-family: var(--font-body);
	font-size: 0.8rem;
	font-weight: 400;
	letter-spacing: 0.2em;
	line-height: 1.4;
	text-transform: uppercase;
}

/* h3, a name within a category (e.g. a composer): the heading serif, modest size. */
.content h3 {
	margin: 1.75rem 0 0.35rem;
	font-size: 1.35rem;
}

/* A composer straight after its category needs less space above it. */
.content h2 + h3 {
	margin-top: 0;
}

/* Lists. Markers sit outside the text ("list-style-position: outside" is the default),
   so a wrapped line lines up with the start of its own item's text, at every level.
   The padding is the indent; it is in em, so it scales with the text. */
.content ul,
.content ol {
	margin: 0 0 1rem;
	padding-left: 1.25em;
}

.content li {
	line-height: 1.45; /* Tighter than body text, so a long list stays scannable. */
}

.content li + li {
	margin-top: 0.2em;
}

/* Level 1: a small muted dot. */
.content ul {
	list-style-type: disc;
}

.content li::marker {
	color: var(--text-muted);
	font-size: 0.8em;
}

.content ol {
	list-style-type: decimal;
}

.content ol > li::marker {
	font-size: 0.9em;
	font-variant-numeric: tabular-nums;
}

/* Levels 2 and 3 (sub-works): indented, slightly smaller, with a quiet dash.
   Browsers that do not know string markers keep the "circle" fallback. */
.content li > ul,
.content li > ol {
	margin: 0.2em 0 0;
	font-size: 0.94em;
}

.content li > ul {
	list-style-type: circle;
	list-style-type: "– ";
}

.content li > ul > li::marker {
	font-size: 1em; /* The dash is already light; keep it level with the text. */
}

/* Level 3 keeps level 2's size (no further shrinking); the indent shows the level.
   Text stays --text for contrast; only the markers are muted. */
.content li li > ul,
.content li li > ol {
	font-size: 1em;
}

/* Events ([upcoming_events], [event_archive]): one month at a time, with arrows
   (assets/js/events.js). Each entry is a narrow date column and the details beside it,
   so it reads well in the narrow right panel. */

/* The list is a size container: the poster's place follows the list's own width
   (see @container below), not the screen's, so it also adapts to the panel. */
.events {
	container-type: inline-size;
}

.events__month[hidden],
.events__nav[hidden] {
	display: none;
}

.events__month-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding-bottom: 0.4rem;
	border-bottom: 1px solid var(--pink);
}

/* A small spaced label, like the h2 categories of .content, so the month
   does not compete with the page title. */
.content .events__month-title {
	margin: 0;
	font-family: var(--font-body);
	font-size: 0.8rem;
	font-weight: 400;
	letter-spacing: 0.2em;
	line-height: 1.4;
	text-transform: uppercase;
}

.events__month + .events__month {
	margin-top: 2.5rem; /* Without JS, when all months are shown one after the other. */
}

/* With the pager, one month is shown; the hidden ones still count as siblings for "+". */
.events.is-paged .events__month {
	margin-top: 0;
}

.events__nav {
	display: flex;
	flex: none;
	gap: 0.25rem;
}

.events__arrow {
	display: grid;
	place-items: center;
	width: 2.25rem;
	height: 2.25rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: none;
	color: var(--text);
	cursor: pointer;
}

.events__arrow:hover:not(:disabled) {
	background: var(--pink);
}

.events__arrow:disabled {
	opacity: 0.3;
	cursor: default;
}

/* Overrides the list styles of .content: no markers, no indent. */
.content .events__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.content .event {
	display: grid;
	grid-template-columns: 3.25rem minmax(0, 1fr);
	gap: 0 1.25rem;
	margin: 0;
	padding: 1.25rem 0;
	line-height: 1.5;
}

.event + .event {
	border-top: 1px solid var(--pink);
}

.content .event__date {
	margin: 0;
	text-align: center;
	line-height: 1.15;
}

.event__date time {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.event__weekday,
.event__month {
	font-size: 0.7rem;
	letter-spacing: 0.15em;
	text-transform: uppercase;
}

.event__day {
	margin: 0.1rem 0;
	font-family: var(--font-heading);
	font-size: 1.9rem;
	line-height: 1;
}

.event__time {
	margin-top: 0.5rem;
	font-size: 0.8rem;
	font-variant-numeric: tabular-nums;
}

.content .event__title {
	margin: 0 0 0.2rem;
	font-size: 1.2rem;
	line-height: 1.25;
}

/* External link icon after the title. The padding makes a 24px click target;
   the negative margin keeps it from pushing the lines apart. */
.event__link {
	display: inline-flex;
	margin: -0.3rem 0 -0.3rem 0.05rem;
	padding: 0.3rem;
	color: var(--text-muted);
	vertical-align: -0.1em;
}

.event__link:hover {
	color: var(--accent);
}

/* Venue on one line, city below it. */
.content .event__place {
	margin: 0;
	font-size: 0.9rem;
}

.event__venue,
.event__city {
	display: block;
}

.event__description {
	margin-top: 0.5rem;
	font-size: 0.95rem;
}

.content .event__description p {
	margin: 0 0 0.5rem;
}

.content .event__description p:last-child {
	margin-bottom: 0;
}

/* Poster thumbnail, a supporting detail. Narrow list: below the details.
   Wide enough list: a column of its own to the right. Opens in the lightbox. */
.event__thumb {
	grid-column: 2;
	align-self: start; /* As tall as the image, not the whole row. */
	justify-self: start;
	width: 5.5rem;
	margin-top: 0.75rem;
	cursor: zoom-in;
}

.event__image {
	display: block;
	width: 100%;
	height: auto;
	border: 1px solid var(--pink);
	transition: opacity 0.2s;
}

/* Drawn inside: the panel's scroll area would clip a ring outside the right edge. */
.event__thumb:focus-visible {
	outline-offset: -2px;
}

.event__thumb:hover .event__image {
	opacity: 0.85;
}

@container (min-width: 26rem) {
	.content .event--has-image {
		grid-template-columns: 3.25rem minmax(0, 1fr) 5.5rem;
	}

	.event__thumb {
		grid-column: 3;
		grid-row: 1;
		margin-top: 0.2rem;
	}
}

/* Poster lightbox (a native <dialog>, see diana_the_lightbox()). */
.lightbox {
	padding: 0;
	border: 0;
	background: transparent;
	overflow: visible;
}

.lightbox::backdrop {
	background: rgb(46 32 31 / 0.85); /* --text, darkened. */
}

.lightbox__img {
	display: block;
	width: auto;
	max-width: 92vw;
	height: auto;
	max-height: 88vh;
}

.lightbox__close {
	position: absolute;
	top: 0.5rem;
	right: 0.5rem;
	display: grid;
	place-items: center;
	width: 2.5rem;
	height: 2.5rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--cream);
	color: var(--text);
	cursor: pointer;
}

.lightbox__close:hover {
	color: var(--accent);
}

.content .events__empty {
	font-style: italic;
}

/* Contact form (Contact Form 7). The plugin's own stylesheet loads after this one,
   so rules start with .content .wpcf7 to outrank it. Focus rings are drawn inside the
   fields and the button: the panel's scroll area would clip a ring drawn outside.
   Floating labels: inc/contact.php wraps each label's text in .float-field__label (still
   inside the <label>, so it stays associated with its field) and gives the field
   placeholder=" ", so :placeholder-shown tells an empty field from a filled one. */

/* Rows with room between them. Name and email share a row on wide screens (below). */
.content .wpcf7-form p {
	margin: 0 0 1.25rem;
}

/* The honeypot's paragraph holds only the hidden trap field: no space for it. */
.content .wpcf7-form p:has(> .cf7apps-honeypot-wrap) {
	margin: 0;
}

@media (min-width: 700px) {
	.content .wpcf7-form {
		display: grid;
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		column-gap: 1.25rem;
		align-items: start;
	}

	.content .wpcf7-form > * {
		grid-column: 1 / -1;
	}

	.content .wpcf7-form > p:has([data-name="your-name"]),
	.content .wpcf7-form > p:has([data-name="your-email"]) {
		grid-column: auto;
	}
}

.content .wpcf7-form .float-field {
	position: relative;
	display: block;
}

.content .wpcf7-form-control-wrap {
	display: block;
}

.content .wpcf7 input[type="text"],
.content .wpcf7 input[type="email"],
.content .wpcf7 input[type="tel"],
.content .wpcf7 input[type="url"],
.content .wpcf7 textarea {
	display: block;
	box-sizing: border-box;
	width: 100%;
	min-height: 3.5rem; /* 56px: room for the floated label above the typed text. */
	margin: 0;
	padding: 1.45rem 0.85rem 0.4rem; /* Room at the top for the floated label. */
	border: 1px solid var(--pink);
	border-radius: 0;
	background: var(--cream);
	color: var(--text);
	font-family: var(--font-body);
	font-size: 1rem; /* 16px: iOS zooms into smaller fields. */
	line-height: 1.4;
	letter-spacing: normal;
	text-transform: none;
	appearance: none;
	transition: border-color 0.2s, box-shadow 0.2s;
}

.content .wpcf7 textarea {
	height: 10rem; /* The visitor can drag it taller. */
	min-height: 10rem;
	padding-bottom: 0.6rem;
	resize: vertical;
}

/* The placeholder is one invisible space, only a hook for :placeholder-shown. */
.content .wpcf7 input::placeholder,
.content .wpcf7 textarea::placeholder {
	color: transparent;
}

/* The label in the theme's small spaced uppercase (like the language
   switch). Resting: inside the field where the text will go. --text, not --text-muted:
   muted is 4.2:1 on cream, below the 4.5:1 that small text needs. */
.content .float-field__label {
	position: absolute;
	z-index: 1; /* CF7 makes the field wrapper position: relative, which would paint over it. */
	top: 1.2rem;
	left: calc(0.85rem + 1px);
	right: calc(0.85rem + 1px);
	overflow: hidden;
	color: var(--text);
	font-family: var(--font-body);
	font-size: 0.75rem;
	letter-spacing: 0.18em;
	line-height: 1.4;
	text-transform: uppercase;
	white-space: nowrap;
	text-overflow: ellipsis;
	pointer-events: none; /* Clicks go to the field (the label would focus it anyway). */
	transition: top 0.15s ease, font-size 0.15s ease, color 0.15s;
}

/* Floated: focused or filled, the label moves up and shrinks a little. */
.content .float-field:has(input:focus, textarea:focus) .float-field__label,
.content .float-field:has(input:not(:placeholder-shown), textarea:not(:placeholder-shown)) .float-field__label {
	top: 0.45rem;
	font-size: 0.68rem;
	line-height: 1.2;
}

.content .float-field:has(input:focus, textarea:focus) .float-field__label {
	color: var(--accent);
}

/* Browsers without :has() can't float the label: show it above the field instead. */
@supports not selector(:has(*)) {
	.content .float-field__label {
		position: static;
		display: block;
		margin-bottom: 0.4rem;
	}

	.content .wpcf7 input[type="text"],
	.content .wpcf7 input[type="email"],
	.content .wpcf7 textarea {
		padding-top: 0.75rem;
	}
}

@media (prefers-reduced-motion: reduce) {
	.content .float-field__label {
		transition: none;
	}
}

/* Focus: accent border plus an inset accent line, so the ring is 2px and never clipped.
   :focus, not only :focus-visible: text fields always show where typing goes. */
.content .wpcf7 input:focus,
.content .wpcf7 textarea:focus {
	border-color: var(--accent);
	outline: none;
	box-shadow: inset 0 0 0 1px var(--accent);
}

/* Submit: a quiet outlined button in the menu's spaced uppercase, accent on hover. */
.content .wpcf7 .wpcf7-submit {
	min-height: 3rem;
	padding: 0.75rem 1.75rem;
	border: 1px solid var(--text);
	border-radius: 0;
	background: transparent;
	color: var(--text);
	font-family: var(--font-body);
	font-size: 0.85rem;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	cursor: pointer;
	appearance: none;
	transition: color 0.2s, border-color 0.2s;
}

.content .wpcf7 .wpcf7-submit:hover {
	border-color: var(--accent);
	color: var(--accent);
}

.content .wpcf7 .wpcf7-submit:focus-visible {
	border-color: var(--accent);
	color: var(--accent);
	outline: 2px solid var(--accent);
	outline-offset: -5px;
}

/* Sending: the button dims and CF7's spinner turns into a small muted dot circling. */
.content .wpcf7-form.submitting .wpcf7-submit {
	opacity: 0.6;
	cursor: progress;
}

.content .wpcf7 .wpcf7-spinner {
	width: 1.25rem;
	height: 1.25rem;
	margin: 0 0 0 1rem;
	vertical-align: middle;
	background-color: var(--pink);
	opacity: 1;
}

.content .wpcf7 .wpcf7-spinner::before {
	background-color: var(--accent);
}

/* Inline field errors: the field gets an accent border, the message sits below it.
   Two classes on the control, to outrank the input[type] rules above. */
.content .wpcf7 .wpcf7-form-control.wpcf7-not-valid {
	border-color: var(--accent);
}

.content .wpcf7 .wpcf7-not-valid-tip {
	margin-top: 0.4rem;
	color: var(--accent);
	font-size: 0.85rem;
	letter-spacing: normal;
	text-transform: none;
}

/* The message under the form after sending. CF7 marks the form with the state:
   sent (success), invalid / unaccepted (fix a field), failed / aborted / spam (error). */
.content .wpcf7 form .wpcf7-response-output {
	margin: 0 0 1.5rem;
	padding: 0.85rem 1rem;
	border: 1px solid var(--pink);
	border-left-width: 3px;
	background: var(--pink-pale);
	color: var(--text);
	font-size: 0.95rem;
	line-height: 1.5;
}

.content .wpcf7 form.sent .wpcf7-response-output {
	border-color: var(--pink);
	border-left-color: var(--text-muted);
}

.content .wpcf7 form.invalid .wpcf7-response-output,
.content .wpcf7 form.unaccepted .wpcf7-response-output,
.content .wpcf7 form.payment-required .wpcf7-response-output,
.content .wpcf7 form.failed .wpcf7-response-output,
.content .wpcf7 form.aborted .wpcf7-response-output,
.content .wpcf7 form.spam .wpcf7-response-output {
	border-color: var(--pink);
	border-left-color: var(--accent);
	background: var(--cream);
}

/* Page dots (front-page.php, assets/js/slider.js): a vertical position indicator on the
   right edge of the right half, in the panel's side padding. One dot per page in menu
   order; the current one filled in --accent. Wide screens with JS only, and only while a
   page panel is shown (.is-visible). Each dot is a link to #page-slug with the page title
   as its (visually hidden) text; the title appears beside the dot on hover and focus. */

.panel-dots {
	display: none;
}

.panel-dots ol {
	display: flex;
	flex-direction: column;
	margin: 0;
	padding: 0;
	list-style: none;
}

.panel-dots a {
	position: relative;
	display: grid;
	place-items: center;
	width: 1.5rem; /* 24px click target around a small dot. */
	height: 1.5rem;
	border-radius: 50%;
	text-decoration: none;
}

.panel-dots a::before {
	content: "";
	width: 7px;
	height: 7px;
	border: 1px solid var(--text-muted);
	border-radius: 50%;
	transition: background-color 0.2s, border-color 0.2s;
}

.panel-dots a:hover::before {
	border-color: var(--accent);
}

.panel-dots a[aria-current]::before {
	border-color: var(--accent);
	background: var(--accent);
}

/* Inside the target: the panel's edge would clip a ring drawn outside. */
.panel-dots a:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: -2px;
}

/* The page title: read by screen readers always, shown beside the dot on hover and focus. */
.panel-dots__label {
	position: absolute;
	top: 50%;
	right: calc(100% + 0.25rem);
	padding: 0.25rem 0.5rem;
	background: var(--cream);
	color: var(--text);
	font-size: 0.7rem;
	letter-spacing: 0.12em;
	line-height: 1.2;
	text-transform: uppercase;
	white-space: nowrap;
	opacity: 0;
	pointer-events: none;
	transform: translateY(-50%);
	transition: opacity 0.2s;
}

.panel-dots a:hover .panel-dots__label,
.panel-dots a:focus-visible .panel-dots__label {
	opacity: 1;
}

@media (min-width: 900px) {
	.js .panel-dots {
		position: absolute;
		top: 50%;
		right: 1rem; /* Dot centres 1.75rem from the edge, in line with the back button. */
		z-index: 5;
		display: block;
		opacity: 0;
		visibility: hidden; /* Hidden dots are out of the Tab order too. */
		transform: translateY(-50%);
		transition: opacity 0.3s, visibility 0s linear 0.3s;
	}

	.js .panel-dots.is-visible {
		opacity: 1;
		visibility: visible;
		transition: opacity 0.3s;
	}
}

@media (prefers-reduced-motion: reduce) {
	.js .panel-dots,
	.js .panel-dots.is-visible,
	.panel-dots a::before,
	.panel-dots__label {
		transition: none;
	}
}

/* Front page panels: the menu panel, then one panel per page. */

.panels {
	--slide-duration: 900ms;
	--slide-ease: cubic-bezier(0.65, 0, 0.35, 1);
	position: relative;
	margin-top: 0; /* No header above it: the menu panel is the header. */
}

/* "Back to menu" (front-page.php, assets/js/slider.js): a small round button in the
   bottom-right corner of the right half, below the dots, a little further in.
   It sits in the panel's side padding (at least 54px at 900px: 6vw), so it never covers
   the content, and its bottom lines up with the bottom of the content area, above the
   footer line. Wide screens with JS only, and only while a page panel is shown
   (.is-visible); on phones the hamburger does this job. Its text is the label shown
   beside it on hover and focus, like the dots' titles. */

.panel-back {
	display: none;
}

@media (min-width: 900px) {
	.js .panel-back {
		position: absolute;
		/* 1.375rem from the edge. On narrower screens (up to about 1030px) the side padding
		   (6vw) is too small for that, so the button moves back out and always keeps 0.25rem
		   between itself and the content (6vw - 2.25rem button - 0.25rem). */
		right: min(1.375rem, calc(6vw - 2.5rem));
		bottom: calc(var(--panel-pad-bottom) + var(--footer-line) + 1.25rem);
		z-index: 5;
		display: grid;
		place-items: center;
		width: 2.25rem;
		height: 2.25rem;
		border: 1px solid var(--text-muted);
		border-radius: 50%;
		background: var(--cream);
		color: var(--text-muted);
		text-decoration: none;
		opacity: 0;
		visibility: hidden; /* Out of the Tab order while hidden. */
		transition: opacity 0.3s, visibility 0s linear 0.3s, color 0.2s, border-color 0.2s;
	}

	.js .panel-back.is-visible {
		opacity: 1;
		visibility: visible;
		transition: opacity 0.3s, color 0.2s, border-color 0.2s;
	}
}

.panel-back:hover,
.panel-back:focus-visible {
	border-color: var(--accent);
	color: var(--accent);
}

.panel-back:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

/* Read by screen readers always, shown beside the button on hover and focus. */
.panel-back__label {
	position: absolute;
	top: 50%;
	right: calc(100% + 0.5rem);
	padding: 0.25rem 0.5rem;
	background: var(--cream);
	color: var(--text);
	font-size: 0.7rem;
	letter-spacing: 0.12em;
	line-height: 1.2;
	text-transform: uppercase;
	white-space: nowrap;
	opacity: 0;
	pointer-events: none;
	transform: translateY(-50%);
	transition: opacity 0.2s;
}

.panel-back:hover .panel-back__label,
.panel-back:focus-visible .panel-back__label {
	opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
	.js .panel-back,
	.js .panel-back.is-visible,
	.panel-back__label {
		transition: none;
	}
}

/* Wide screens: the document never scrolls, only a panel's content area does.
   Not on full pages (page-templates/full-page.php): they scroll normally. */
@media (min-width: 900px) {
	html.js:not(.full-page),
	html.js:not(.full-page) body {
		height: 100%;
		overflow: hidden;
	}

	/* The admin bar's margin already pushes <html> down; body must end at the screen's bottom. */
	html.js:not(.full-page) body {
		height: calc(100% - var(--admin-bar));
	}

	/* Menu panel: title, tagline, menu and channel icons centred in the right half.
	   Auto margins centre it but, unlike justify-content, keep the top reachable:
	   on a short screen the panel scrolls instead of squeezing the menu. */
	.panel--menu .panel__content {
		display: flex;
		flex-direction: column;
	}

	/* The menu and the channel icons stay centred. */
	.menu-panel__inner {
		flex: none;
		width: 100%;
		max-width: 56rem;
		margin: auto;
		text-align: center;
	}

	.panel--menu .site-nav .menu {
		align-items: center;
	}

	/* Centred under the menu, also when they wrap onto two lines. */
	.channels {
		justify-content: center;
	}
}

/* [recordings] shortcode: the videos from Recordings in the admin.
   auto-fit adapts to how many there are: one fills the width, two sit side by side,
   more wrap into rows. Each video is at least 15rem wide, so on a narrow panel they
   stack. min(100%, …) keeps a single video from overflowing a very narrow column.
   No media query needed: it follows the panel's width. */
.recordings {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
	gap: 1rem;
	margin: 1.5rem 0;
}

.video {
	position: relative;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	background: var(--pink);
}

.video__play {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}

/* Drawn inside the frame, which clips anything outside it. */
.video__play:focus-visible {
	outline-offset: -3px;
}

.video__thumb {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover; /* Crops the black bars of YouTube's 4:3 thumbnail. */
	filter: saturate(0.85);
}

.video__icon {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	width: 3rem;
	height: 3rem;
	margin: auto;
	border-radius: 50%;
	background: rgb(252 243 236 / 0.88);
	color: var(--accent);
	transition: transform 0.2s;
}

.video__play:hover .video__icon {
	transform: scale(1.08);
}

.video iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
}

/* YouTube channel links below the menu: icon plus name, side by side in one row.
   flex-wrap stacks them only when both do not fit on one line.
   A small gap above, so they read as part of the menu block. */
.channels {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem 2rem; /* Rows, then between the two links. */
	margin: 1rem 0 0;
	padding: 0;
	list-style: none;
}

/* The icon is currentColor, so the hover colour reaches icon and name together. */
.channels a {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	padding: 0.25rem;
	color: var(--text-muted);
	text-decoration: none;
}

.channels__label {
	font-family: var(--font-body);
	font-size: 0.85rem; /* Same as the menu items. */
}

.channels a:hover {
	color: var(--accent);
}

/* Panel switcher (wide screens, switched on by assets/js/slider.js)
   Panels sit on top of each other. JS sets --offset on each one:
   -1 = parked above, 0 = on screen, 1 = parked below. Opening a page moves
   the menu up and out while the page comes in from below; Back reverses it. */

.panels.is-slider {
	overflow: hidden;
}

/* Only the current panel is visible, so Tab and screen readers stay in it. */
.is-slider .panel {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	transform: translateY(calc(var(--offset, 0) * 100%));
	visibility: hidden;
}

.is-slider .panel.is-current {
	visibility: visible;
}

/* The content scrolls when it is long. */
.is-slider .panel__content {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
}

/* The outgoing panel stays visible until its slide has finished. */
.is-slider.is-animated .panel {
	transition:
		transform var(--slide-duration) var(--slide-ease),
		visibility 0s linear var(--slide-duration);
}

.is-slider.is-animated .panel.is-current {
	transition:
		transform var(--slide-duration) var(--slide-ease),
		visibility 0s;
}

/* Panels are focused by script after a click; no ring around the whole area. */
.is-slider .panel:focus {
	outline: none;
}

/* Phones: no split. Photo on top, sections stacked, normal scrolling,
   menu behind a hamburger button as a full-screen overlay. */
@media (max-width: 899.98px) {
	.site {
		display: block;
		height: auto;
	}

	.site-photo {
		height: 45vh;
		height: 45svh;
	}

	.site-panel {
		overflow: visible;
		padding: 2.5rem 1.5rem 2rem;
	}

	.site-main {
		overflow: visible;
		margin-top: 2.5rem;
	}

	/* Title and tagline centred, as on the desktop menu panel; page content stays left. */
	.site-title,
	.site-tagline {
		text-align: center;
	}

	/* The menu panel's wrappers step aside (display: contents), so the site header and the
	   channel icons become direct items of the panel stack, above the page sections. */
	.panels {
		display: flex;
		flex-direction: column;
		margin-top: 0;
	}

	.panel--menu,
	.panel--menu .panel__content,
	.menu-panel__inner {
		display: contents;
	}

	/* Directly below the title and tagline (the menu is in the overlay), centred like them. */
	.channels {
		justify-content: center;
		margin-top: 1.5rem;
	}

	.panel--page {
		margin-top: 4rem;
		scroll-margin-top: 1.5rem;
	}

	.js .menu-toggle {
		position: fixed;
		top: calc(1rem + var(--admin-bar));
		right: 1rem;
		z-index: 20;
		display: flex;
		align-items: center;
		justify-content: center;
		width: 3rem;
		height: 3rem;
		padding: 0;
		border: 0;
		border-radius: 50%;
		background: var(--cream);
		color: var(--text);
		box-shadow: 0 2px 12px rgb(46 32 31 / 0.12);
		cursor: pointer;
	}

	/* Beside the hamburger: same height, same cream and shadow, as one small top bar. */
	.js .lang-switch {
		position: fixed;
		top: calc(1rem + var(--admin-bar));
		right: 4.5rem; /* 1rem + the 3rem button + 0.5rem gap. */
		z-index: 20;
		display: flex;
		align-items: center;
		height: 3rem;
		margin: 0;
		padding: 0 0.6rem;
		border-radius: 1.5rem;
		background: var(--cream);
		box-shadow: 0 2px 12px rgb(46 32 31 / 0.12);
	}

	/* Three lines; they turn into an X when the menu is open.
	   The middle line is the element itself, centred in the button by its flex layout;
	   the other two sit exactly --burger-gap above and below it, so they are evenly spaced.
	   8px keeps all three lines on the same sub-pixel offset at 1x, 1.25x, 1.5x and 2x
	   display scaling, so they render identically (at 6px, 1.25x scaling drew the middle
	   line thicker than the others). Widths are identical px, not rem. */
	.menu-toggle {
		--burger-gap: 8px;
	}

	.menu-toggle__icon,
	.menu-toggle__icon::before,
	.menu-toggle__icon::after {
		display: block;
		width: 22px;
		height: 1.5px;
		background: currentColor;
		transition: transform 0.3s, background-color 0.3s;
	}

	.menu-toggle__icon {
		position: relative;
	}

	.menu-toggle__icon::before,
	.menu-toggle__icon::after {
		content: "";
		position: absolute;
		left: 0;
	}

	.menu-toggle__icon::before {
		top: calc(-1 * var(--burger-gap));
	}

	.menu-toggle__icon::after {
		top: var(--burger-gap);
	}

	.menu-toggle[aria-expanded="true"] .menu-toggle__icon {
		background-color: transparent;
	}

	.menu-toggle[aria-expanded="true"] .menu-toggle__icon::before {
		transform: translateY(var(--burger-gap)) rotate(45deg);
	}

	.menu-toggle[aria-expanded="true"] .menu-toggle__icon::after {
		transform: translateY(calc(-1 * var(--burger-gap))) rotate(-45deg);
	}

	/* Without JS (no .js class) the menu simply stays in the page. */
	.js .site-nav {
		position: fixed;
		inset: var(--admin-bar) 0 0; /* Below the admin bar, if shown. */
		z-index: 15;
		display: flex;
		align-items: center;
		justify-content: center;
		margin: 0;
		background: var(--cream);
		opacity: 0;
		visibility: hidden;
		transition: opacity 0.3s, visibility 0s linear 0.3s;
	}

	.js .site-nav.is-open {
		opacity: 1;
		visibility: visible;
		transition: opacity 0.3s;
	}

	.js .site-nav .menu {
		align-items: center;
		gap: 1.25rem;
	}

	.js .site-nav a {
		font-size: 1rem;
	}

	html.menu-open {
		overflow: hidden;
	}
}

@media (prefers-reduced-motion: reduce) {
	.panels {
		--slide-duration: 0ms;
	}

	.js .site-nav,
	.js .site-nav.is-open,
	.menu-toggle__icon,
	.menu-toggle__icon::before,
	.menu-toggle__icon::after,
	.video__icon {
		transition: none;
	}
}


/* Full page (page-templates/full-page.php, the privacy pages): one centred column on the
   cream background, no photo, no panels; the document scrolls normally. */

.full-page__wrap {
	display: flex;
	flex-direction: column;
	width: min(100%, calc(70ch + 2 * var(--full-page-pad)));
	min-height: calc(100vh - var(--admin-bar));
	min-height: calc(100dvh - var(--admin-bar));
	margin: 0 auto;
	padding: 0 var(--full-page-pad) 1.25rem;
	--full-page-pad: clamp(1rem, 5vw, 3rem);
}

.full-page__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem 1.5rem;
	padding: clamp(1rem, 4vh, 2.5rem) 0 clamp(1.5rem, 5vh, 3.5rem);
}

.full-page__back {
	display: inline-block;
	padding: 0.35rem 0; /* Comfortable click target. */
	color: var(--text);
	font-size: 0.85rem;
	letter-spacing: 0.08em;
	text-decoration: none;
}

.full-page__back:hover {
	color: var(--accent);
	text-decoration: underline;
}

/* The switcher sits in the bar here, not in the panel (desktop) or beside the hamburger
   (phones): undo the phone pill (.js .lang-switch, "Phones"). */
html.full-page .lang-switch {
	position: static;
	height: auto;
	margin: 0;
	padding: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
}

.full-page__main {
	flex: 1 0 auto;
}

.full-page .site-footer {
	margin-top: 3rem;
}

/* Contact form: success message in soft green */
.wpcf7 form.sent .wpcf7-response-output {
	background: #eef3ea;
	border-color: #6f8f6a;
	color: #2e201f;
}

@media (max-width: 900px) {
  .site-photo {
    height: auto;
    aspect-ratio: 4 / 5;
  }
  .site-photo__img {
    object-position: center;
  }
}