/*
Theme Name: SIVA
Theme URI:
Author:
Author URI:
Description: Custom WordPress theme for SIVA — homepage venue map (blog deferred to post-launch).
Version: 0.1.0
Requires at least: 6.4
Requires PHP: 8.0
Text Domain: siva
*/

/* Base styles — replace with the real Figma-derived styles once the design is finalised.
   Keep global CSS here; component-specific CSS can live in assets/css and be enqueued
   from functions.php instead if it grows large. */

/* Standard reset, missing until now — without it, padding/border ADD to
   any explicitly-set width (the browser default is content-box), which
   is what caused .venue-map-section to render 20px wider than its
   1200px cap (its own 10px padding on each side was adding on top).
   Likely affects other already-sized elements too; border-box is what
   every value in this file has implicitly assumed. */
*, *::before, *::after {
	box-sizing: border-box;
}

/* Client's own custom heading typeface, self-hosted — replaced Anton
   (the free Google Fonts lookalike used until the real one was
   available) on 2026-09-17. No external request for this one at all. */
@font-face {
	font-family: 'SIVA Heading';
	src: url('assets/fonts/SIVAsiva.otf') format('opentype');
	font-weight: normal;
	font-style: normal;
	font-display: swap;
}

/* Body font, self-hosted (was Google Fonts until 2026-09-21): no third-party
   request, no visitor IPs sent to Google (a GDPR concern in the UK/EU), one
   less connection before text can render. Archivo is licensed under the SIL
   Open Font License, which permits this. One variable-font file covers every
   weight; the range below is the ones the site uses (300 body, 600 for bold
   text in venue descriptions). Latin subset only -- a character outside it
   (rare for Sheffield venue names) falls back to the system font in
   --siva-font-body's stack. */
@font-face {
	font-family: 'Archivo';
	src: url('assets/fonts/Archivo-latin.woff2') format('woff2');
	font-weight: 300 600;
	font-style: normal;
	font-display: swap;
}

/* Design tokens — pulled from Figma's own Variables via get_design_context
   on 2026-09-09 (fileKey N4nbg0DVMlYubNtpXpMIPY, node 2:2), not guessed. */
:root {
	--siva-dark: #393939;
	--siva-pink: #FF4E9D;
	--siva-white: #ffffff;
	--siva-grey: #b2b2b2;
	--siva-black: #101010;

	/* Headings: was 'Anton' (free Google Fonts lookalike matching Figma's
	   "Anton SC" spec) — replaced 2026-09-17 with the client's own custom
	   typeface, self-hosted (see @font-face above). Not keeping Anton as
	   a fallback here — it's no longer loaded at all (removed from the
	   Google Fonts request in functions.php), so listing it would be
	   misleading; a plain sans-serif fallback is honest about what
	   actually happens if the local OTF fails to load. */
	--siva-font-heading: 'SIVA Heading', sans-serif;
	/* The custom typeface's own letter spacing is tight enough that
	   glyphs overlap at this uppercase/display scale — added 2026-09-17.
	   Centralized as a token (referenced next to every
	   font-family: var(--siva-font-heading) below) so it only needs
	   tuning in one place; Anton didn't need this. */
	--siva-heading-letter-spacing: 0.1em; /* was 0.03em, bumped per request 2026-09-17 */

	/* Body: Figma specifies "Neue Haas Grotesk Display Pro" — a PAID
	   Linotype/Monotype font. Client decided (2026-09-10) to use a free
	   lookalike rather than license it: Archivo, one of the closest free
	   grotesques to Helvetica/Neue Haas Grotesk's own lineage. Self-hosted
	   (see @font-face above). Revisit if a real license is bought. */
	--siva-font-body: 'Archivo', -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;

	/* Type scale + spacing — FLUID (2026-09-16), not a two-step mobile/
	   desktop swap. Each clamp(MIN, preferred, MAX) scales continuously
	   with viewport width between our two real reference points — the
	   Figma mobile frame (393px) and desktop frame (1440px) — instead of
	   jumping instantly at a breakpoint and then sitting static outside
	   that one 393px/1440px data point. MIN/MAX are the values from those
	   frames (get_design_context, some bumped afterward per request); the
	   middle term is the standard linear interpolation between them:
	     slope = (max - min) / (1440 - 393)
	     preferred = (min - slope * 393) + (slope * 100)vw
	   Below 393px it holds at MIN; above 1440px it holds at MAX — same
	   floor/ceiling as before, just smooth in between rather than a hard
	   jump at 48rem. Recompute both reference values and redo the formula
	   above if a token's min/max ever changes.
	   --siva-block-gap stays deliberately NOT fluid — Figma uses the same
	   value at both breakpoints and nothing on desktop needed it to grow
	   further. --siva-tight-gap and --siva-text-body WERE flat like that
	   too, but that meant button padding/text (they're the ones built
	   from these two) never got the +10% pass below — buttons are still
	   flat-ish (11px/19.8px ceiling is barely a stretch off 10px/18px)
	   but now genuinely scale on desktop like everything else. */
	/* Desktop (MAX) ends of every clamp below were bumped +10% per request
	   2026-09-16 — mobile (MIN) ends deliberately untouched, this was
	   about the desktop site feeling small, not mobile. Re-derived each
	   formula from the new max, same method as above. */
	/* Mobile-review fix, 2026-09-18: the flat 0.7x scale-down above made
	   both of these smaller than body text at the mobile end (hero
	   16.8px, subhead 14px, vs. body's 18px) — inverted hierarchy on a
	   phone. Re-derived with a raised mobile floor, desktop max
	   untouched (that end was never flagged as a problem). */
	--siva-text-hero: clamp(1.75rem, 1.25rem + 2.03vw, 3.08rem);      /* 28px -> 49.3px */
	--siva-text-subhead: clamp(1.375rem, 1.17rem + 0.84vw, 1.925rem); /* 22px -> 30.8px */
	--siva-text-body: clamp(1.125rem, 1.08rem + 0.17vw, 1.2375rem);     /* 18px -> 19.8px — was flat both breakpoints; now fluid so button/nav/venue-card text scales on desktop too, per request 2026-09-17 */
	--siva-text-body-small: clamp(1rem, 0.91rem + 0.36vw, 1.2375rem);   /* 16px -> 19.8px (was 18px) — About/footer copy specifically (Figma sizes these down on mobile even though the venue card stays at 18px) */

	--siva-container-px: clamp(0.625rem, -0.69rem + 5.35vw, 4.125rem);  /* 10px -> 66px — page/section horizontal padding. Was 10px -> 132px (originally 120px); halved per request 2026-09-21, side margins read about 2x too big between 1024px and 1456px. Re-derived: slope = (66-10)/(1440-393) */
	--siva-container-py: clamp(0.625rem, 0.09rem + 2.2vw, 2.0625rem);   /* 10px -> 33px (was 30px) — page/section vertical padding */
	--siva-section-gap: clamp(2.5rem, 2.15rem + 1.43vw, 3.4375rem);     /* 40px -> 55px (was 50px) — gap between major page sections */
	--siva-block-gap: 1.5rem;      /* Figma value was 20px (1.25rem); bumped to 1.5rem (24px) per request 2026-09-10 — flat/same at both breakpoints already, not part of the desktop-only +10% pass — gap within a section (e.g. About heading to its columns) */
	--siva-tight-gap: clamp(0.625rem, 0.6rem + 0.1vw, 0.6875rem);       /* 10px -> 11px — was flat both breakpoints; now fluid so button/tag/grid padding (used everywhere, including every button) scales on desktop too, per request 2026-09-17 */
	--siva-footer-px: clamp(0.625rem, -4.3rem + 20.06vw, 13.75rem);     /* 10px -> 220px (was 200px) — the About/footer block gets EXTRA indent on desktop, see below */

	/* Max-width caps — without these, content just kept stretching wider
	   forever past Figma's 1440px frame width on larger screens, since
	   padding alone never stops growing. Per request 2026-09-10. Not
	   fluid themselves — they're the hard ceiling the clamps above feed
	   into via width: min(100% - 2*gutter, max) elsewhere in this file. */
	--siva-container-max: 75rem;        /* 1200px — header, hero/map */
	--siva-container-max-narrow: 50rem; /* 800px — About/footer (corrected 2026-09-10, was 1000px) */
}

