/*
Theme Name: Nie | Romantyczni
Theme URI: https://nieromantyczni.pl
Author: Federico Bresciani
Description: Custom black-and-white theme for Nie | Romantyczni, a period-instrument orchestra. Stripped down from Underscores (_s).
Version: 1.0.0
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: LICENSE
Text Domain: nie-romantyczni

This theme, like WordPress, is licensed under the GPL.
Based on Underscores https://underscores.me/, (C) 2012-2020 Automattic, Inc.
*/

/* ==========================================================================
   1. Design tokens
   ========================================================================== */

:root {
	--color-bg: #ffffff;
	--color-fg: #000000;
	--color-bg-invert: #000000;
	--color-fg-invert: #ffffff;
	--color-border: #000000;
	--color-muted: #595959; /* only used for secondary meta text, e.g. concert dates in a list */

	--font-display: 'Anton', 'Arial Narrow', sans-serif;
	--font-body: 'Work Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

	--content-max: 1200px;
	--space-unit: 8px;
}

/* ==========================================================================
   2. Reset
   ========================================================================== */

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

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

body {
	margin: 0;
	background: var( --color-bg );
	color: var( --color-fg );
	font-family: var( --font-body );
	font-size: 18px;
	line-height: 1.6;
	-webkit-font-smoothing: antialiased;
}

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

a {
	color: currentColor;
}

ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

button {
	font-family: inherit;
	cursor: pointer;
}

/* Belt-and-braces alongside &nbsp; for "Nie | Romantyczni" — in at least
   one spot (Orchestra team-card bio) Chrome still broke the line right
   after the pipe despite genuine U+00A0 characters on both sides
   (verified via Range.getClientRects()), so this forces the whole
   phrase to stay on one line regardless. */
.nowrap {
	white-space: nowrap;
}

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect( 1px, 1px, 1px, 1px );
	white-space: nowrap;
}

.skip-link {
	position: absolute;
	top: -100px;
	left: 0;
	background: var( --color-bg-invert );
	color: var( --color-fg-invert );
	padding: 12px 20px;
	z-index: 1000;
}

.skip-link:focus {
	top: 0;
}

/* ==========================================================================
   3. Typography
   ========================================================================== */

/* .text-display-1/2 get the same display-face treatment as real headings —
   they're used on non-heading elements (e.g. .page-lede is a <p>) that
   still need to look like a headline, so this can't be scoped to the h1-h4
   tag selectors alone. Caught via computed-style inspection: a .page-lede
   was silently rendering in the body font at regular weight, no uppercase,
   because it only ever matched the font-size rule below, not this one. */
h1,
h2,
h3,
h4,
.text-display-1,
.text-display-2 {
	font-family: var( --font-display );
	font-weight: 400; /* Anton only ships one weight; heaviness comes from the typeface itself */
	text-transform: uppercase;
	line-height: 0.95;
	letter-spacing: 0.01em;
	margin: 0 0 0.4em;
}

/* Display sizes scale with viewport but stay controlled at both ends. */
h1,
.text-display-1 {
	font-size: clamp( 2.75rem, 8vw, 7rem );
}

h2,
.text-display-2 {
	font-size: clamp( 2rem, 5vw, 4rem );
}

h3 {
	font-size: clamp( 1.5rem, 3vw, 2.25rem );
}

p {
	margin: 0 0 1.2em;
	max-width: 65ch;
}

/* Opts a paragraph out of the 65ch readability cap above and centers it —
   for a short opening statement that should use the full content-column
   width (same edge distance as everything else in .entry-content, just
   not narrowed to a reading measure) rather than read as a normal
   left-aligned paragraph. */
.content-wide-centered {
	max-width: none;
	text-align: center;
}

.entry-content,
.page-content {
	font-size: 1.05rem;
}

blockquote {
	margin: 0;
	font-family: var( --font-body );
	font-style: italic;
	font-size: clamp( 1.75rem, 4.5vw, 3rem );
	line-height: 1.3;
	max-width: 22ch;
}

/* The quote text is a <p>, which otherwise inherits the global
   `p { margin: 0 0 1.2em; }` — at this font-size (up to 3rem) that alone
   put 20-36px of empty space between the quote and its <cite>, on top of
   the cite's own margin-top, reading as too far apart from the quote it's
   attributing. */
blockquote p {
	margin-bottom: 0;
}

/* ==========================================================================
   4. Layout
   ========================================================================== */

.site {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
}

.site-content {
	flex: 1;
}

main.site-main {
	max-width: var( --content-max );
	margin: 0 auto;
	padding: 0 24px;
}

/* Breaks an element out of main.site-main's centered, padded max-width box
   to span the true viewport width. Written against 50vw rather than the
   parent's own (padded) 50% so it holds regardless of the parent's padding
   — a translateX(-50%) version was tried first and came up short exactly
   because it resolved against the padded parent box, not the viewport. */
.full-bleed {
	width: 100vw;
	margin-left: calc( 50% - 50vw );
	margin-right: calc( 50% - 50vw );
}

/* ==========================================================================
   5. Header / nav
   ========================================================================== */

.site-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 20px 24px;
	border-bottom: 1px solid var( --color-border );
	position: fixed; /* also the positioning context for the mobile nav dropdown below */
	top: 0;
	left: 0;
	right: 0;
	z-index: 200;
	background: var( --color-bg );
	transition: background-color 0.3s ease, backdrop-filter 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

/* Toggled by header-scroll.js once the page has scrolled past a small
   threshold. Not fully transparent — a see-through white tint (rather than
   opacity: 0) so the wordmark/nav stay legible over whatever has scrolled
   underneath, including a dark full-bleed photo like the Home hero. */
.site-header.is-scrolled {
	background: rgba( 255, 255, 255, 0.82 );
	backdrop-filter: blur( 10px );
	-webkit-backdrop-filter: blur( 10px );
	border-bottom-color: rgba( 0, 0, 0, 0.08 );
}

/* Front page only (see header.php) — the header starts fully transparent,
   floating directly over the hero photo (which is pulled up underneath it,
   see .home-hero-photo's negative margin below) instead of pushing the
   photo down by its own height. Text flips to white via currentColor
   (wordmark and hamburger bars need their own explicit override, since
   they set color/background directly rather than inheriting). The
   :not(.is-scrolled) guard means this simply stops applying once
   header-scroll.js adds that class, falling back to the normal opaque
   black-on-white look with no extra reset rules needed. */