/* Two real LAYOUT breakpoints (discrete mode switches, not something
   clamp() can express) — only the sizing TOKENS above are fluid:
   - 48rem / 768px: nav collapses to a hamburger below it, footer columns
     go from stacked to a wrapping row above it. Start of "tablet".
   - 64rem / 1024px: the map + venue panel go from stacked (mobile AND
     tablet) to side by side, at the capped desktop container width.
     Tablet keeps them stacked because side by side leaves the panel too
     short for the venue photos.
   There's no Figma tablet frame — see the "Tablet" block further down for
   the rules used instead. */

body {
	margin: 0;
	font-family: var(--siva-font-body);
	font-size: var(--siva-text-body);
	font-weight: 300; /* Archivo Light — brought down from the default 400 per request 2026-09-10 */
	line-height: normal;
	background: var(--siva-dark);
	color: var(--siva-white);
}

/* The About/footer copy specifically downsizes on mobile in Figma, even
   though body text elsewhere (venue card, buttons) stays at the same
   size on both breakpoints — see --siva-text-body-small. */
.site-footer__about p {
	font-size: var(--siva-text-body-small);
}

.site-footer__about p + p {
	margin-top: var(--siva-tight-gap); /* the keyword sentence under the bio reads as its own line, not a run-on */
}

h1, h2, h3, h4, h5, h6 {
	font-family: var(--siva-font-heading);
	letter-spacing: var(--siva-heading-letter-spacing);
	text-transform: uppercase;
	font-weight: normal; /* Anton is already a bold display face at weight 400 */
}

/* Figma's spacing is entirely gap-driven (every block is a flex column
   with an explicit gap value, never relying on element spacing) — reset
   browser default margins on headings/paragraphs globally so nothing
   silently stacks on top of a flex gap and inflates it. Hit this exact
   bug on the footer's heading-to-icon spacing: a flex gap PLUS the
   browser's own h3 margin were both applying at once. */
h1, h2, h3, h4, h5, h6, p {
	margin: 0;
}

a {
	color: inherit;
}

/* Icon utility — renders an SVG as a CSS mask filled with `currentColor`,
   instead of an <img src="...svg">. An <img>-referenced SVG can't be
   recolored via CSS (it renders in its own isolated context, so
   `currentColor`/CSS variables inside it never see the host page's
   styles) — that's what made the icon-button hover color-invert
   impossible before. A mask has no such isolation: the shape comes from
   the SVG, the color comes from `background-color: currentColor`, so it
   follows the same `color` property the surrounding button already
   flips on hover. */
.icon {
	display: inline-block;
	background-color: currentColor;
	mask-repeat: no-repeat;
	mask-position: center;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	-webkit-mask-position: center;
	-webkit-mask-size: contain;
}

.icon--instagram {
	width: 1.6875rem; /* 27px, Figma's asset size */
	height: 1.6875rem;
	mask-image: url("assets/images/icon-instagram.svg");
	-webkit-mask-image: url("assets/images/icon-instagram.svg");
}

.icon--search {
	width: 1rem; /* 16px, Figma's ant-design search icon size */
	height: 1rem;
	mask-image: url("assets/images/icon-search.svg");
	-webkit-mask-image: url("assets/images/icon-search.svg");
}

/* Replaces the plain "←"/"→" unicode characters used for the map
   prev/next buttons and the "Upcoming events" link — per request
   2026-09-17, using the client's own arrow artwork instead. Same
   width/height for both so they read as a matched pair; mask-size:
   contain (via .icon) keeps each SVG's own aspect ratio inside that box
   regardless of the two files having slightly different native ratios. */
.icon--arrow-left,
.icon--arrow-right {
	width: 1.25rem;
	height: 0.9rem;
}

.icon--arrow-left {
	mask-image: url("assets/images/icon-arrow-left.svg");
	-webkit-mask-image: url("assets/images/icon-arrow-left.svg");
}

.icon--arrow-right {
	mask-image: url("assets/images/icon-arrow-right.svg");
	-webkit-mask-image: url("assets/images/icon-arrow-right.svg");
}

/* --- Header / nav — mobile-first, hamburger below the tablet breakpoint --- */

.site-header {
	position: relative; /* .site-nav's "top: 100%" below needs this to be the positioned ancestor it measures from -- without it, the mobile dropdown positioned against the viewport instead and opened ~a screen-height down, overlapping the footer */
	display: flex;
	align-items: center;
	justify-content: space-between;
	/* min() gives padding-like gutters on small screens, but locks to the
	   1200px cap + auto-centers once the viewport is wide enough — plain
	   padding alone never stops growing, which was the actual bug. */
	width: min(100% - 2 * var(--siva-container-px), var(--siva-container-max));
	margin-inline: auto;
	padding-block: var(--siva-container-py);
}

.site-header__logo {
	display: block;
}