.site-header--transparent-hero:not( .is-scrolled ) {
	background: transparent;
	border-bottom-color: transparent;
	color: var( --color-fg-invert );
}

.site-header--transparent-hero:not( .is-scrolled ) .site-wordmark {
	color: var( --color-fg-invert );
}

.site-header--transparent-hero:not( .is-scrolled ) .menu-toggle__bar {
	background: var( --color-fg-invert );
}

/* Compensates for the header leaving normal document flow (position: fixed
   above) — --header-height is measured and kept in sync by
   header-scroll.js, not hardcoded, since the header's own height already
   changes between the desktop nav and the mobile hamburger layouts. */
.site-content {
	padding-top: var( --header-height, 76px );
}

.site-wordmark {
	font-family: var( --font-display );
	font-size: 2.5rem; /* fixed, not fluid — stays put as the window resizes instead of shrinking/shifting */
	text-decoration: none;
	color: var( --color-fg );
	letter-spacing: 0.02em;
	margin-left: 16px;
	flex-shrink: 0; /* never gets squeezed by the nav before the hamburger breakpoint kicks in */
}

.site-wordmark__pipe {
	display: inline-block;
	margin: 0 0.15em;
}

.main-navigation {
	display: flex;
	align-items: center;
	gap: 32px;
	flex-shrink: 0; /* never gets squeezed narrower than its content needs */
}

/* Desktop: lays its two children (menu, language switcher) out exactly like
   .main-navigation used to before the button was split out into a sibling —
   see header.php and the mobile media query below for why. */
.nav-dropdown {
	display: flex;
	align-items: center;
	gap: 32px;
	flex-shrink: 0;
}

.main-navigation ul {
	display: flex;
	gap: 28px;
}

.main-navigation a {
	text-decoration: none;
	font-weight: 600;
	text-transform: uppercase;
	font-size: 0.85rem;
	letter-spacing: 0.05em;
	white-space: nowrap; /* without this, a flex item can shrink by wrapping its text
		mid-label instead of holding its natural width — "O nas" splitting into "O" /
		"NAS" partway through a resize was exactly that */
}

.main-navigation a:hover,
.main-navigation a:focus {
	text-decoration: underline;
}

/* wp_nav_menu adds these classes itself by comparing each item's URL
   against the current request — no PHP needed on our end, just styling
   the state it already flags. */
.main-navigation .current-menu-item > a,
.main-navigation .current_page_item > a,
.main-navigation .current-menu-ancestor > a,
.main-navigation .current_page_ancestor > a {
	text-decoration: underline;
}

.language-switcher {
	display: flex;
	gap: 10px;
	font-size: 0.8rem;
	font-weight: 600;
}

.language-switcher .is-current {
	text-decoration: underline;
}

.menu-toggle {
	display: none;
	background: none;
	border: none;
	padding: 4px;
	flex-direction: column;
	gap: 5px;
}

.menu-toggle__bar {
	width: 24px;
	height: 2px;
	background: var( --color-fg );
}

/* Measured: the wordmark + full PL nav need ~1012px combined before they'd
   touch at all (243px wordmark + 721px nav + 48px header padding, both now
   flex-shrink: 0 so neither gives ground). 1060px lets the first link sit
   close to the wordmark — a real but modest ~48px gap — before the switch
   to the hamburger, rather than collapsing while there's still plenty of
   unused space. */
@media ( max-width: 1060px ) {
	.menu-toggle {
		display: flex;
	}

	/* .nav-dropdown is a wrapper around the links + language switcher,
	   separate from the toggle button itself (see header.php) — that way
	   the button stays fixed in the header and only this panel animates.
	   Always laid out (position: absolute, flex) so opacity/transform can
	   transition smoothly; display:none couldn't animate at all, and
	   toggling it on the button's own container used to drag the button
	   into the dropdown along with everything else. visibility keeps it
	   out of tab order and unclickable while closed, same as display:none
	   would, just with the timing pushed to the end of the transition. */
	.nav-dropdown {
		display: flex;
		flex-direction: column;
		align-items: flex-start;
		gap: 16px;
		position: absolute;
		top: 100%;
		right: 0;
		background: var( --color-bg );
		border: 1px solid var( --color-border );
		padding: 20px;
		z-index: 100;
		opacity: 0;
		visibility: hidden;
		transform: translateY( -8px );
		/* On the homepage before scrolling, .site-header--transparent-hero
		   flips the WHOLE header's text to white (for contrast over the hero
		   photo — see that rule above), which .main-navigation a inherits
		   since it sets no color of its own. This panel always has its own
		   solid white background once open, though, regardless of that hero
		   state — without resetting color back here, the links render white
		   text on a white box: technically present, invisible. */
		color: var( --color-fg );
	}

	.nav-dropdown ul,
	.nav-dropdown .language-switcher {
		display: flex;
		flex-direction: column;
		gap: 14px;
	}

	.main-navigation.is-open .nav-dropdown {
		opacity: 1;
		visibility: visible;
		transform: translateY( 0 );
	}

	/*
	 * .js-nav-animate is added by navigation.js only inside the click
	 * handler — never on page load, never on a plain resize. Without that
	 * gate, the opacity/transform above would still transition the FIRST
	 * time this media query itself starts matching (crossing the breakpoint
	 * while resizing flips the dropdown from its implicit desktop "visible,
	 * no transform" state to this closed state in one style recalc),
	 * producing a stray quick fade/slide flash at the exact moment the
	 * layout switches to the hamburger — even though nobody had clicked
	 * anything yet. Scoping the transition to a click-only class keeps that
	 * switch instant and reserves the animation for deliberate opens/closes.
	 */
	.main-navigation.js-nav-animate .nav-dropdown {
		transition: opacity 0.22s ease, transform 0.22s ease, visibility 0s linear 0.22s;
	}
}

/* ==========================================================================
   6. Footer
   ========================================================================== */

.site-footer {
	border-top: 1px solid var( --color-border );
	padding: 40px 24px;
	margin-top: 80px;
}