.site-header__logo img {
	display: block;
	width: 5.15625rem; /* 82.5px — 50% bigger than Figma's 55px mobile spec, per request 2026-09-18 */
	height: 3.28125rem; /* 52.5px — same 50%, keeps the logo's own aspect ratio */
}

@media (min-width: 48rem) {
	.site-header__logo img {
		width: 7.2875rem;  /* 116.6px — Figma's desktop logo size (106px) +10% per request 2026-09-16 */
		height: 4.60625rem; /* 73.7px — same +10%, keeps the logo's own aspect ratio */
	}
}

/* --- Shared typography — sized from the Figma type scale, see :root --- */

.site-title {
	font-size: var(--siva-text-hero);
	margin: 0;
}

.site-subhead {
	font-size: var(--siva-text-subhead);
	margin: 0;
}

.site-footer h3 {
	font-size: var(--siva-text-subhead);
}

/* Width-capped, auto-centered containers — see --siva-container-max /
   --siva-container-max-narrow in :root. The map itself is full-bleed on
   mobile (matches Figma) but joins the same 1200px-capped container as
   everything else on desktop, so it only gets this applied above the
   breakpoint. */
.site-container {
	width: min(100% - 2 * var(--siva-container-px), var(--siva-container-max));
	margin-inline: auto;
}

@media (min-width: 64rem) {
	.venue-map {
		width: min(100% - 2 * var(--siva-container-px), var(--siva-container-max));
		margin-inline: auto;
	}
}

.site-nav__toggle {
	display: flex; /* was padding-sized (25px icon + 2*8px padding = 41px) -- explicit box meets the WCAG/Apple touch-target minimum, per mobile review 2026-09-18 */
	align-items: center;
	justify-content: center;
	width: 3.4375rem; /* 44px touch-target base, +25% per request 2026-09-18 */
	height: 3.4375rem;
	background: none;
	border: none;
	color: var(--siva-white);
	cursor: pointer;
	padding: 0;
	transition: opacity 0.15s ease, transform 0.15s ease;
}

.site-nav__toggle:hover,
.site-nav__toggle:focus-visible {
	opacity: 0.7;
	transform: scale(1.08);
}

.site-nav__toggle-icon {
	display: block;
	width: 1.953125rem; /* 25px Figma asset, +25% to match the button above, per request 2026-09-18 */
	height: 1.953125rem;
}

.site-nav {
	display: none;
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	flex-direction: column;
	gap: 0.5rem;
	padding: 1rem;
	background: var(--siva-dark);
	z-index: 10;
}

.site-nav--open {
	display: flex;
}

.site-nav__link--button {
	background: var(--siva-pink);
	color: var(--siva-dark);
	font-family: var(--siva-font-heading);
	letter-spacing: var(--siva-heading-letter-spacing);
	text-transform: uppercase;
	text-decoration: none;
	padding: var(--siva-tight-gap); /* was a hardcoded literal matching --siva-tight-gap by coincidence, which meant it silently missed the +10% desktop pass -- fixed 2026-09-17 to actually reference the token */
	text-align: center;
	transition: background-color 0.15s ease, color 0.15s ease;
}

.site-nav__link--button:hover,
.site-nav__link--button:focus-visible {
	background: var(--siva-dark);
	color: var(--siva-pink);
}

.site-nav__icon-link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: background-color 0.15s ease, color 0.15s ease;
	background: var(--siva-pink);
	color: var(--siva-dark); /* drives the icon's color via currentColor, see .icon */
	text-decoration: none;
	padding: var(--siva-tight-gap); /* was hardcoded, same value as --siva-tight-gap by coincidence -- fixed 2026-09-17 to actually reference the token so it gets the desktop-fluid scaling */
}

.site-nav__icon-link:hover,
.site-nav__icon-link:focus-visible {
	background: var(--siva-dark);
	color: var(--siva-pink);
}

/* Above the tablet breakpoint: nav is always visible, hamburger hidden.
   TODO: replace 48rem with the real Figma breakpoint once confirmed. */
@media (min-width: 48rem) {
	.site-nav__toggle {
		display: none;
	}

	.site-nav {
		display: flex;
		position: static;
		flex-direction: row;
		width: auto;
		padding: 0;
		background: none;
	}
}

.site-main {
	padding-top: var(--siva-container-py);
	padding-bottom: var(--siva-section-gap);
	display: flex;
	flex-direction: column;
	gap: var(--siva-tight-gap); /* H1-to-map gap is a tight 10px in Figma, not the larger section gap */
}

/* --- Venue map + panel — functional styling, restyle further once the
   real map artwork exists (still a placeholder image) --- */

.venue-map-section {
	display: flex;
	flex-direction: column;
	gap: var(--siva-tight-gap);
	padding: var(--siva-tight-gap);
	background: var(--siva-pink);
	touch-action: pan-y; /* lets vertical page scroll start immediately on touch, while map.js's pointer drag still gets first say on horizontal movement -- per request 2026-09-18 */
}

@media (min-width: 64rem) {
	.venue-map-section {
		flex-direction: row;
		/* align-items stays at its default (stretch) here — the panel
		   column (and the venue-panel "black box" inside it) should always
		   fill the row's full height. .venue-map opts OUT of that via its
		   own align-self below, since it has a definite height already
		   (aspect-ratio) and shouldn't be force-stretched taller. */
		/* Same width-capped, centered container as .site-header/.site-container
		   — this was missing entirely, so the section was running full
		   viewport width on desktop instead of joining the 1200px column
		   everything else sits in. Mobile stays full-bleed (matches Figma). */
		width: min(100% - 2 * var(--siva-container-px), var(--siva-container-max));
		margin-inline: auto;
	}
}

.venue-map {
	position: relative;
	max-width: 100%;
	/* No max-height — the aspect-ratio below already gives it a definite,
	   contained size derived from its own width, not the row's height
	   (align-self: flex-start, in the desktop rule below), so a height
	   cap would only ever crop the image rather than actually constrain
	   anything. Removed 2026-09-10 — 25rem was cropping well over half
	   the real map image. */
	aspect-ratio: 1; /* the real map artwork (Map v3) is a perfect 2000x2000 square, so the box matches it exactly and nothing gets cropped. Was 1317/1274, sized to the old "Map Stand In" placeholder, per request 2026-09-21 */
	overflow: hidden;
}

@media (min-width: 64rem) {
	.venue-map {
		flex: 1 1 55%;
		align-self: flex-start; /* opts out of the row's default stretch — see .venue-map-section above */
	}
}