.footer-primary {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 20px;
	max-width: var( --content-max );
	margin: 0 auto 30px;
}

.footer-contact {
	display: flex;
	gap: 24px;
}

.footer-contact a {
	text-decoration: none;
}

.footer-social {
	display: flex;
	gap: 20px;
	/* .footer-primary's space-between otherwise pushes this flush to the
	   content box's own right edge — small icons read as cramped there
	   in a way the old text labels didn't. */
	margin-right: 12px;
}

.footer-social__link {
	display: inline-flex;
	text-decoration: none;
	opacity: 0.75;
	transition: opacity 0.15s ease;
}

.footer-social__link svg {
	width: 28px;
	height: 28px;
}

.footer-social__link:hover {
	opacity: 1;
}

.footer-partners {
	max-width: var( --content-max );
	margin: 0 auto 30px;
	border-top: 1px solid var( --color-border );
	padding-top: 24px;
}

.footer-partners__label {
	text-transform: uppercase;
	font-size: 0.75rem;
	letter-spacing: 0.08em;
	color: var( --color-muted );
	margin-bottom: 12px;
}

/* Logos and the funding notice are all direct items of ONE flex-wrap
   row (not a logos sub-block sitting beside the notice as two rigid
   units) — deliberately, after that two-unit version produced a bad
   case: at some widths the 6 logos alone wrapped to 2 lines (5 + 1),
   leaving a lone 6th logo with a huge stretch of empty space beside it
   on its own line, while the notice — unable to peek into that gap
   since it could only sit beside the logos block as a whole — dropped
   below everything onto a 3rd line instead. Flattening lets normal
   flex-wrap line-packing place the notice whichever line actually has
   room, including right after a trailing lone logo. */
.footer-partners__row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 20px 24px;
}

.footer-partners__logo {
	max-height: 72px;
	width: auto;
	flex-shrink: 0;
}

.footer-partners__notice {
	flex: 1 1 360px;
	min-width: 360px;
	max-width: 480px;
	padding: 0.85rem 1.1rem;
	border: 1px solid var( --color-border );
	font-size: 0.75rem;
	line-height: 1.5;
	color: var( --color-muted );
	/* An actual bordered box, not a text-align-last: justify effect —
	   forcing every line (including the last) flush turned out to be
	   fragile: whenever the last line only had a couple of words (as
	   happened with the English translation), the browser stretched
	   huge gaps between them to fill the width. A visible border gives
	   the "boxed" look reliably regardless of language or line count,
	   while the text inside justifies normally (ragged last line, as
	   usual — barely noticeable next to a border).
	   Sitting next to the logos is the actual requirement (see
	   .footer-partners__row below) — an earlier attempt pinned
	   min-width to max-width to force exactly two lines, but the six
	   logos leave only ~460px of leftover row space even at full
	   content width (1200px), and flex-wrap won't shrink an item below
	   its min-width — it pushes the whole item to its own row instead.
	   With min-width pinned to a fixed ~480px, that leftover was never
	   enough, so the box dropped below the logos on every realistic
	   screen width — the opposite of what was asked for. flex-basis is
	   set equal to min-width (rather than something larger) so the box
	   joins the row as soon as there's room for it at its smallest, and
	   then grows into whatever space is actually left, up to max-width.
	   360px floor is deliberate, not arbitrary: below it the text
	   degrades past 3 lines into a cramped 5-6 line column once space
	   gets tight, which reads as broken rather than boxed — better to
	   fall back to its own full-width row (still 2 lines there, just
	   not beside the logos) than let it get that narrow. The border
	   keeps it reading as "boxed" whether the shared-row result is two
	   lines or three. hyphens stays off so any wrapping happens at
	   whole word boundaries. */
	text-align: justify;
	text-justify: inter-word;
	hyphens: none;
}

/* Phones: the six logos sit in a fixed 3 x 2 grid (two tidy rows, one
   under the other) instead of free-wrapping into whatever 4+2 / 5+1
   split the width happens to allow, and the notice gets its own full-
   width row underneath. Logos scale down to their column rather than
   overflowing it. */
@media ( max-width: 640px ) {
	.footer-partners__row {
		display: grid;
		grid-template-columns: repeat( 3, minmax( 0, 1fr ) );
		gap: 20px 16px;
		align-items: center;
	}

	.footer-partners__logo {
		max-height: 56px;
		max-width: 100%;
		justify-self: center;
	}

	.footer-partners__notice {
		grid-column: 1 / -1;
		min-width: 0;
		max-width: 100%;
	}
}

.site-info {
	max-width: var( --content-max );
	margin: 0 auto;
	font-size: 0.8rem;
	color: var( --color-muted );
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 8px 24px;
}

.footer-legal {
	display: flex;
	gap: 16px;
}

.footer-legal a {
	color: var( --color-muted );
}

/* ==========================================================================
   7. Photography — original color, site-wide (reversed from the initial
      monochrome-everywhere brief; partner/funder logos in the footer keep
      their own separate desaturation below, which is a different design
      decision — brand-logo consistency, not photo treatment).
   ========================================================================== */

/* ==========================================================================
   8. Buttons / links
   ========================================================================== */

.button,
.contact-form-submit {
	display: inline-block;
	background: var( --color-bg-invert );
	color: var( --color-fg-invert );
	border: 1px solid var( --color-border );
	text-transform: uppercase;
	font-weight: 600;
	letter-spacing: 0.05em;
	font-size: 0.85rem;
	padding: 14px 28px;
	text-decoration: none;
	transition: background 0.15s ease, color 0.15s ease;
}

.button:hover,
.contact-form-submit:hover {
	background: var( --color-bg );
	color: var( --color-fg );
}

.button--outline {
	background: transparent;
	color: var( --color-fg );
}

.button--outline:hover {
	background: var( --color-bg-invert );
	color: var( --color-fg-invert );
}

/* ==========================================================================
   9. Contact page — a single two-column row: the display-type opener,
   lede, and email/phone stacked on the left; the form on the right,
   starting at the same top as "Let's talk." itself (align-items: start
   on one shared grid, rather than the intro sitting in its own
   full-width block above a second row). Inputs are underline-only
   rather than boxed, closer to the editorial feel of the rest of the
   site than a generic web form.
   ========================================================================== */