/* --- Tablet: 48rem-63.99rem (768px-1023px) ---
   There's no Figma frame for this, so per request 2026-09-21 it follows
   two rules instead:
   1. The container is 100% wide -- the same tight gutter as mobile, not
      the desktop side margins (which grow to 132px). Everything sized off
      --siva-container-px (header, page container, footer, lightbox)
      follows from overriding that one token; the map section runs edge
      to edge, as it does on mobile.
   2. Text scales up from mobile but stays smaller than desktop. Already
      true with no extra rules: every type token in :root is a fluid
      clamp() interpolated between the 393px and 1440px Figma frames, so
      768px lands part-way between the two.
   The map + venue panel STACK here exactly as on mobile (arrows over the
   map corner, full-width save-list bar, etc. -- those rules are scoped to
   max-width: 63.99rem), and only go side by side from 64rem: side by side
   at tablet width left the panel too short to fit the venue photos. */
@media (min-width: 48rem) and (max-width: 63.99rem) {
	:root {
		--siva-container-px: 0.625rem;
	}

	.venue-map-section {
		width: 100%;
		margin-inline: 0;
	}
}

.venue-map__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.venue-marker {
	position: absolute;
	/* -100% on Y (not -50%) anchors the pin's BOTTOM at the stored x/y% —
	   correct for a teardrop pin shape, where the tip (not the visual
	   center of its bounding box) is what actually points at the
	   location, same convention as Google Maps-style pins. Per request
	   2026-09-16. transform-origin below keeps hover/selected scaling
	   growing from that same anchor point rather than the box's center. */
	transform: translate(-50%, -100%) scale(0.8);
	transform-origin: bottom center;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.75rem; /* reverted to this 2026-09-18 -- sizing up to hit a 44px effective tap target (post scale(0.8)) made the pins read as too big; back to the original visual size */
	height: 2.75rem;
	border: none;
	background: none;
	cursor: pointer;
	padding: 0;
	transition: transform 0.15s ease;
}

/* The pin is an inline SVG (see front-page.php), not a CSS mask/background
   image, so it can have a real stroke. Every earlier attempt at an
   outline was fighting the fact that a mask is only a shape and can't
   be stroked (filter: drop-shadow was clipped away by the mask itself;
   layering two sized masks never lined up at the tip). Fill/stroke swap
   per state instead. Pins are fully opaque black at rest. Per request
   2026-09-21. */
.venue-marker__pin {
	display: block;
	width: 1.825rem;
	aspect-ratio: 32.7998 / 41; /* the Figma pin's own proportions */
	overflow: visible; /* a stroke straddles the path edge, so half of it falls outside the viewBox */
	fill: var(--siva-black);
	stroke: transparent;
	stroke-width: 8; /* viewBox units (~0.9px each); only the outer half shows, see paint-order. Was 5, thickened per request 2026-09-21 */
	stroke-linejoin: round; /* keeps the tip from spiking past the anchor point */
	paint-order: stroke; /* stroke first, fill on top -- only the OUTER half of the stroke is visible, so the fill keeps its full size */
	transition: fill 0.15s ease, stroke 0.15s ease;
}

/* Selected/hover: pink fill with a black outline. Plain pink disappeared
   against the map's own pink background; the outline keeps it legible. */
.venue-marker--selected .venue-marker__pin,
.venue-marker:hover .venue-marker__pin,
.venue-marker--preview .venue-marker__pin { /* --preview: set by map.js while a row in the venue list is hovered/focused, so you can see where it is before clicking */
	fill: var(--siva-pink);
	stroke: var(--siva-black);
}

.venue-marker--selected {
	transform: translate(-50%, -100%) scale(1);
}

/* Markers paint in DOM order by default, so a hovered/focused marker's
   label could render underneath a later, nearby marker instead of
   clearly above it. Raising it (and its ::after label, which shares its
   stacking context) above every other marker fixes that. Per request
   2026-09-18. */
.venue-marker--selected,
.venue-marker:hover,
.venue-marker:focus-visible,
.venue-marker--preview {
	z-index: 1;
}

.venue-marker:hover,
.venue-marker--preview {
	transform: translate(-50%, -100%) scale(1.15); /* keep the base anchor translate, just add scale (from transform-origin: bottom center) */
}

.venue-marker:focus-visible {
	outline: 0.1875rem solid var(--siva-white); /* stroke width — kept px-equivalent for crisp rendering, see plan; white for contrast against the pink map background */
	outline-offset: 0.125rem;
}

/* Hover/focus tooltip showing the venue name — reuses the marker's own
   aria-label via attr() rather than a separate data attribute, so
   there's only one source of truth for the name. Per request
   2026-09-17. Keyboard-reachable too (:focus-visible), not just mouse
   hover. */
.venue-marker::after {
	content: attr(aria-label);
	position: absolute;
	/* The marker's icon graphic is smaller than its own box (see the pin
	   background-size above) and centered within it, so there's several
	   px of transparent box padding above the icon itself before you
	   even get to this offset — pulling IN past 100% (not adding to it)
	   accounts for that so the label sits visually close to the pin, not
	   just close to its invisible box edge. Was +0.375rem, then
	   +0.125rem, then +0.0625rem, all additive and all still reading as
	   too large a gap since none of them touched this. Per request
	   2026-09-18. */
	bottom: calc(100% - 0.125rem); /* was -0.25rem; nudged out a little per request 2026-09-21 (the thicker pin outline also eats into the gap) */
	left: 50%;
	/* --tooltip-shift: set by map.js when centering on the marker would
	   push this past the map's left/right edge -- keeps the whole label
	   inside .venue-map's clipped bounds instead of cutting it off. */
	transform: translateX(calc(-50% + var(--tooltip-shift, 0px)));
	background: var(--siva-black);
	color: var(--siva-white);
	font-family: var(--siva-font-body);
	font-weight: 300;
	font-size: 0.875rem;
	line-height: 1.2;
	white-space: nowrap;
	padding: 0.25rem 0.5rem;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.15s ease;
	z-index: 10;
}

.venue-marker:hover::after,
.venue-marker:focus-visible::after,
.venue-marker--preview::after {
	opacity: 1;
}

/* Markers close to the map's top edge (measured by map.js's
   updateTooltipDirections()) would otherwise open their tooltip mostly
   above .venue-map's own box, which clips it (overflow: hidden) and
   made it invisible. Open downward instead for those. Per request
   2026-09-18. */
.venue-marker--tooltip-below::after {
	bottom: auto;
	top: calc(100% - 0.125rem);
}