.contact-layout {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 64px;
	align-items: start;
	margin: 56px 0 80px;
}

.contact-intro__lede {
	max-width: 46ch;
	margin-top: 16px;
	font-size: 1.1rem;
	color: var( --color-muted );
}

.contact-layout__details {
	display: flex;
	flex-direction: column;
	gap: 20px;
	margin-top: 40px;
}

.contact-layout__detail {
	display: block;
	font-family: var( --font-display );
	text-transform: uppercase;
	font-size: clamp( 1.25rem, 2.5vw, 1.75rem );
	letter-spacing: 0.01em;
	text-decoration: none;
	color: var( --color-fg );
	border-bottom: 1px solid var( --color-border );
	padding-bottom: 16px;
	transition: opacity 0.15s ease;
}

.contact-layout__detail:hover {
	opacity: 0.6;
}

@media ( max-width: 780px ) {
	.contact-layout {
		grid-template-columns: 1fr;
		gap: 48px;
	}
}

.contact-form-honeypot {
	position: absolute;
	left: -9999px;
}

.contact-form-field {
	margin-bottom: 26px;
}

/* The message field's own underline lands on the same line as the one
   under the phone number on the left column — but the label above it
   keeps the normal 26px gap from the email field (same as every other
   field-to-field gap). The textarea itself grows taller (136px vs. the
   default 99px) to make up the 37px difference, instead of pushing the
   label down with it. */
.contact-form-field--message textarea {
	height: 136px;
}

.contact-form-field label {
	display: block;
	text-transform: uppercase;
	font-size: 0.8rem;
	letter-spacing: 0.05em;
	margin-bottom: 8px;
}

.contact-form-field input,
.contact-form-field textarea {
	width: 100%;
	border: none;
	border-bottom: 1px solid var( --color-border );
	background: transparent;
	color: var( --color-fg );
	font-family: var( --font-body );
	font-size: 1.05rem;
	padding: 10px 0;
	transition: border-color 0.2s ease;
}

.contact-form-field input:focus,
.contact-form-field textarea:focus {
	border-bottom-color: var( --color-fg );
	outline: none;
}

.contact-form-required {
	color: var( --color-muted );
	text-transform: none;
	font-size: 0.75rem;
}

.contact-form-status {
	padding: 14px;
	border: 1px solid var( --color-border );
	margin-bottom: 20px;
}

/* ==========================================================================
   10. Utility
   ========================================================================== */

.page-header {
	margin: 60px 0 40px;
}

/* letter-spacing is computed and applied by assets/text-stretch.js — nowrap
   keeps it a single line the calculation can measure/stretch correctly. */
.js-stretch-text {
	white-space: nowrap;
}

/* Musicians page: the title sits directly above the photo (normal
   flow, fully visible on its own — not layered over the image), with
   the gap between them tightened so it reads as sitting right at the
   photo's edge rather than floating with a lot of space beneath it.
   Top margin matches .page-header's convention so the title clears
   the header by the same breathing room as elsewhere on the site. */
.musicians-hero-title {
	margin: 60px 0 16px;
}

.musicians-hero-page .content-photo {
	margin-top: 0;
}

/* ==========================================================================
   11. Home
   ========================================================================== */

.home-hero {
	padding: 64px 0 32px;
}

.home-hero__lede {
	margin: 0;
	max-width: 16ch;
}

/* The full-page hero photo, with the Harnoncourt quote centered on top of
   it. The photo itself keeps the site's standard monochrome filter (see
   section 7); a dark scrim sits between photo and text purely for
   contrast, independent of any one photo's own tones.

   Negative top margin cancels out .site-content's padding-top (added to
   compensate for the header's own position: fixed) so the photo starts at
   the true top of the page, y=0, running underneath the header rather
   than being pushed down by it — the header goes transparent over it
   instead (see .site-header--transparent-hero above). Every other page
   still gets pushed down normally; only this section fights its way back
   up past that padding. */
.home-hero-photo {
	position: relative;
	width: 100%;
	height: 100vh;
	/* No bottom margin: the CTA button already lives inside the photo's
	   own overlay (see .home-hero-photo__cta) whenever there's a photo,
	   so .home-main renders completely empty right after this — the
	   48px this used to carry was just adding dead space on top of
	   .site-footer's own 80px margin-top, not separating this from any
	   actual content. */
	margin: calc( -1 * var( --header-height, 105px ) ) 0 0;
}

.home-hero-photo img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* Biases the crop down from dead-center so a lighter-toned top edge on
	   some photos (e.g. a venue's archway/ceiling) doesn't sit right under
	   the header reading as a seam — there's no actual layout gap between
	   header and photo (verified: 0px), this is purely about which part of
	   the image is visible at that edge. */
	object-position: center 30%;
}

.home-hero-photo__overlay {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: flex-start; /* quote sits near the top of the photo, not dead center vertically */
	justify-content: center; /* stays horizontally centered */
	text-align: center;
	/* The photo (and this overlay with it) now starts at the true top of
	   the page rather than below the header — see .home-hero-photo's
	   negative margin — so top padding has to clear the transparent
	   header's own height first, then a bit of breathing room below it
	   (nudged down from 6vh to 2vh), or the quote would start underneath
	   the header's text. */
	padding: calc( var( --header-height, 105px ) + 2vh ) 24px 24px;
	background: linear-gradient( rgba( 0, 0, 0, 0.35 ), rgba( 0, 0, 0, 0.45 ) );
}

.home-hero-photo__overlay blockquote {
	max-width: 26ch;
	color: var( --color-fg-invert );
}

/* Polish runs longer than English for the same quote — give it more
   horizontal measure instead of wrapping into extra narrow lines; it
   stays centered via the overlay's own justify-content: center. */
.home-hero-photo__overlay blockquote.quote--wide {
	max-width: 40ch;
}

.home-hero-photo__overlay cite {
	display: block;
	margin-top: 20px;
	font-style: normal;
	font-size: 0.85rem;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: rgba( 255, 255, 255, 0.75 );
}

/* CTA buttons sit near the photo's bottom edge — centered horizontally
   (inherited from .home-cta), pinned to the bottom rather than the
   vertical center. */
.home-hero-photo__cta {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 64px;
}

/* Two classes beats .home-cta's own `padding: 0 0 80px` regardless of
   source order — that padding was sized for trailing space before the
   footer in normal flow, meaningless once this sits absolutely positioned
   over the photo. */
.home-cta.home-hero-photo__cta {
	padding: 0 24px;
}

/* Overrides .button's own solid invert fill — a see-through white
   frosted-glass fill with a blur behind it instead, so it stays legible
   over any part of the photo without going fully opaque. Bigger and
   bumped up in opacity compared to the two-button version this replaced,
   since it's now the only, and therefore the more deliberate, CTA — needs
   to read clearly on its own rather than as half of a pair. Hover
   brightens the fill further and lifts the button slightly. */
.home-hero-photo__cta .button {
	background: rgba( 255, 255, 255, 0.88 );
	color: var( --color-fg );
	border-color: rgba( 255, 255, 255, 0.95 );
	backdrop-filter: blur( 8px );
	-webkit-backdrop-filter: blur( 8px );
	font-size: 1.05rem;
	padding: 18px 36px;
	transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}

.home-hero-photo__cta .button:hover {
	background: rgba( 255, 255, 255, 1 );
	transform: translateY( -3px );
	box-shadow: 0 10px 24px rgba( 0, 0, 0, 0.3 );
}

/* Fallback for before a photo is uploaded: quote sits in the normal flow
   instead of overlaid. */
.home-quote {
	max-width: var( --content-max );
	margin: 0 auto 48px;
	padding: 64px 24px 0;
	text-align: center;
}

.home-quote blockquote {
	margin: 0 auto;
}

.home-hero + .home-quote {
	padding-top: 0;
}

.home-quote cite {
	display: block;
	margin-top: 24px;
	font-style: normal;
	font-size: 0.85rem;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var( --color-muted );
}

.home-content {
	max-width: var( --content-max );
	margin: 0 auto 48px;
	padding: 0 24px;
}

.home-cta {
	display: flex;
	justify-content: center;
	gap: 20px;
	padding: 0 0 80px;
}

/* ==========================================================================
   12. Philosophy / long-form pages
   ========================================================================== */

.page-lede {
	max-width: 26ch;
	margin: 0 0 40px;
	/* Longer ledes wrap to several lines at this size — the base 0.95
	   line-height (tuned for a short 1-2 line headline) was tight enough to
	   make descenders/ogonki collide with the line below on a wrap this
	   deep. */
	line-height: 1.08;
}

/* ==========================================================================
   13. Content photos — reusable anywhere inside .entry-content/.page-content
   (long-form pages: Philosophy now, About/Gallery/etc. later). Two sizes
   (full column width, and a same-row pair) for pacing rather than a wall
   of text; deliberately block-level and never floated so images sit
   cleanly between paragraphs with generous margin instead of any risk of
   text wrapping around/overlapping them. Swap the placeholder box below
   for a real <img> (drop the .content-photo__placeholder div and its
   figcaption stays) once photos exist — .content-photo/-wide/-pair keep
   working the same way with a real image inside.
   ========================================================================== */

.content-photo {
	margin: 56px 0;
}

.content-photo__placeholder {
	aspect-ratio: 16 / 10;
	border: 1px dashed var( --color-border );
	display: flex;
	align-items: center;
	justify-content: center;
	color: var( --color-muted );
	text-transform: uppercase;
	font-size: 0.75rem;
	letter-spacing: 0.08em;
	text-align: center;
	padding: 24px;
}

/* A real photo dropped into a standalone .content-photo (not inside a
   .content-media-row) fills the same box the placeholder used, cropped
   via object-fit rather than distorted. */
.content-photo img {
	width: 100%;
	aspect-ratio: 16 / 10;
	object-fit: cover;
	display: block;
}

/* Matches this specific photo's own native ratio (2560×1139, a wide
   cinematic crop) instead of forcing it into the default 16:10 box,
   which would have cropped a meaningful amount off the sides. */
.content-photo--wide img {
	aspect-ratio: 2560 / 1139;
}

.content-photo-row {
	display: flex;
	gap: 24px;
	margin: 56px 0;
}

.content-photo-row .content-photo {
	flex: 1 1 0;
	margin: 0;
}

.content-photo-row .content-photo__placeholder {
	aspect-ratio: 4 / 5;
}

/* Portrait/vertical variant — e.g. alongside the Philosophy page's lede,
   where a tall image reads better next to a few short lines of huge type
   than the default landscape ratio would. */
.content-photo__placeholder--tall {
	aspect-ratio: 3 / 4;
}

@media ( max-width: 640px ) {
	.content-photo-row {
		flex-direction: column;
	}
}

/* Text-beside-image rows: uses the full content width as a two-column
   grid, one column of prose and one placeholder/image, side by side.
   Which side the image falls on is controlled purely by DOM order in the
   markup (media <figure> first = image-left, text first = image-right) —
   no left/right modifier classes needed. Collapses to a single stacked
   column on narrow viewports, in whatever order the markup already has. */
.content-media-row {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 40px;
	align-items: center;
	margin: 64px 0;
}

.content-media-row .content-photo {
	margin: 0;
}

/* A real photo dropped into .content-media-row__media (replacing the
   placeholder div) fills whatever height the row/placeholder ends up
   with, cropped via object-fit rather than distorted — same approach as
   .team-card__photo img. */
.content-media-row__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* .content-media-row defaults to align-items: center (items keep their
   own height, not stretched to the row) — so the generic height: 100%
   above would resolve against an auto-height ancestor and do nothing.
   This modifier fixes the image to the same 3:4 box the placeholder it
   replaced used, regardless of the row's own height. */
.content-photo--portrait img {
	aspect-ratio: 3 / 4;
	height: auto;
}

/* Same fix as .content-photo--portrait above, at a 5:7 ratio instead —
   used on the "Historical instruments" row. */
.content-photo--5x7 img {
	aspect-ratio: 5 / 7;
	height: auto;
}

/* Matches this specific photo's native ratio (1600×2560 = 5:8 exactly)
   — a taller portrait than -5x7, used on the Musicians/Orchestra page. */
.content-photo--5x8 img {
	aspect-ratio: 5 / 8;
	height: auto;
}

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