.venue-map-section__panel-col {
	display: flex;
	flex-direction: column;
	gap: var(--siva-tight-gap);
	/* max-height is set inline by map.js's syncPanelHeight(), matching
	   .venue-map's actual rendered height — CSS alone can't express "cap
	   at a sibling's height" (flex/grid only ever grow a row to fit its
	   TALLEST item, there's no "shrink to the shortest" mode), and the
	   map's height has to be the one driving this, not the panel, since
	   the map must never be cropped/stretched away from its own aspect
	   ratio. Without this, real venue content (more photos, a longer
	   description) can make the panel taller than the map. */
}

@media (min-width: 64rem) {
	.venue-map-section__panel-col {
		flex: 1 1 45%;
	}
}

.venue-panel {
	flex: 1;
	min-height: 0; /* lets this actually shrink within panel-col's JS-set max-height (see map.js syncPanelHeight()), instead of just growing to its content's natural size */
	display: flex; /* lets .venue-panel__content below fill its full height */
	background: var(--siva-dark);
	color: var(--siva-white);
	padding: var(--siva-tight-gap);
	overflow-x: hidden; /* clips .venue-panel__content during its slide transition */
	overflow-y: auto; /* safety net if a venue's content genuinely can't fit in the space the map allows — scrolls rather than breaking the layout or exceeding the map's height */
}

.venue-panel__content {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--siva-tight-gap);
	transition: transform 0.2s ease, opacity 0.2s ease;
	flex: 1;
	min-height: 0; /* allows the gallery's flex: 1 below to actually shrink/grow within a flex column, rather than being pushed out to its content size */
	width: 100%; /* align-items: flex-start above would otherwise shrink this to its content's width */
}

/* Set by map.js for the duration of an active drag -- while it's
   following the pointer 1:1 (via an inline transform), the normal
   transition would introduce lag between finger/cursor and content
   instead of true 1:1 tracking. Per request 2026-09-18. */
.venue-panel__content--dragging {
	transition: none;
}

/* Holds every "a venue is selected" field (gallery, name, address,
   description, actions) as one unit -- map.js shows/hides this single
   wrapper to switch out of the default placeholder state, rather than
   toggling each field individually (previously did that, and it was easy
   to add a new field and forget its hidden toggle). Needs the same
   flex-column setup .venue-panel__content has, since it's now the direct
   parent of the gallery's flex: 1. */
.venue-panel__details {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--siva-tight-gap);
	flex: 1;
	min-height: 0;
	width: 100%;
}

.venue-panel__details[hidden] {
	display: none;
}

/* Subtle left/right slide+fade when switching venues — plain CSS
   transitions, no animation library needed. See goToVenue() in map.js
   for how these classes get toggled. */
.venue-panel__content--leave-next {
	transform: translateX(-1.25rem);
	opacity: 0;
}

.venue-panel__content--leave-prev {
	transform: translateX(1.25rem);
	opacity: 0;
}

/* The --enter-* states set the STARTING position for content that just
   swapped in, with transitions disabled so jumping there is instant/
   invisible — removing the class then lets the base rule's transition
   animate it back to rest. */
.venue-panel__content--enter-next {
	transition: none;
	transform: translateX(1.25rem);
	opacity: 0;
}

.venue-panel__content--enter-prev {
	transition: none;
	transform: translateX(-1.25rem);
	opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
	.venue-panel__content,
	.venue-panel__content--leave-next,
	.venue-panel__content--leave-prev,
	.venue-panel__content--enter-next,
	.venue-panel__content--enter-prev {
		transition: none;
		transform: none;
		opacity: 1;
	}
}

.venue-panel__gallery {
	display: grid;
	grid-template-columns: 1fr 1fr;
	grid-template-rows: 1fr 1fr; /* rows now fill whatever height flex: 1 gives the grid, rather than being sized by the photos' own aspect-ratio */
	gap: var(--siva-tight-gap);
	width: 100%;
	flex: 1; /* the gallery is the part that grows/shrinks to fill whatever space is left in the panel (name/address/description/actions keep their natural size) */
	min-height: 0;
}

/* Explicit — author styles otherwise override the UA [hidden] rule even
   at equal specificity, since author origin always wins. Hit this exact
   bug already with the old venue-modal; not repeating it. */
.venue-panel__gallery[hidden],
.venue-panel__instagram[hidden],
.venue-panel__events-btn[hidden] {
	display: none;
}

/* Default "nothing selected yet" state: a search field over a scrollable
   list of every venue, swapped for the real venue content the moment one
   is selected and swapped back on a click off the map / "Back to list"
   (see map.js renderPanel()). Per Figma frame 55:81, 2026-09-21. */
.venue-panel__browse {
	display: flex;
	flex-direction: column;
	gap: var(--siva-tight-gap);
	flex: 1;
	min-height: 0; /* lets the list below actually shrink and scroll inside the panel's height cap, rather than pushing the panel taller */
	width: 100%;
}

.venue-panel__browse[hidden] {
	display: none;
}

.venue-search {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex: none;
	min-height: 2.625rem; /* 42px, Figma */
	padding-inline: 0.5rem;
	background: var(--siva-white);
	color: var(--siva-dark);
}

.venue-search:focus-within {
	outline: 0.1875rem solid var(--siva-pink);
	outline-offset: 0.125rem;
}

.venue-search__input {
	flex: 1;
	min-width: 0;
	padding-block: 0.5rem;
	border: none;
	border-radius: 0;
	background: transparent;
	color: var(--siva-dark);
	font: inherit; /* body font at body size -- also keeps iOS from zooming the page on focus, which it does for inputs under 16px */
	-webkit-appearance: none;
	appearance: none;
	outline: none; /* the focus ring is on .venue-search via :focus-within instead, so it wraps the icon too */
}

.venue-search__input::-webkit-search-cancel-button {
	-webkit-appearance: none; /* the browser's default blue clear (x) is off-brand */
}

.venue-search__input::placeholder {
	/* Was --siva-grey (#b2b2b2): only 2.1:1 on the white field, and this
	   text is the search instructions -- needs 4.5:1. #6b6b6b is 5.3:1.
	   Accessibility audit, 2026-09-21. */
	color: #6b6b6b;
	opacity: 1; /* Firefox dims placeholders by default */
}

.venue-list {
	list-style: none;
	margin: 0;
	padding: 0;
	padding-right: var(--siva-tight-gap); /* keeps the rows off the scrollbar */
	flex: 1;
	min-height: 0;
	overflow-y: auto;

	/* Same brand scrollbar as the photo lightbox. */
	scrollbar-width: thin;
	scrollbar-color: var(--siva-pink) transparent;
}

.venue-list::-webkit-scrollbar {
	width: 0.5rem;
}

.venue-list::-webkit-scrollbar-track {
	background: transparent;
}

.venue-list::-webkit-scrollbar-thumb {
	background-color: var(--siva-pink);
	border-radius: 999px;
}

.venue-list__item {
	border-bottom: 0.0625rem solid var(--siva-grey); /* Figma's hairline divider between rows */
}

.venue-list__link {
	display: block;
	padding-block: var(--siva-tight-gap);
	color: var(--siva-white);
	/* Same type settings as the other headings ("Follow us" etc.), per request. */
	font-family: var(--siva-font-heading);
	font-size: var(--siva-text-subhead);
	letter-spacing: var(--siva-heading-letter-spacing);
	text-transform: uppercase;
	text-decoration: none;
	transition: color 0.15s ease;
}

.venue-list__link:hover,
.venue-list__link:focus-visible {
	color: var(--siva-pink);
}

.venue-list__empty {
	margin: 0;
	color: var(--siva-grey);
}

.venue-list__empty[hidden] {
	display: none;
}

/* Mobile + tablet: below the 64rem breakpoint the panel isn't height-capped
   (see syncPanelHeight() in map.js), so flex: 1 above has nothing to
   fill -- cap the list explicitly so a long list scrolls instead of
   pushing the rest of the page way down. */
@media (max-width: 63.99rem) {
	.venue-list {
		flex: none;
		max-height: 19rem;
	}
}

/* map.js moves focus here after a keyboard selection so a screen reader
   announces the venue -- it's focused by script, not something to tab to,
   so it doesn't want a focus ring. */
.venue-panel__name:focus {
	outline: none;
}

.venue-panel__back {
	align-self: flex-start;
	display: inline-flex;
	align-items: center;
	gap: 0.375rem;
	padding: 0;
	border: none;
	background: none;
	color: var(--siva-grey);
	font: inherit;
	text-decoration: underline;
	cursor: pointer;
	transition: color 0.15s ease;
}

.venue-panel__back:hover,
.venue-panel__back:focus-visible {
	color: var(--siva-white);
}

.venue-panel__back .icon {
	width: 1rem; /* same 1.25 : 0.9 proportions as the other arrow icons, just smaller for a text link */
	height: 0.72rem;
}

.venue-panel__photo {
	position: relative;
	display: block;
	width: 100%;
	height: 100%; /* fills its grid cell — the gallery (not each individual photo) is what's constrained, via flex: 1 above */
	padding: 0;
	border: none;
	background: none;
	cursor: pointer;
	overflow: hidden;
}

/* Mobile + tablet: the panel isn't height-capped below the 64rem breakpoint
   (see syncPanelHeight() in map.js), so flex: 1 / 1fr rows above had
   nothing to actually constrain against and the tiles rendered very
   tall (~450px). An explicit aspect-ratio replaces that open-ended
   fill behaviour with a fixed, predictable tile shape -- about half
   that previous height. Desktop is unaffected (still height-capped, so
   flex: 1 does real work there). Per request 2026-09-18. */
@media (max-width: 63.99rem) {
	.venue-panel__gallery {
		grid-template-rows: auto auto;
	}

	.venue-panel__photo {
		height: auto;
		aspect-ratio: 3 / 2; /* was 4/5 -- still read as too tall, per request 2026-09-18 */
	}
}

.venue-panel__photo img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.venue-panel__photo-overflow {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(16, 16, 16, 0.6); /* var(--siva-black) at reduced opacity */
	color: var(--siva-white);
	font-family: var(--siva-font-heading);
	letter-spacing: var(--siva-heading-letter-spacing);
	font-size: var(--siva-text-body);
}

.venue-panel__address {
	color: var(--siva-grey);
}

.venue-panel__address a,
.venue-panel__read-more {
	color: var(--siva-grey);
	text-decoration: underline;
}

.venue-panel__actions {
	display: flex;
	gap: var(--siva-tight-gap);
}

.venue-panel__events-btn {
	display: inline-flex; /* so the arrow icon (added 2026-09-17, replacing a plain "→" character) sits centered with a small gap after the text, instead of just wrapping inline */
	align-items: center;
	gap: 0.375rem;
	background: var(--siva-pink);
	color: var(--siva-dark);
	font-family: var(--siva-font-heading);
	letter-spacing: var(--siva-heading-letter-spacing);
	text-transform: uppercase;
	text-decoration: none;
	padding: var(--siva-tight-gap); /* was hardcoded, same value as --siva-tight-gap by coincidence -- fixed 2026-09-17 to actually reference the token so it gets the desktop-fluid scaling */
	transition: background-color 0.15s ease, color 0.15s ease;
}

.venue-panel__events-btn:hover,
.venue-panel__events-btn:focus-visible {
	background: var(--siva-dark);
	color: var(--siva-pink);
}

.venue-panel__instagram {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* No fixed width/height — .venue-panel__actions is a flex row with the
	   default align-items: stretch, so this naturally matches whatever
	   height the Upcoming Events button ends up being; aspect-ratio: 1
	   keeps it square by deriving width from that same stretched height,
	   rather than the two buttons having independently-set, possibly
	   mismatched sizes. Per request 2026-09-17. */
	aspect-ratio: 1;
	/* Padding around the 27px icon (same as every other icon button) gives
	   it its own ~47px square size. aspect-ratio + a stretched height alone
	   only worked in some layouts -- on the venue page the button
	   collapsed to a 27px-wide sliver, since a flex item's width doesn't
	   reliably derive from a height that was only stretched into place. */
	padding: var(--siva-tight-gap);
	background: var(--siva-pink);
	color: var(--siva-dark);
	transition: background-color 0.15s ease, color 0.15s ease;
}

.venue-panel__instagram:hover,
.venue-panel__instagram:focus-visible {
	background: var(--siva-dark);
	color: var(--siva-pink);
}

.venue-map-section__footer {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--siva-tight-gap);
	flex-wrap: wrap;
}

.venue-map-section__nav {
	display: flex;
	gap: var(--siva-tight-gap);
}

.venue-map-section__prev,
.venue-map-section__next {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.75rem;
	height: 2.75rem;
	background: var(--siva-dark);
	color: var(--siva-white);
	border: none;
	font-family: var(--siva-font-heading);
	letter-spacing: var(--siva-heading-letter-spacing);
	font-size: var(--siva-text-body);
	cursor: pointer;
	transition: background-color 0.15s ease, color 0.15s ease;
}

.venue-map-section__prev:hover,
.venue-map-section__prev:focus-visible,
.venue-map-section__next:hover,
.venue-map-section__next:focus-visible {
	background: var(--siva-white);
	color: var(--siva-dark);
}