/* The name heading on a bio page (template-bio.php), and any "read more"
   CTA that follows the text column's paragraphs. */
.content-media-row__title {
	margin-bottom: 0.6em;
}

/* Forces a name heading's second word onto its own line with extra gap
   above it (e.g. "Fundacja" / "Żmigrodzkich") — a block-level span
   starts a new line on its own, and margin-top on it only pushes that
   second line down, leaving the first line's position untouched. */
.content-media-row__title-break {
	display: block;
	margin-top: 0.25em;
}

.content-media-row__text .button {
	margin-top: 32px;
}

/* Modifier for a row whose text column runs much longer than usual (e.g.
   a full biography) — the photo stays a normal portrait box, but tracks
   down the page with the reader while the (much taller) text column
   scrolls past, then scrolls away normally with the rest of the row once
   its bottom edge is reached. Pure CSS: a single-row grid gives both
   cells the SAME row-track height (the text column's, since it's
   tallest) regardless of align-items — align-items: start here just
   keeps the photo at its own natural height instead of stretching to
   fill that tall cell, and position: sticky lets it travel within that
   cell's bounds, releasing exactly at the text's end. No JS needed.
   Falls back to static positioning once the row stacks on mobile, where
   a stuck image next to full-width text below it would look broken. */
.content-media-row--sticky-portrait {
	align-items: start;
}

.content-media-row--sticky-portrait .content-media-row__media {
	position: sticky;
	top: var( --header-height, 76px );
}

.content-media-row--sticky-portrait .content-photo__placeholder,
.content-media-row--sticky-portrait .content-media-row__media img {
	aspect-ratio: 3 / 4;
	height: auto;
}

/* A photo with its own specific ratio class (e.g. --5x8) keeps that
   ratio instead of the sticky-portrait default above — three classes
   beats that rule's two regardless of source order. */
.content-media-row--sticky-portrait .content-photo--5x8 img {
	aspect-ratio: 5 / 8;
}

@media ( max-width: 780px ) {
	.content-media-row--sticky-portrait .content-media-row__media {
		position: static;
	}
}

@media ( max-width: 780px ) {
	.content-media-row {
		grid-template-columns: 1fr;
		gap: 24px;
	}
}

/* Same fix as .content-photo--portrait/-5x7 above, at a 1:1 ratio —
   used on the closing "We want to look beyond..." row. */
.content-photo--square img {
	aspect-ratio: 1 / 1;
	height: auto;
}

/* A section heading split one word per line in a narrow left column, next
   to its intro paragraphs in a wider right column — used for "Beyond the
   Canon" on the Philosophy page instead of the usual full-width centered
   h2. The title is a flex column with justify-content: space-between so
   its words spread out to fill the row's full height (grid's default
   align-items: stretch sizes both columns to the taller one, i.e. the
   text column), matching the text column's height exactly regardless of
   how long the paragraphs run. */
.split-heading-row {
	display: grid;
	grid-template-columns: 0.9fr 1.4fr;
	gap: 40px;
	margin: 64px 0;
}

.split-heading-row__title {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	align-items: center;
	text-align: center;
	font-size: clamp( 2.5rem, 6vw, 5rem );
	margin: 0;
}

.split-heading-row__text p:last-child {
	margin-bottom: 0;
}

@media ( max-width: 780px ) {
	.split-heading-row {
		grid-template-columns: 1fr;
		gap: 16px;
	}

	.split-heading-row__title {
		font-size: clamp( 2rem, 10vw, 3rem );
	}
}

/* ==========================================================================
   14. Team grid — reusable anywhere inside .entry-content/.page-content
   (About now: people, orchestra, foundation; could apply to a future
   Musicians page too). Each card is photo + name + optional role line +
   bio + a button, in normal document flow so nothing overlaps regardless
   of bio length.
   ========================================================================== */

.team-grid {
	display: grid;
	grid-template-columns: repeat( 2, 1fr );
	gap: 45px 32px;
	margin: 45px 0;
}

/* align-items: center keeps the photo+text block itself centered within
   the card (same width as the picture, per team-card__photo/name/role/bio
   below) — but the text WITHIN that block reads left-aligned, not
   centered. */
.team-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: left;
}

/* Everything below scaled to ~80% of its previous size (photo box, name,
   role, bio, button) — a deliberately smaller/lighter card than the
   generic .content-photo/heading/button defaults elsewhere on the site. */

/* Photo and text share the same center line, rather than a narrower
   image sitting flush left above full-width text — the photo's own
   width is scaled down further below, independently of the text. */
.team-card__name,
.team-card__role,
.team-card__bio {
	width: 80%;
}

/* Narrower than the text above (65% vs. 80%) — the photo took up too
   much space at the same width; only the picture shrinks, not the
   text/spacing/layout around it. */
.team-card__photo {
	width: 65%;
	margin: 0 0 16px;
}

/* A real photo dropped into .team-card__photo (replacing the placeholder
   div) fills the same 3:4 box the placeholder occupied, cropped via
   object-fit rather than distorted. */
.team-card__photo img {
	width: 100%;
	aspect-ratio: 3 / 4;
	object-fit: cover;
	display: block;
}

/* For a logo (square, needs to stay whole) rather than a portrait photo
   (fine to crop to fill the frame) — contain instead of cover, plus
   padding so it doesn't touch the box's edges, letterboxed within the
   same 3:4 frame every other card uses. */
/* Two classes + element beats .team-card__photo img's one class + element
   regardless of source order — without this, that rule's object-fit:
   cover silently won here instead, cropping into the logo itself rather
   than just the padding around it (only visible once the logo's own
   source image got cropped tight enough for the difference to matter). */
.team-card__photo img.team-card__photo-img--contain {
	object-fit: contain;
	padding: 2%;
}

/* Centered horizontally under the picture (which is narrower, 65% vs.
   this box's 80%) rather than left-aligned like the bio below it — both
   boxes share the same center via .team-card's align-items: center, so
   centering the text within its own wider box still lines it up with
   the narrower picture above. */
.team-card__name {
	font-size: clamp( 1.2rem, 2.4vw, 1.8rem );
	margin: 0 0 4px;
	text-align: center;
}

.team-card__role {
	text-transform: uppercase;
	font-size: 0.64rem;
	letter-spacing: 0.05em;
	color: var( --color-muted );
	margin: 0 0 13px;
	text-align: center;
}