.venue-map-section__save-list {
	background: var(--siva-dark);
	color: var(--siva-white);
	font-family: var(--siva-font-heading);
	letter-spacing: var(--siva-heading-letter-spacing);
	text-transform: uppercase;
	text-decoration: none;
	padding: var(--siva-tight-gap); /* was hardcoded, same value as --siva-tight-gap by coincidence -- fixed 2026-09-17 to actually reference the token so it gets the desktop-fluid scaling */
	transition: background-color 0.15s ease, color 0.15s ease;
}

.venue-map-section__save-list:hover,
.venue-map-section__save-list:focus-visible {
	background: var(--siva-white);
	color: var(--siva-dark);
}

/* Mobile only, per request 2026-09-18: the prev/next arrows move into
   the map's own bottom-right corner (overlapping it) instead of sitting
   in the footer row below the panel, and the footer -- now just the
   save-list link -- goes full-width and centered. The arrows are
   positioned relative to panel-col (bottom: 100%, i.e. flush with its
   own top edge, which is where the map ends) since they're not actually
   inside .venue-map in the DOM; sitting flush there means they extend
   upward from that edge into the map itself. The extra --siva-tight-gap
   in bottom's value below leaves the same breathing room under the
   arrows as panel-col already has above the save-list button. Desktop
   keeps the original footer row arrangement (untouched by this block). */
@media (max-width: 63.99rem) {
	.venue-map-section__panel-col {
		position: relative;
	}

	.venue-map-section__nav {
		position: absolute;
		bottom: calc(100% + var(--siva-tight-gap));
		right: 0;
	}

	.venue-map-section__footer {
		justify-content: center;
	}

	.venue-map-section__save-list {
		display: block;
		width: 100%;
		text-align: center;
	}
}

/* --- Venue page (single-venue.php) — Figma frame 3:557 ---
   A narrow centred column (Figma's is 780px; uses the existing 800px
   narrow-container token). The address and the events/Instagram buttons
   reuse the homepage panel's .venue-panel__* rules rather than restating
   them. */
.venue-page {
	width: min(100% - 2 * var(--siva-container-px), var(--siva-container-max-narrow));
	margin-inline: auto;
	padding-block: var(--siva-section-gap);
}

.venue-page__article {
	display: flex;
	flex-direction: column;
	gap: var(--siva-block-gap);
}

/* Photo mosaic: two rows. Top row is a small tile + a wide one (Figma:
   199px / 571px of 780px, i.e. about 26:74), bottom row two equal tiles.
   Rows are a fixed 5:1 (Figma: 780 x 156), so the tiles crop to fit rather
   than the photos deciding the height. With fewer than 4 photos the last
   row just has fewer tiles and they fill it. */
.venue-gallery {
	display: flex;
	flex-direction: column;
	gap: var(--siva-tight-gap);
}

.venue-gallery__row {
	display: flex;
	gap: var(--siva-tight-gap);
	aspect-ratio: 5 / 1;
	min-height: 0; /* a flex item's automatic minimum height is its content's, which would override the aspect ratio */
}

.venue-gallery__tile {
	position: relative;
	flex: 1 1 0;
	min-width: 0;
	padding: 0;
	border: none;
	background: none;
	cursor: pointer;
	overflow: hidden;
}

.venue-gallery__row:first-child > .venue-gallery__tile:first-child {
	flex-grow: 26;
}

.venue-gallery__row:first-child > .venue-gallery__tile:nth-child(2) {
	flex-grow: 74;
}

.venue-gallery__tile img {
	/* Absolutely positioned so the photo's own dimensions can't influence
	   the row's height -- as a normal-flow image, a tall photo in a
	   single-tile row stretched the row far past the 5:1 ratio. */
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: filter 0.15s ease;
}

.venue-gallery__tile:hover img,
.venue-gallery__tile:focus-visible img {
	filter: brightness(1.12);
}

.venue-gallery__tile:focus-visible {
	outline: 0.1875rem solid var(--siva-pink);
	outline-offset: 0.125rem;
}

/* No Figma mobile frame for this page. A 5:1 row would be only ~70px tall
   on a phone, so the rows get a much taller ratio and the small/wide split
   evens out (a 26% tile would be a ~90px sliver). */
@media (max-width: 47.99rem) {
	.venue-gallery__row {
		aspect-ratio: 2.2 / 1;
	}

	.venue-gallery__row:first-child > .venue-gallery__tile:first-child {
		flex-grow: 40;
	}

	.venue-gallery__row:first-child > .venue-gallery__tile:nth-child(2) {
		flex-grow: 60;
	}
}

.venue-page__heading {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.venue-page__description p + p,
.venue-page__description p + ul,
.venue-page__description ul + p {
	margin-top: 1em; /* paragraph spacing -- the global reset zeroes every p margin */
}

.venue-page__description a {
	color: inherit;
	text-decoration: underline;
}

/* --- Lightbox — venue panel photo gallery overflow --- */

.venue-lightbox {
	position: fixed;
	inset: 0;
	z-index: 100;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(16, 16, 16, 0.9);
}

.venue-lightbox[hidden] {
	display: none;
}

/* Two-column masonry, scrolling vertically. map.js pre-measures each
   photo's natural aspect ratio and greedily places it into whichever
   column currently has the smaller total height, so the two columns
   stay close to equal height and there's no gap left under a short
   image next to a tall one — while every image keeps its original,
   uncropped aspect ratio. (A plain 2-col grid can't do this: its rows
   share a fixed height, so a short image in a mixed-ratio row leaves
   visible empty space below it. Real CSS multi-column can't either:
   it fills column 1 top-to-bottom before starting column 2, which
   reads in the wrong order for a photo grid.) */
.venue-lightbox__images {
	display: flex;
	gap: var(--siva-tight-gap);
	width: min(100% - 2 * var(--siva-container-px), var(--siva-container-max));
	min-width: 0; /* flex items default to a content-based min-width, which fights the width above */
	max-height: 90vh;
	overflow: hidden auto; /* vertical scroll only */
	/* Small, symmetric padding -- NOT --siva-container-px (the page's full
	   gutter token, up to ~132px). That's sized for page-edge margins, not
	   a modal's inner padding: used here it pushed the top/left in by that
	   much while the right stayed tight for the scrollbar, so the images
	   themselves rendered off-centre within the box. */
	padding: var(--siva-container-py) var(--siva-tight-gap);

	/* Custom scrollbar to match the brand instead of the OS default. */
	scrollbar-width: thin; /* Firefox */
	scrollbar-color: var(--siva-pink) transparent; /* Firefox */
}

.venue-lightbox__images::-webkit-scrollbar {
	width: 0.5rem;
}

.venue-lightbox__images::-webkit-scrollbar-track {
	background: transparent;
}

.venue-lightbox__images::-webkit-scrollbar-thumb {
	background-color: var(--siva-pink);
	border-radius: 999px;
}

/* The photo area is focusable (tabindex=0 in the template) so keyboard
   users can scroll it with the arrow keys -- it needs a visible focus ring,
   drawn inside the box so it isn't clipped. */
.venue-lightbox__images:focus-visible {
	outline: 0.1875rem solid var(--siva-pink);
	outline-offset: -0.1875rem;
}

.venue-lightbox__col {
	flex: 1 1 0;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: var(--siva-tight-gap);
}

.venue-lightbox__images img {
	display: block;
	width: 100%;
	height: auto; /* natural aspect ratio, not forced-square */
}

/* Screen-reader-only utility, used by the skip link and the venue list fallback */
.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: -6.25rem;
	left: 0;
	background: #000;
	color: #fff;
	padding: 0.75rem 1rem;
	z-index: 1000;
}