.team-card__bio {
	max-width: none;
	font-size: 0.84rem;
	margin: 0 0 19px;
}

.team-card__button {
	/* Grid rows stretch every .team-card to the row's tallest card by
	   default, so margin-top: auto (absorbing ALL leftover space, pinning
	   the button flush to that shared bottom edge) is what actually keeps
	   every button in a row aligned regardless of how long each card's bio
	   runs. margin-bottom: auto was tried too, to avoid the button sitting
	   right at the bottom — but centering each button within its OWN
	   leftover space means a card with a shorter bio (more leftover space)
	   centers higher than a card with a longer bio (less leftover space),
	   breaking row-alignment. Exact alignment wins over that. */
	margin-top: auto;
	/* No align-self/margin override needed — the button's own natural
	   (narrow) width just centers via .team-card's align-items: center,
	   same as the picture and name above it. */
	font-size: 0.68rem;
	padding: 11px 22px;
}

@media ( max-width: 640px ) {
	.team-grid {
		grid-template-columns: 1fr;
	}
}

/* ==========================================================================
   16. Gallery grid — a disciplined uniform-crop grid (not masonry), matching
   the site's "one consistent photo treatment" rule rather than a looser
   Pinterest-style layout. Photo and video items share the same placeholder
   box; video items additionally show a play icon and the video's own title
   so the grid reads correctly even before real media is dropped in — swap
   .gallery-item__placeholder for a real <img>/<video> later and the grid
   keeps working the same way.
   ========================================================================== */

.gallery-grid {
	display: grid;
	grid-template-columns: repeat( 3, 1fr );
	gap: 32px;
	margin: 45px 0;
}

.gallery-item__placeholder {
	aspect-ratio: 4 / 3;
	border: 1px dashed var( --color-border );
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 14px;
	color: var( --color-muted );
	text-align: center;
	padding: 24px;
}

.gallery-item__label {
	text-transform: uppercase;
	font-size: 0.75rem;
	letter-spacing: 0.08em;
}

.gallery-item__play-icon svg {
	width: 30px;
	height: 30px;
	color: var( --color-fg );
	fill: currentColor;
}

.gallery-item__video-title {
	color: var( --color-fg );
	font-size: 0.85rem;
	max-width: 22ch;
}

@media ( max-width: 900px ) {
	.gallery-grid {
		grid-template-columns: repeat( 2, 1fr );
	}
}

@media ( max-width: 560px ) {
	.gallery-grid {
		grid-template-columns: 1fr;
	}
}

/* ==========================================================================
   17. Concerts — archive-concert.php and single-concert.php. Each concert
   is a date tile (big day number, short month/year underneath, the way a
   concert listing is conventionally scanned) beside the details. Past
   concerts get no special per-card treatment beyond the section heading
   itself ("Past Concerts") — that's already the unambiguous signal, a
   second one on every card would just be visual noise.
   ========================================================================== */

.concert-section {
	margin: 0 0 56px;
}

.concert-section__title {
	font-size: clamp( 1.5rem, 3vw, 2.25rem );
	border-bottom: 1px solid var( --color-border );
	padding-bottom: 16px;
	margin-bottom: 32px;
}

.concert-section__empty {
	color: var( --color-muted );
}

.concert-list {
	display: flex;
	flex-direction: column;
	gap: 40px;
}

.concert-card {
	display: flex;
	gap: 24px;
	padding-bottom: 40px;
	border-bottom: 1px solid var( --color-border );
}

.concert-list > .concert-card:last-child {
	border-bottom: none;
	padding-bottom: 0;
}

/* Fixed-width tile rather than shrinking/growing with the day number's
   own digit count (2 vs. 1 digit) — every date in the list lines up on
   the same left edge regardless. */
.concert-card__date {
	flex: 0 0 88px;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	text-align: center;
	padding: 12px 0;
	border: 1px solid var( --color-border );
	height: fit-content;
}

.concert-card__day {
	font-family: var( --font-display );
	font-size: 2.25rem;
	line-height: 1;
}

.concert-card__month-year {
	font-size: 0.7rem;
	letter-spacing: 0.05em;
	color: var( --color-muted );
	margin-top: 6px;
}

.concert-card__info {
	flex: 1;
	min-width: 0;
}

.concert-card__title {
	font-size: clamp( 1.25rem, 2.5vw, 1.75rem );
	margin: 0 0 8px;
}

.concert-card__title a {
	text-decoration: none;
}

.concert-card__title a:hover {
	text-decoration: underline;
}

.concert-card__venue {
	font-weight: 600;
	margin: 0 0 4px;
}

/* Deliberately no "Conductor:" label — his name just reads as a credit
   line under the venue, same way a printed program would show it. */
.concert-card__conductor,
.concert-card__soloists {
	color: var( --color-muted );
	margin: 0 0 4px;
}

.concert-card__program {
	margin-top: 16px;
	font-size: 0.9rem;
	color: var( --color-muted );
}

.concert-card__program p {
	margin: 0 0 6px;
}

.concert-card__tickets {
	margin-top: 20px;
	display: inline-block;
}

/* ---- Single concert ---- */

.concert-single__date {
	text-transform: uppercase;
	font-size: 0.85rem;
	letter-spacing: 0.05em;
	color: var( --color-muted );
	margin-bottom: 8px;
}

.concert-single__venue {
	font-size: 1.1rem;
	font-weight: 600;
	margin: 0 0 4px;
}

.concert-single__conductor,
.concert-single__soloists {
	color: var( --color-muted );
	margin: 0 0 4px;
}

.concert-single__program {
	margin-top: 32px;
}

.concert-single__tickets {
	margin-top: 32px;
	display: inline-block;
}

.concert-single__back {
	margin-top: 32px;
	margin-left: 16px;
	display: inline-block;
}

@media ( max-width: 560px ) {
	.concert-card {
		gap: 16px;
	}

	.concert-card__date {
		flex-basis: 68px;
	}

	.concert-card__day {
		font-size: 1.75rem;
	}
}

/* ==========================================================================
   18. Concert program — the full grant-facing program notes page (one
   composer/piece essay per section, jump nav, sponsor acknowledgement).
   Lives in .entry-content on a plain Page, not its own template.
   ========================================================================== */