.skip-link:focus {
	position: fixed;
	top: 0;
	left: 0;
	width: auto;
	height: auto;
	clip: auto;
	white-space: normal;
}

/* --- Footer — same content everywhere (see footer.php), home page gets a
   styling-only modifier class --- */

.site-footer {
	/* Now matches the same 1200px container as the header/map section, per
	   request 2026-09-16 (was a narrower 800px cap with its own wider
	   gutter — --siva-container-max-narrow / --siva-footer-px are unused
	   now but left defined in :root in case a narrower container is
	   wanted somewhere else later). No distinct background here to worry
	   about creating a seam against — it shares body's background. */
	width: min(100% - 2 * var(--siva-container-px), var(--siva-container-max));
	margin-inline: auto;
	padding-block: var(--siva-section-gap) var(--siva-container-py);
}

.site-footer__about {
	display: flex;
	flex-direction: column;
	align-items: flex-start; /* Figma's "items-start" — without this, flex's default stretch makes children fill the full width */
	/* No gap — Figma's About-heading-to-paragraph block has none, headings
	   sit flush against their content (see the h1-h6 margin reset above). */
}

.site-footer--home {
	/* TODO: homepage-specific footer styling, once Figma defines the difference */
}

.site-footer__columns {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--siva-block-gap);
	margin-top: var(--siva-block-gap); /* Figma nests About/columns/supported-by in one flex column with a flat 20px gap throughout, not the larger section gap */
}

.site-footer__column {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	width: 100%; /* without an explicit width, this shrink-wraps to its content, which defeats the email button's max-width: 100% below (nothing definite for the percentage to resolve against) and let it force the whole page wider than the mobile viewport */
	/* Was "no gap" (reasoning: the button's own padding gives it breathing
	   room from the heading) -- but padding is INSIDE the button, it
	   doesn't push the button's own box away from the heading above it,
	   so that left these flush while .site-footer__supported-by (which
	   got an explicit gap for the same button-vs-bare-image reason) didn't.
	   Matched to it here. Per request 2026-09-18. */
	gap: 0.5rem;
}

.site-footer__button {
	display: inline-block;
	max-width: 100%; /* the email address button's text is long enough to otherwise force this (and the whole page) wider than the mobile viewport -- found 2026-09-18 */
	overflow-wrap: break-word;
	background: var(--siva-pink);
	color: var(--siva-dark);
	font-family: var(--siva-font-heading);
	letter-spacing: var(--siva-heading-letter-spacing);
	text-transform: uppercase;
	text-decoration: none;
	padding: var(--siva-tight-gap); /* was hardcoded, same value as --siva-tight-gap by coincidence -- fixed 2026-09-17 to actually reference the token so it gets the desktop-fluid scaling */
	transition: background-color 0.15s ease, color 0.15s ease;
}

.site-footer__button:hover,
.site-footer__button:focus-visible {
	background: var(--siva-dark);
	color: var(--siva-pink);
}

.site-footer__icon-link {
	display: inline-flex;
	align-items: center;
	gap: var(--siva-tight-gap);
	transition: background-color 0.15s ease, color 0.15s ease;
	justify-content: center;
	background: var(--siva-pink);
	color: var(--siva-dark); /* drives the icon's color via currentColor, see .icon */
	text-decoration: none;
	padding: var(--siva-tight-gap);
	font-family: var(--siva-font-heading);
	letter-spacing: var(--siva-heading-letter-spacing);
	text-transform: uppercase;
}

.site-footer__icon-link:hover,
.site-footer__icon-link:focus-visible {
	background: var(--siva-dark);
	color: var(--siva-pink);
}

.site-footer__supported-by {
	margin-top: var(--siva-block-gap);
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.5rem; /* Figma's own data has no gap here (see .site-footer__about), but a bare image sitting flush under the heading read as cramped compared to "Join us" etc., whose button has its own padding creating that breathing room — added per request 2026-09-16 */
}

.site-footer__supported-by-list {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: var(--siva-tight-gap); /* per request 2026-09-18: multiple supporters sit side by side, not stacked */
}

.site-footer__supported-by img,
.site-footer__supported-by-fallback {
	display: inline-block;
	max-width: 9.375rem;
}

/* Above the tablet breakpoint, columns sit side by side with the larger
   section-gap between them (Figma: 50px desktop vs 20px mobile — the two
   breakpoints genuinely use different gap tokens here, not just a layout
   direction change). TODO: confirm real breakpoint against Figma. */
@media (min-width: 48rem) {
	.site-footer__columns {
		flex-direction: row;
		flex-wrap: wrap; /* three columns don't all fit on one row at tablet widths -- the email button pushed the whole page sideways. Wrap instead. Found 2026-09-21 */
		gap: var(--siva-block-gap) var(--siva-section-gap);
	}

	/* width: 100% (base rule) is right when columns are stacked, but in a
	   row it makes every column demand the full width at once. */
	.site-footer__column {
		width: auto;
		max-width: 100%;
	}
}

.venue-lightbox__close {
	position: absolute;
	top: 1rem;
	right: 1rem;
	background: none;
	border: none;
	color: var(--siva-white);
	font-size: 2rem;
	line-height: 1;
	cursor: pointer;
	transition: color 0.15s ease;
	z-index: 1;
}

@media (max-width: 47.99rem) {
	.venue-lightbox__close {
		font-size: 2.5rem; /* +25% per request 2026-09-18, mobile only */
	}
}

.venue-lightbox__close:hover,
.venue-lightbox__close:focus-visible {
	color: var(--siva-pink);
}