.program-toc {
	display: flex;
	flex-wrap: wrap;
	gap: 8px 20px;
	margin: 0 0 48px;
	padding: 20px 0;
	border-top: 1px solid var( --color-border );
	border-bottom: 1px solid var( --color-border );
}

.program-toc a {
	text-transform: uppercase;
	font-size: 0.8rem;
	font-weight: 600;
	letter-spacing: 0.05em;
	text-decoration: none;
}

.program-toc a:hover {
	text-decoration: underline;
}

.program-note {
	margin: 0 0 72px;
	max-width: 65ch;
}

.program-note__header {
	display: flex;
	align-items: center;
	gap: 20px;
	margin-bottom: 20px;
}

.program-note__portrait {
	width: 96px;
	height: 96px;
	object-fit: cover;
	flex-shrink: 0;
}

.program-note__header h2 {
	margin: 0;
}

.program-note__piece {
	margin-top: 40px;
}

.program-backtotop {
	display: inline-block;
	margin-top: 8px;
	text-transform: uppercase;
	font-size: 0.8rem;
	font-weight: 600;
	letter-spacing: 0.05em;
}

.program-sponsor {
	max-width: 65ch;
	border: 1px solid var( --color-border );
	padding: 40px;
	margin: 0 0 48px;
}

.program-sponsor img {
	max-height: 64px;
	width: auto;
	margin-bottom: 24px;
}

.program-sponsor p {
	max-width: none;
}

@media ( max-width: 560px ) {
	.program-note__header {
		flex-direction: column;
		align-items: flex-start;
		gap: 12px;
	}

	.program-sponsor {
		padding: 24px;
	}
}

/* ==========================================================================
   19. Donate — a distinct one-off layout (circled-word headline, bold
   statement + attribution, two-column support copy + action buttons)
   rather than the site's usual prose/heading patterns, so it gets its
   own small section instead of reusing .entry-content defaults.
   ========================================================================== */

.donate-hero {
	max-width: var( --content-max );
	margin: 24px auto 56px;
	padding: 0 24px;
	text-align: center;
}

.donate-hero h1 {
	margin: 0;
}

/* The hand-circled "(alive)"/"(żyje)" — an inline-block wrapper gives the
   SVG a box to size itself against via inset, padded out a bit further
   than the text so the ring has room to clear the letterforms rather
   than hug them. preserveAspectRatio="none" lets the oval stretch to
   whatever width the word ends up at (different per language) — an
   ellipse is just a stretched circle, so the non-uniform scale still
   reads as one confident hand-drawn loop rather than a distortion. */
.circled-word {
	position: relative;
	display: inline-block;
	padding: 0.15em 0.3em;
}

.circled-word__mark {
	position: absolute;
	inset: -0.2em -0.15em;
	width: calc( 100% + 0.3em );
	height: calc( 100% + 0.4em );
	overflow: visible;
	pointer-events: none;
}

/* EXPERIMENT v2 — alternative to .circled-word above: the actual letterform
   outlines of "alive"/"żyje" (traced from Dancing Script Bold via
   fontTools + HarfBuzz shaping, offline — no font is loaded in the
   browser for this, the SVG paths ARE the letters), drawn on stroke by
   stroke in sequence like a pen, each letter's fill catching up just
   behind its outline, then a hand-drawn underline stroke at the end.
   Real text sits alongside for accessibility (see .screen-reader-text
   sibling in the markup); the SVG itself is aria-hidden. */
.handwrite {
	display: inline-block;
	height: 1.55em;
	width: auto;
	vertical-align: -0.32em;
	overflow: visible;
	color: inherit;
}

.handwrite path {
	fill: currentColor;
	fill-opacity: 0;
	stroke: currentColor;
	stroke-width: var( --glyph-stroke, 22 );
	stroke-linecap: round;
	stroke-linejoin: round;
	/* pathLength="1" normalizes each glyph's own contour length to 1
	   regardless of how visually complex that letter is, so one dash
	   animation works the same for a simple "i" and a looping "l". */
	stroke-dasharray: 1;
	stroke-dashoffset: 1;
}

.handwrite-underline {
	fill: none;
	stroke: currentColor;
	stroke-width: 26;
	stroke-linecap: round;
	stroke-linejoin: round;
	stroke-dasharray: 1;
	stroke-dashoffset: 1;
	animation: handwrite-stroke 0.6s ease-out forwards;
}

@keyframes handwrite-stroke {
	to {
		stroke-dashoffset: 0;
	}
}

@keyframes handwrite-fill {
	to {
		fill-opacity: 1;
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.handwrite path,
	.handwrite-underline {
		animation: none !important;
		stroke-dashoffset: 0;
		fill-opacity: 1;
	}
}

.donate-statement {
	max-width: 50ch;
	margin: 0 auto 64px;
	padding: 0 24px;
	text-align: center;
}

.donate-statement__lines {
	margin: 0 0 16px;
	font-size: clamp( 1.1rem, 2vw, 1.5rem );
	line-height: 1.3;
}

.donate-statement cite {
	display: block;
	font-style: italic;
	font-family: var( --font-body );
	color: var( --color-muted );
}

.donate-grid {
	display: grid;
	grid-template-columns: minmax( 0, 460px ) minmax( 260px, 340px );
	justify-content: center;
	gap: 40px 64px;
	max-width: 900px;
	margin: 0 auto 24px;
	padding: 0 24px;
}

.donate-lede,
.donate-list li,
.donate-note {
	font-style: italic;
}

.donate-lede {
	margin-bottom: 16px;
}

.donate-list {
	list-style: disc outside;
	padding-left: 1.2em;
	margin: 0 0 32px;
}

.donate-list li {
	margin-bottom: 10px;
}

.donate-note {
	max-width: none;
}

.donate-grid__actions {
	display: flex;
	flex-direction: column;
	gap: 24px;
	align-content: flex-start;
}

.donate-action {
	width: 100%;
	text-align: center;
	padding: 22px 28px;
}

@media ( max-width: 780px ) {
	.donate-grid {
		grid-template-columns: 1fr;
	}

	.donate-grid__actions {
		max-width: 360px;
	}
}
