/*
Theme Name: Marine Studios
Theme URI: https://marinestudios.co.uk
Author: Pressing Space
Author URI: https://pressingspace.com
Description: Block theme for Marine Studios, Margate — a co-working space for writers and creatives. Risograph spot-colour palette drawn from the studio's own logo, Jost and Literata self-hosted, and a 70s film grade on every photograph by default.
Version: 0.32.3
Requires at least: 6.6
Tested up to: 7.1
Requires PHP: 8.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: marinestudios
Update URI: false
Tags: full-site-editing, block-patterns, block-styles, custom-menu, editor-style, featured-images, one-column, wide-blocks
*/

/*
 * Design tokens live in theme.json, not here. The aliases below only
 * point short names at its presets; everything after them is component
 * CSS that theme.json has no vocabulary for — structural shapes, the
 * film-grade layers, the masthead.
 *
 * Two rules for this file, both learned the hard way in the prototype:
 * 1. Resets go in :where() so they carry ZERO specificity. A plain
 *    `.foo p { margin: 0 }` is (0,1,1) and silently outranks any
 *    component class at (0,1,0). Vertical rhythm dies quietly.
 * 2. Never write a bare element selector inside a class
 *    (`.card img { … }`) for anything a component might need to own.
 *    Prefer `.card > img` plus an explicit :not() escape hatch.
 */

/* ---------------------------------------------------------------
   TOKEN ALIASES
   The design layer below is written against short token names; these
   map them onto the presets theme.json generates, so theme.json stays
   the single source of truth for values. They live here, not in
   theme.json's styles.css: CSS saved in the Site Editor (Additional
   CSS) replaces that field outright, and every alias would go with it.
   --------------------------------------------------------------- */
:root {
	--ink: var(--wp--preset--color--ink);
	--paper: var(--wp--preset--color--paper);
	--paper-2: var(--wp--preset--color--paper-alt);
	--blue: var(--wp--preset--color--blue);
	--red: var(--wp--preset--color--red);
	--yellow: var(--wp--preset--color--yellow);
	--orange: var(--wp--preset--color--orange);
	--teal: var(--wp--preset--color--teal);
	--violet: var(--wp--preset--color--violet);
	--mark: var(--wp--preset--color--red);
	--sp-1: var(--wp--preset--spacing--10);
	--sp-2: var(--wp--preset--spacing--20);
	--sp-3: var(--wp--preset--spacing--30);
	--sp-4: var(--wp--preset--spacing--40);
	--sp-5: var(--wp--preset--spacing--50);
	--sp-6: var(--wp--preset--spacing--60);
	--measure: var(--wp--custom--measure);
	--gutter: var(--wp--custom--gutter);
	--wide: var(--wp--style--global--wide-size);
	--shadow-col: var(--wp--custom--shadow--color);
	--shadow-off: var(--wp--custom--shadow--offset);
	--film: var(--wp--custom--film--strength);
	--film-desat: calc(1 - .28 * var(--film));
	--film-fade: calc(1 - .16 * var(--film));
	--film-bright: calc(1 + .08 * var(--film));
	--film-tone: calc(.26 * var(--film));
	--film-hue: calc(-6deg * var(--film));
	--film-lift: calc(.20 * var(--film));
	--film-warm: calc(.38 * var(--film));
	--film-bloom: calc(.42 * var(--film));
	--film-grain: calc(.20 * var(--film));
	--film-vignette: calc(.58 * var(--film));
	/* The keyboard focus ring: ink on paper and yellow, paper on the dark
	   grounds (FOCUS RINGS, below). theme.json draws it on links and
	   buttons. */
	--focus: var(--ink);
}

/* Buttons press into their shadow rather than sliding it. */
.wp-element-button,
.wp-block-button__link { transition: transform .12s, box-shadow .12s; }
.wp-element-button:hover,
.wp-block-button__link:hover {
	transform: translate(2px, 2px);
	box-shadow: calc(var(--shadow-off) - 2px) calc(var(--shadow-off) - 2px) 0 var(--shadow-col);
}
.wp-element-button:active,
.wp-block-button__link:active {
	transform: translate(var(--shadow-off), var(--shadow-off));
	box-shadow: 0 0 0 var(--shadow-col);
}

/* Accent ink. Each section variation carries its own mark, so the page
   accumulates the full spot-colour set on the way down; the eyebrow, the
   halfrule and the tick-list marker all read --mark by inheritance, so the
   variation must be an ancestor and never a sibling. */
.is-style-section-blue { --mark: var(--wp--preset--color--yellow); }
.is-style-section-violet { --mark: var(--wp--preset--color--yellow); }
.is-style-section-newsprint { --mark: var(--wp--preset--color--blue); }
.is-style-section-red { --mark: var(--wp--preset--color--yellow); }
.is-style-section-yellow { --mark: var(--wp--preset--color--ink); }

/* ---------------------------------------------------------------
   THE WORDMARK
   Real vector artwork from assets/logo/, inlined by the header
   pattern. Letters use currentColor so the mark inverts on dark
   sections; only the two substituted glyphs are recoloured.
   Do NOT add a `.logo path { fill: … }` rule — CSS outranks the
   SVG's own fill attributes and would flatten the triangle and disc.
   --------------------------------------------------------------- */
.logo { display: block; height: auto; }
:root { --logo-tri: var(--yellow); --logo-disc: var(--red); }

/* ---------------------------------------------------------------
   70s FILM GRADE — `is-style-film-70s`
   A block style variation in theme.json for core/image and
   core/cover only: the grade needs a direct-child <img>.
   Five layers, in the order a photograph actually degrades. The base
   grade sits on the <img> itself, so an image is still graded with
   JavaScript disabled; the four overlay layers are injected by
   assets/js/film.js and are progressive enhancement.
   Bloom and vignette are sized in cqw so they scale with the image —
   a blur calibrated for a full-bleed hero is a smear on a thumbnail.
   Grain stays in px: real grain belongs to the stock, not the print.
   --------------------------------------------------------------- */
.is-style-film-70s {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	container-type: inline-size;
}

/* :not(.film__bloom) is required, not tidiness — the bloom is also a
   direct child <img>, so a bare `> img` would overwrite its blur with
   the base grade and the halation layer would silently vanish. */
.is-style-film-70s > img:not(.film__bloom),
.is-style-film-70s > picture > img {
	filter:
		saturate(var(--film-desat))
		contrast(var(--film-fade))
		brightness(var(--film-bright))
		sepia(var(--film-tone))
		hue-rotate(var(--film-hue));
}

/* The grade is on by default (functions.php, film_by_default()), which adds
   the class when the page renders. The editor canvas never sees that
   class, so it gets the base grade here, on the same terms: every image
   but an Original. */
.editor-styles-wrapper .wp-block-image:not(.is-style-original) img {
	filter:
		saturate(var(--film-desat))
		contrast(var(--film-fade))
		brightness(var(--film-bright))
		sepia(var(--film-tone))
		hue-rotate(var(--film-hue));
}

.is-style-film-70s > img.film__bloom {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	filter: blur(1.7cqw) brightness(1.32) saturate(1.45) sepia(0.35);
	mix-blend-mode: screen;
	opacity: var(--film-bloom);
}

.film__wash,
.film__grain,
.film__vignette {
	position: absolute;
	inset: 0;
	pointer-events: none;
}

/* LIFTED BLACKS — the actual 70s signature. `lighten` clamps the
   shadows to a warm brown floor; without it this reads as sepia. */
.film__wash::before {
	content: "";
	position: absolute;
	inset: 0;
	background: #4a3520;
	mix-blend-mode: lighten;
	opacity: var(--film-lift);
}

/* Warm cast over the midtones, leaving highlights alone. */
.film__wash::after {
	content: "";
	position: absolute;
	inset: 0;
	background: #ff8a3d;
	mix-blend-mode: soft-light;
	opacity: var(--film-warm);
}

.film__grain {
	z-index: 2;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
	background-size: 180px 180px;
	mix-blend-mode: overlay;
	opacity: var(--film-grain);
}

/* Vignette via an inset shadow, not a radial-gradient. There are no
   gradients anywhere in this theme — the riso look depends on it. */
.film__vignette {
	z-index: 3;
	box-shadow: inset 0 0 9cqw rgba(58, 34, 14, var(--film-vignette));
}

/* ---------------------------------------------------------------
   FOOTER BOTTOM BAR
   `1fr auto 1fr` centres the middle item against the page, not its
   neighbours — flex would put the copyright visibly off-centre.
   --------------------------------------------------------------- */
.foot__bar {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: var(--sp-2) var(--sp-4);
	padding-top: var(--sp-3);
	border-top: 1px solid var(--wp--custom--rule--on-ink);
}

/* The footer's column headings: small yellow tracked caps on the ink.
   A rule here rather than a block style, which would be offered on every
   heading, where yellow on paper is unreadable. */
.foot .wp-block-heading {
	color: var(--yellow);
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.2em;
}
.foot__bar > :nth-child(1) { justify-self: start; }
.foot__bar > :nth-child(2) { justify-self: center; font-variant-numeric: tabular-nums; }
.foot__bar > :nth-child(3) { justify-self: end; display: flex; gap: var(--sp-3); }
/* No legal page is published yet, so the legal links paragraph is empty.
   Hidden then, or the stacked mobile bar shows a blank row; the copyright
   still sits in the middle column on wider screens. */
.foot__bar > .legal-links:empty { display: none; }

@media (max-width: 44rem) {
	.foot__bar {
		grid-template-columns: 1fr;
		justify-items: center;
		text-align: center;
	}
	.foot__bar > :nth-child(1),
	.foot__bar > :nth-child(2),
	.foot__bar > :nth-child(3) { justify-self: center; }
}

/* Masthead wordmark. Height comes from the logo plus a spacing step,
   so the bar is never a fixed number the logo sits flush against. */
.wordmark {
	display: block;
	color: var(--ink);
	width: clamp(5.5rem, 9vw, 6.5rem);
	padding-right: var(--sp-3);
}

/* ===============================================================
   MASTHEAD AND NAVIGATION
   Matched to the approved prototype. core/navigation ships almost
   unstyled, so all of this is the theme's, mapped onto core's class
   names rather than the prototype's hand-written .nav__* ones.
   =============================================================== */
/* Docked to the top at every breakpoint.
   `position: sticky` on `.masthead` alone does nothing: WordPress wraps a
   template part in its own `<header class="wp-block-template-part">`, that
   wrapper is exactly as tall as the masthead inside it, and a sticky
   element can only travel within its parent's box — so it has no room and
   scrolls straight off. The sticky has to sit on the wrapper. The rule on
   `.masthead` is kept as the fallback for browsers without :has(), and has
   to be a rule of its own: a selector list containing :has() is dropped
   whole by a browser that cannot parse it. */
.masthead {
	position: sticky;
	top: 0;
	z-index: 60;
}
.wp-block-template-part:has(> .masthead) {
	position: sticky;
	top: 0;
	z-index: 60;
}
/* Signed in, the admin bar is fixed across the top of the window, so the
   masthead docks below it rather than under it. Core sets the bar's height
   on <html> only while the bar shows. Below 601px the bar scrolls away with
   the page, so the masthead goes back to the top edge. */
.admin-bar .wp-block-template-part:has(> .masthead) { top: var(--wp-admin--admin-bar--height, 0px); }
@media (max-width: 600px) {
	.admin-bar .wp-block-template-part:has(> .masthead) { top: 0; }
}
/* A link to an anchor (/meeting-room-hot-desk-hire/#marine-sands) lands
   below the sticky masthead, not under it, and below the admin bar when it
   shows. html:root outranks the admin bar's own `html` rule, which would
   otherwise reset this to the bar's height alone. */
html:root { scroll-padding-top: calc(6rem + var(--wp-admin--admin-bar--height, 0px)); }

.wp-block-navigation { gap: 0.25rem; }

/* Jost, not the body serif, and a hairline that only shows on hover —
   the prototype's nav reads as quiet until you reach for it. */
.wp-block-navigation .wp-block-navigation-item__content {
	font-family: var(--wp--preset--font-family--jost);
	font-size: 0.95rem;
	font-weight: 500;
	letter-spacing: 0.02em;
	color: var(--ink);
	text-decoration: none;
	padding: 0.45rem 0.7rem;
	border-bottom: 3px solid transparent;
}
.wp-block-navigation .wp-block-navigation-item__content:hover,
.wp-block-navigation .wp-block-navigation-item__content:focus-visible,
.wp-block-navigation .has-child[data-wp-context]:hover > .wp-block-navigation-item__content {
	border-bottom-color: var(--red);
	background: none;
}
/* The section you are in keeps that underline on its top-level item: it
   says where you are, as the hero's eyebrow used to. The section is the
   page hero's colour (docs/pages.md): Spaces blue, About red, Events
   violet, and every single event; Contact yellow. */
body:has(.page-hero.has-spot-blue) .wp-block-navigation__container > li > .wp-block-navigation-item__content[href$="/our-spaces/"],
body:has(.page-hero.has-spot-red) .wp-block-navigation__container > li > .wp-block-navigation-item__content[href$="/about/"],
body:has(:is(.page-hero.has-spot-violet, .event-hero)) .wp-block-navigation__container > li > .wp-block-navigation-item__content[href$="/events/"],
body:has(.page-hero.has-spot-yellow) .wp-block-navigation__container > li > .wp-block-navigation-item__content[href$="/contact/"] {
	border-bottom-color: var(--red);
}

/* The dropdown is a riso card: flat paper, hard rule, hard shadow.
   :not(.has-background) matches core's own selector, whose white ground
   otherwise wins on specificity. */
.wp-block-navigation:not(.has-background) .wp-block-navigation__submenu-container {
	min-width: 15rem;
	background: var(--paper);
	border: var(--wp--custom--rule--width) solid var(--ink);
	box-shadow: 6px 6px 0 var(--shadow-col);
	padding: 0.4rem;
}
.wp-block-navigation .wp-block-navigation__submenu-container
	.wp-block-navigation-item__content {
	font-size: 0.95rem;
	padding: 0.55rem 0.7rem;
	border-bottom: 0;
	width: 100%;
}
.wp-block-navigation .wp-block-navigation__submenu-container
	.wp-block-navigation-item__content:hover {
	background: var(--yellow);
	color: var(--ink);
}

/* A menu item given the class `nav-cta` becomes the booking button.
   Added as a custom menu item so the client can retarget or retitle it
   without a theme change. The prototype's is `.btn.btn--red.btn--sm`:
   red ground, paper text, 4px shadow offset. */
/* The masthead's Bookings is the Secondary button (styles/secondary.json),
   drawn on a menu item: red, paper text, the ink border and hard shadow. */
.wp-block-navigation .nav-cta > .wp-block-navigation-item__content {
	background: var(--red);
	color: var(--paper);
	border: var(--wp--custom--rule--width) solid var(--ink);
	box-shadow: var(--wp--preset--shadow--hard-sm);
	font-weight: 600;
	letter-spacing: 0.02em;
	padding: 0.6rem 1rem;
	margin-left: var(--sp-2);
	border-bottom-color: var(--ink);
}
.wp-block-navigation .nav-cta > .wp-block-navigation-item__content:hover {
	transform: translate(2px, 2px);
	box-shadow: 2px 2px 0 var(--shadow-col);
	border-bottom-color: var(--ink);
	background: var(--red);
	color: var(--paper);
}

/* ===============================================================
   GALLERY — `.gallery` on a core/gallery block
   From the prototype: the photographs run untinted and the ink is in
   the FRAME, not over the image. A multiply tint over a saturated ink
   crushed these to mud — the print reference stops where legibility
   starts. The film grade still applies; that is a filter, not a tint.

   The frame colour cycles every four so the row reads as a set rather
   than four unrelated pictures. `4n` rather than the prototype's plain
   nth-child, because the live gallery has eight images and the
   prototype only showed four.
   =============================================================== */
.gallery > figure {
	margin: 0;
	border: 5px solid var(--ink);
	overflow: hidden;
}
/* theme.json borders every core/image <img> in ink; inside the coloured
   frame that is a second, inner frame. */
.gallery > figure > img,
.gallery > figure > a > img {
	border: 0;
	width: 100%;
	aspect-ratio: 1;
	object-fit: cover;
	display: block;
}
.gallery > figure:nth-child(4n + 1) { border-color: var(--red); }
.gallery > figure:nth-child(4n + 2) { border-color: var(--blue); }
.gallery > figure:nth-child(4n + 3) { border-color: var(--teal); }
.gallery > figure:nth-child(4n + 4) { border-color: var(--violet); }

/* Six photographs run in one row on a wide screen, like the prototype's
   four. Core keeps columns-6 six across down to 600px, where the frames
   are too small to read, so the tablet range drops to three. Core's rule
   carries an ID through :not(#individual-image); this one has to as well. */
@media (min-width: 600px) and (max-width: 52rem) {
	.wp-block-gallery.has-nested-images.gallery.columns-6 figure.wp-block-image:not(#individual-image) {
		width: calc(33.333% - var(--wp--style--unstable-gallery-gap, 16px) * 0.66667);
	}
}

/* ===============================================================
   FUNDER ROW
   The marks are credits, not images: one row, one height, never
   scaled to the column. `.is-style-film-70s` must never reach them —
   recolouring a funder's mark breaks their brand terms.
   =============================================================== */
.wp-block-group.funders {
	align-items: center;
	gap: clamp(1.25rem, 4vw, 3rem);
}
/* theme.json frames every image in ink; a funder's mark takes no frame. */
.funders .wp-block-image,
.funders .wp-block-image img { border: 0; margin: 0; }
.funders img { height: 2.4rem; width: auto; }
/* A credit line, in ink: not the red of a section eyebrow. */
.funders .eyebrow { color: var(--ink); letter-spacing: 0.18em; }

/* ===============================================================
   CONTENT ADOPTION
   What survives of the Twenty Twenty-One inheritance. The rebuild
   retires core/media-text — only a direct-child <img> can carry the
   film grade — so its adoption rules went with it. Inline hex and
   line-height need the CONTENT to change: normalise-block-markup.php.
   =============================================================== */

/* --- cover: flat ink, never a dim overlay ---------------------- */
.wp-block-cover .wp-block-cover__background { opacity: 1; }
.wp-block-cover :where(h1, h2, h3, h4, h5, h6) { color: inherit; }

/* --- dead utilities from the removed theme: `tw-mb-3` and its ~100
   siblings are defined nowhere, deliberately. Rhythm is blockGap. --- */

/* ===============================================================
   LINE BREAKS — no orphans in headings and lead-ins
   Headings, hero titles included, balance their lines, so a title
   never ends on one short word. Lead-ins (the large paragraphs: the
   lead under a hero, home's card) wrap "pretty", which keeps a lone
   word off the last line. Both are progressive: a browser without
   them wraps as before.
   =============================================================== */
:where(h1, h2, h3, h4, h5, h6) { text-wrap: balance; }
:where(p.has-large-font-size) { text-wrap: pretty; }

/* ===============================================================
   DESIGN COMPONENTS
   Class hooks applied to CORE blocks via the editor's "Additional
   CSS class" field. No custom blocks — every one is a core block
   wearing a theme class, so the content stays portable and editable.
   =============================================================== */

/* --- eyebrow: small tracked label above a heading -------------- */
.eyebrow {
	font-family: var(--wp--preset--font-family--jost);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.22em;
	color: var(--mark, var(--red));
}

/* --- half-disc rule: the logo's O, used as a section divider ---
   Now a core/separator style variation: a real <hr>, with no inside
   to type into. `border: 0` clears core's border-top and theme.json's
   own; `display: flex` lays the two pseudo-elements out; `color:
   inherit` beats theme.json's ink on separators, without which the
   hairline goes dark on blue and violet. Width/margin and the :not()s
   only bite if wp-block-styles is added (theme.css:211). `.halfrule`
   stays an alias for one release, for markup already in the DB. --- */
.halfrule,
.wp-block-details > summary,
.wp-block-separator.is-style-halfrule:not(.is-style-wide):not(.is-style-dots) {
	display: flex;
	align-items: center;
	gap: 0.9rem;
	border: 0;
	color: inherit;
	width: auto;
	margin-inline: 0;
}
.halfrule::before,
.wp-block-separator.is-style-halfrule::before,
.wp-block-details > summary::before {
	content: "";
	flex: 0 0 auto;
	width: 1.6rem;
	height: 0.8rem;
	background: var(--mark, var(--red));
	border-radius: 1.6rem 1.6rem 0 0;
}
.halfrule::after,
.wp-block-separator.is-style-halfrule::after {
	content: "";
	flex: 1 1 auto;
	height: var(--wp--custom--rule--width);
	background: currentColor;
}

/* --- core/details: theme.json owns the box (a rule on top, not a heavy
   box); here the summary's size and caps, and the summary joins the
   half-disc rule above — the flex there also kills the UA marker, and
   the disc flips when the answer is open. --- */
.wp-block-details > summary {
	cursor: pointer;
	list-style: none;
	font-family: var(--wp--preset--font-family--jost);
	font-weight: 600;
	font-size: 0.9rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}
.wp-block-details[open] > summary { margin-bottom: var(--wp--preset--spacing--20); }
.wp-block-details > summary::-webkit-details-marker { display: none; }
.wp-block-details[open] > summary::before { transform: rotate(180deg); }

/* --- triangle list marker: the logo's A ------------------------ */
.tick-list { list-style: none; padding-left: 0; }
.tick-list li {
	position: relative;
	padding-left: 1.9rem;
	margin-bottom: var(--sp-2);
}
.tick-list li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.6em;
	width: 0;
	height: 0;
	border-left: 0.44rem solid transparent;
	border-right: 0.44rem solid transparent;
	border-bottom: 0.76rem solid var(--mark, var(--red));
}

/* The --mark assignments are at the top of this file. Small yellow type
   is 3.4:1 on red, so a red section's eyebrow is paper; its half-disc and
   tick markers stay yellow (--mark). */
.is-style-section-red .eyebrow { color: var(--paper); }

/* --- card: a core/group, in a grid or a column ----------------- */
.card {
	background: var(--paper);
	border: var(--wp--custom--rule--width) solid var(--ink);
	box-shadow: var(--wp--preset--shadow--hard-lg);
	height: 100%;
	transition: transform 0.14s, box-shadow 0.14s;
}
/* Only a card you can click may move under the pointer. */
.card:has(a):hover {
	transform: translate(3px, 3px);
	box-shadow: var(--wp--preset--shadow--hard);
}
/* Enforcement, not decoration. The pattern zeroes the image border and
   the group's block gap in attributes; these rules stop an author who
   drags in a replacement image from bringing the 3px border back. */
.card > .wp-block-image, .card > figure { border-width: 0; margin: 0; }
.card > * { --wp--style--block-gap: 0; }
.card { display: flex; flex-direction: column; }
/* The card is a constrained group too, so core gives every child auto side
   margins with !important. In a flex column those shrink the picture's
   figure to zero width and the photograph disappears. */
.card.is-layout-constrained > * {
	margin-left: 0 !important;
	margin-right: 0 !important;
}

/* theme.json borders the <img>, not the figure, so the rule above never
   reached it and every card photo sat in a second frame. One shape for
   every photo, so a row of cards lines up however each was taken, and a
   single rule under it: the prototype's `.card__media`. */
.card > .wp-block-image img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border: 0;
	border-bottom: var(--wp--custom--rule--width) solid var(--ink);
}

/* The body fills the card and stacks on one small gap, so the link line
   can sit on the bottom edge of every card in the row. Core centres the
   children of a constrained group with !important; in a flex column that
   shrink-wraps them to the middle, hence the answer in kind. */
.card > .wp-block-group {
	flex: 1;
	display: flex;
	flex-direction: column;
	gap: 0.55rem;
}
.card > .wp-block-group.is-layout-constrained > * {
	margin: 0 !important;
}
.card > .wp-block-group > .price {
	align-self: flex-start;
	font-size: var(--wp--preset--font-size--large);
}
.card > .wp-block-group.is-layout-constrained > .card__link {
	margin-top: auto !important;
	padding-top: 0.9rem;
}
.card__link a {
	font-family: var(--wp--preset--font-family--jost);
	font-size: 0.9rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 0.25em;
	color: var(--blue);
}
.card__link a:hover {
	color: var(--blue);
	background: none;
	text-decoration: underline;
	text-underline-offset: 0.25em;
}

/* --- price chip, unscoped from .card: the meeting-room string runs
   to three clauses and has to wrap inside the chip. -------------- */
.price {
	display: inline-block;
	font-family: var(--wp--preset--font-family--jost);
	font-weight: 600;
	background: var(--yellow);
	color: var(--ink);
	padding: 0.15rem 0.5rem;
	white-space: normal;
}

/* --- hero ------------------------------------------------------ */
/* The hero owns its layout. Core clamps every non-aligned child of an
   .is-layout-constrained group to contentSize — which shrinks the
   inset:0 .hero__stage photograph to the contentSize measure and centres
   it, and beats .hero__block's `width` because max-width wins. Done in
   CSS, not the block's layout attribute: that is one editor click from
   being reset, and it fails silently. (0,2,0) clears core's (0,1,0). */
.hero.is-layout-constrained > * { max-width: none; }

/* The card sits LEFT, not centred. The prototype gets that from a
   `.hero__inner` flex wrapper with align-items:flex-start; there is no
   such wrapper in the block markup, and core's constrained layout puts
   `margin-inline: auto !important` on every child, so the !important
   has to be answered in kind — at (0,3,0) against core's (0,1,0). */
.hero.is-layout-constrained > .hero__block {
	margin-left: calc((100% - min(100%, var(--wp--style--global--content-size))) / 2) !important;
	margin-right: auto !important;
	width: min(100%, var(--hero-card));
}

/* The standfirst runs the width of the card. It used to hold a 34ch
   measure, from when the card spanned half the page; now the card is sized
   to the wordmark, that measure left a one-word last line. */
.hero__block .has-large-font-size { max-width: none; }

/* The hero takes the shape of the crop it shows at each breakpoint (the
   <picture> sources in inc/image-sizes.php): 2:3 on phones, square on
   tablets, 16:9 from 1024px, never taller than 88% of the viewport (from
   600px, short enough for the card to fit the first screen; 50rem on
   desktop), so the crop an editor sets is the crop visitors see.
   A min-height, not aspect-ratio: with aspect-ratio, a max-height also caps
   the width, and the hero stopped short of the right edge. As a minimum the
   hero still grows if the card needs more room. */
.hero {
	position: relative;
	isolation: isolate;
	display: flex;
	align-items: flex-end;
	min-height: min(150vw, 88vh);
	overflow: hidden;
	background: var(--paper-2);
	/* Every hero closes on the same rule as the masthead above it. */
	border-bottom: var(--wp--custom--rule--width) solid var(--ink);
}
/* From 600px the card hangs over the photo's bottom edge by
   --hero-overhang, and the whole card has to fit the first screen: the
   photo stops short of the window's height by the masthead (5rem), the
   overhang, a margin and, signed in, the admin bar. */
@media (min-width: 600px) {
	.hero { min-height: min(100vw, 100svh - 6.5rem - var(--hero-overhang) - var(--wp-admin--admin-bar--height, 0px)); }
}
@media (min-width: 1024px) {
	.hero { min-height: min(56.25vw, 100svh - 6.5rem - var(--hero-overhang) - var(--wp-admin--admin-bar--height, 0px), 50rem); }
}
/* Laid out as if the <picture> were not there: the <img> is still the child
   the gallery and the slide position and size. */
.hero picture { display: contents; }
.hero__stage { position: absolute; inset: 0; z-index: 0; }
.hero__stage .hero__slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity 0.9s ease;
}
.hero__stage .hero__slide.is-current { opacity: 1; }
.hero__slide img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}
@media (prefers-reduced-motion: reduce) {
	.hero__stage .hero__slide { transition: none; }
}
/* The source gallery stays in the content for the editor and for
   no-JS readers; the carousel hides it once it has the images. */
.hero__source[hidden] { display: none; }

/* The card is sized from the wordmark, not the page: on a phone the wordmark
   fills the card, and from tablet up it stops at --hero-logo and the card
   stops with it, keeping the phone's proportions instead of a wordmark
   stretched across a wide screen. 31rem is the width at which the eyebrow
   line, at its largest size, still sits on one line under it. */
.hero__block {
	--hero-logo: 31rem;
	/* Spacing presets, not a one-off clamp: step 3 on a phone, step 4 from
	   600px, where the card has room. */
	--hero-pad: var(--wp--preset--spacing--30);
	--hero-card: calc(var(--hero-logo) + 2 * var(--hero-pad) + 8px);
	position: relative;
	z-index: 2;
	background: var(--paper);
	border: 4px solid var(--ink);
	box-shadow: var(--wp--preset--shadow--hard-xl);
	padding: var(--hero-pad);
	width: min(100%, var(--hero-card));
}
@media (min-width: 600px) {
	.hero__block { --hero-pad: var(--wp--preset--spacing--40); }
}
.hero__block .wordmark,
.hero__block .logo { width: min(100%, var(--hero-logo)); }
/* On home the wordmark IS the h1 (patterns/wordmark-h1.php). Bottom margin
   only: `margin: 0` also cancelled the block gap above it and left the
   eyebrow touching the wordmark. */
.hero__title { margin-bottom: 0; }

/* The block is a constrained group too, so core centres every child. The
   34ch standfirst then sat 150px in from the wordmark's left edge. */
.hero__block.is-layout-constrained > * { margin-left: 0 !important; }

/* The lead under an inner page's hero: one step below the photograph. A
   bold opening phrase in it ("Make this your office.") is set in Jost, as a
   lead-in to the sentence. */
:is(.wp-block-post-content, .event-main) > :is(.hero, .page-hero) + .is-style-band { padding-top: var(--sp-5); }
:is(.wp-block-post-content, .event-main) > :is(.hero, .page-hero) + .is-style-band > .has-large-font-size strong {
	font-family: var(--wp--preset--font-family--jost);
	font-weight: 700;
	letter-spacing: 0.01em;
}

/* HOME: the wordmark card has more presence without covering more of the
   carousel. From 600px the wordmark is larger and the card hangs over the
   bottom edge of the photograph by --hero-overhang; the section after the
   hero moves down by the same amount, so nothing sits under the card. On a
   phone the card stays inside the photo. Keyed on the wordmark heading
   (.hero__title), which only home's hero has. */
@media (min-width: 600px) {
	/* On :root, not the hero: the section after the hero reads it too, and a
	   sibling does not inherit custom properties. */
	:root { --hero-overhang: clamp(1.25rem, 2.5vw, 2.25rem); }
	.hero:has(> .hero__block .hero__title) { overflow: visible; }
	.hero:has(> .hero__block .hero__title) > .hero__block {
		--hero-logo: clamp(31rem, 48vw, 42rem);
		margin-bottom: calc(-1 * (var(--wp--custom--gutter) + var(--hero-overhang))) !important;
		box-shadow: 14px 14px 0 var(--ink);
	}
	.hero:has(> .hero__block .hero__title) > .hero__block .has-large-font-size {
		font-size: clamp(1.3rem, 2.1vw, 1.7rem);
	}
	.hero:has(> .hero__block .hero__title) + * { margin-top: var(--hero-overhang); }
}

/* The prototype's `.hero .btn-row`: one step more air above the buttons. */
.hero__block > .wp-block-buttons { margin-top: var(--sp-5); }

/* ===============================================================
   PAGE SEAMS
   Core puts the root blockGap between the header, main and footer.
   Every band carries its own padding, so bands meet edge to edge as in
   the prototype: no strip of paper under the masthead or above the
   footer.
   =============================================================== */
body .wp-site-blocks > * + * { margin-block-start: 0; }
/* The same inside the page: core's constrained layout puts the blockGap
   above every section of the post content, which showed as a 22px strip of
   paper wherever a coloured section met another section. Sections meet edge
   to edge; the space under a page hero's photo (.page-hero + *, below)
   comes later in this file and still applies. */
.wp-block-post-content > * + * { margin-block-start: 0; }

/* --- statement: a large opening line. It runs across about three quarters
   of the column — the left half plus half of what remains — rather than
   stopping at half, but never the full width of a wide screen:
     - at most 58rem (928px), so it reads as a line, not a banner;
     - at least 36rem (576px) where there is room, so a tablet does not
       squeeze it to a narrow column;
     - never wider than its container, so a phone uses the full width.
   A width, not `ch`: the type size is fluid, so `ch` moved with it. --- */
.statement { max-width: min(100%, max(75%, 36rem), 58rem); }
/* Core centres a constrained group's children; the statement reads from
   the left edge of the content column, under the half-disc. Not
   `margin-left: 0`: wherever the band is wider than contentSize that puts
   it outside the column, left of the logo and the rule above it. The hero
   card uses the same edge. */
.is-layout-constrained > .statement { margin-left: calc((100% - min(100%, var(--wp--style--global--content-size))) / 2) !important; }

/* --- split: a photo beside a text column, the prototype's `.split`. The
   photo fills its column at 4:3, one of the three crop shapes
   (docs/images.md), so a square or panoramic source neither towers over
   the copy beside it nor shrinks to a strip. --- */
.split .wp-block-image img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

/* On a saturated band a photo's frame takes the band's text colour, as
   the prototype's `.split figure` does, instead of ink on violet. */
:is(.is-style-section-blue, .is-style-section-violet, .is-style-section-red) .wp-block-image img {
	border-color: currentColor;
}

/* ===============================================================
   FOOTER — `.foot` on the footer template part's group
   =============================================================== */
.foot .wp-block-column p,
.foot .foot__links {
	font-size: 0.97rem;
	line-height: 1.45;
}
.foot .wp-block-column > p + p { margin-block-start: var(--sp-2); }
.foot .foot__links {
	list-style: none;
	margin-bottom: 0;
	padding: 0;
	display: grid;
	gap: var(--sp-2);
}
.foot a { color: var(--paper); text-decoration: underline; text-underline-offset: 0.25em; }
.foot a:hover {
	color: var(--yellow);
	background: none;
	text-decoration: underline;
	text-underline-offset: 0.25em;
}
/* Grid items, not a flow: the block gap core adds above the second and
   third paragraphs pushed the copyright and legal links below the credit. */
.foot .foot__bar > * { margin: 0; }
.foot .foot__legal a { text-decoration: underline; text-underline-offset: 0.2em; }
/* theme.json paints separators in ink, which vanishes on the ink footer.
   The prototype's rule here is a 3px paper line. */
.foot .wp-block-separator {
	border: 0;
	height: var(--wp--custom--rule--width);
	background: var(--paper);
	opacity: 1;
}

/* ===============================================================
   INNER PAGES — the standard section rhythm
   Every section of an inner page is a Band: core/group with the Band style,
   a half-rule separator, an optional h2, then ordinary core blocks. The
   spacing between and inside sections comes from these rules and nowhere
   else, so no block on a page carries its own margin or padding. See
   docs/pages.md.
   =============================================================== */

/* The page title is a band too. Content starts one spacing step below it,
   not a full band's bottom padding plus the next band's top padding. */
.page-title.is-style-band { padding-bottom: 0; }
.wp-block-post-content > .is-style-band:first-child { padding-top: var(--sp-5); }

/* Consecutive paper bands share a single gap; the next half-rule marks it.
   On an inner page that gap is one step smaller than a full band's padding:
   the pages are sections of one document, not separate posters. */
.wp-block-post-content > .is-style-band + .is-style-band { padding-top: 0; }
.wp-block-post-content > .is-style-band { padding-bottom: var(--sp-5); }

/* Whatever follows the half-rule — a heading or a row — starts one step
   below it, the same on every page. */
.is-style-band > .wp-block-separator.is-style-halfrule + * { margin-block-start: var(--sp-3); }

/* A row of columns is a unit: it stands a clear step away from whatever is
   above and below it inside the band, including another row. */
.is-style-band > * + .wp-block-columns,
.is-style-band > .wp-block-columns + * { margin-block-start: var(--sp-5); }

/* A sub-heading opens a sub-section, so it has more air above than below.
   Scoped to bands, so the home page's own composition is untouched. */
.is-style-band :where(h3, h4):not(:first-child) { margin-block-start: var(--sp-4); }
.is-style-band :where(h2, h3, h4) + * { margin-block-start: var(--sp-2); }

/* Ordered and unordered lists in body copy: the marker hangs, items breathe. */
.wp-block-post-content :where(ol, ul).wp-block-list:not(.tick-list) { padding-left: 1.4em; }
.wp-block-post-content :where(ol, ul).wp-block-list:not(.tick-list) > li + li { margin-top: var(--sp-1); }

/* Prose straight in a band stops at the reading measure, its left edge on
   the half-rule: the band is 78rem, which ran lines to about 150 characters.
   Padding, not max-width, because core's constrained layout would centre a
   narrower box. Leads keep their own inset; columns, cards and home are
   untouched. */
body:not(.home) :is(.is-style-band, [class*="is-style-section-"]):not(:is(.hero, .page-hero) + .is-style-band) > :is(p, ul, ol):not(.has-large-font-size) {
	box-sizing: border-box;
	padding-inline-end: max(0px, calc(min(100%, var(--wp--style--global--content-size)) - var(--wp--custom--measure)));
}

/* A photograph in a band fills the width it is given — its column, or the
   band — however small the file, so photos on one page line up. A resized
   image (a logo, a book cover) keeps the width set on it. */
.is-style-band .wp-block-image:not(.is-resized) img { width: 100%; }

/* An image row (docs/pages.md: a picture in a 40% or 33.33% column, beside the
   copy) stays side by side from 600px. Core stacks every column row below
   782px, which on a tablet turned each row's picture into a 690px-wide slab
   above its text. Core's stacking rules carry !important, so these must too,
   and must restate the columns' own widths. */
@media (min-width: 600px) and (max-width: 781px) {
	.is-style-band .wp-block-columns:has(> .wp-block-column:is([style*="flex-basis:40%"], [style*="flex-basis:33.33%"]) > .wp-block-image) {
		flex-wrap: nowrap !important;
	}
	.is-style-band .wp-block-columns:has(> .wp-block-column:is([style*="flex-basis:40%"], [style*="flex-basis:33.33%"]) > .wp-block-image) > .wp-block-column[style*="flex-basis:40%"] { flex-basis: 40% !important; }
	.is-style-band .wp-block-columns:has(> .wp-block-column:is([style*="flex-basis:40%"], [style*="flex-basis:33.33%"]) > .wp-block-image) > .wp-block-column[style*="flex-basis:60%"] { flex-basis: 60% !important; }
	.is-style-band .wp-block-columns:has(> .wp-block-column:is([style*="flex-basis:40%"], [style*="flex-basis:33.33%"]) > .wp-block-image) > .wp-block-column[style*="flex-basis:33.33%"] { flex-basis: 33.33% !important; }
	.is-style-band .wp-block-columns:has(> .wp-block-column:is([style*="flex-basis:40%"], [style*="flex-basis:33.33%"]) > .wp-block-image) > .wp-block-column[style*="flex-basis:66.66%"] { flex-basis: 66.66% !important; }
}

/* Coloured sections on inner pages: Riso blue for anything you can book or
   join, violet for the studio's own voice, newsprint for the record. A
   section is a core/group with one of the section styles instead of the Band
   style (a group takes one block style), so it gets the band's rhythm here.
   Scoped away from home, whose sections carry their own padding. */
body:not(.home) .wp-block-post-content > :is(.is-style-section-blue, .is-style-section-violet, .is-style-section-newsprint, .is-style-section-red, .is-style-section-yellow) {
	padding-top: var(--sp-5);
	padding-bottom: var(--sp-6);
}
body:not(.home) .wp-block-post-content > :is(.is-style-section-blue, .is-style-section-violet, .is-style-section-newsprint, .is-style-section-red, .is-style-section-yellow):first-child { margin-top: var(--sp-5); }
body:not(.home) .wp-block-post-content > :is(.is-style-section-blue, .is-style-section-violet, .is-style-section-newsprint, .is-style-section-red, .is-style-section-yellow) + .is-style-band { padding-top: var(--sp-5); }
:is(.is-style-section-blue, .is-style-section-violet, .is-style-section-newsprint, .is-style-section-red, .is-style-section-yellow) > .wp-block-separator.is-style-halfrule + * { margin-block-start: var(--sp-3); }
body:not(.home) :is(.is-style-section-blue, .is-style-section-violet, .is-style-section-newsprint, .is-style-section-red, .is-style-section-yellow) > * + :is(.wp-block-columns, .wp-block-group.card-grid),
body:not(.home) :is(.is-style-section-blue, .is-style-section-violet, .is-style-section-newsprint, .is-style-section-red, .is-style-section-yellow) > .wp-block-columns + * { margin-block-start: var(--sp-5); }
.is-style-band > * + .wp-block-group.card-grid { margin-block-start: var(--sp-4); }

/* A card is paper, so it keeps ink text wherever it sits. Inside a Riso blue
   or violet section the section's paper text and headings otherwise land
   on the card's paper ground and vanish. */
.wp-block-group.card,
.wp-block-group.card :is(h1, h2, h3, h4, h5, h6) { color: var(--ink); }

/* Coming up: the list starts a step below its heading. */
.is-style-band > .wp-block-heading + .event-upcoming { margin-block-start: var(--sp-4); }

/* A grid of cards: one step between cards, each card the height of its row. */
.wp-block-group.card-grid { gap: var(--sp-4); }
/* Cards share the row between them: three cards fill it rather than leave
   an empty fourth column. Core's grid is auto-fill; this is auto-fit. */
.wp-block-group.card-grid.is-layout-grid { grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr)); }
.card-grid > .card { margin: 0; }

/* A wall of client logos (a gallery with the class logo-wall, Original
   style images): each logo sits whole in an equal white tile with the ink
   rule, so marks of different shapes and backgrounds read as one row.
   White, not paper, because the logos are screenshots on white. */
.wp-block-gallery.logo-wall { gap: var(--sp-3); margin-top: var(--sp-4); }
.wp-block-gallery.logo-wall > .wp-block-image {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 3 / 2;
	padding: var(--sp-3);
	background: var(--wp--preset--color--white);
	border: var(--wp--custom--rule--width) solid var(--ink);
}
.wp-block-gallery.logo-wall > .wp-block-image img {
	width: auto !important;
	height: auto !important;
	max-width: 100%;
	max-height: 100%;
	object-fit: contain;
	border: 0;
}

/* A price outside a card: the same chip, on its own line. */
.wp-block-post-content :is(.is-style-band, [class*="is-style-section-"]).is-layout-constrained > p.price {
	width: fit-content;
	margin-left: calc((100% - min(100%, var(--wp--style--global--content-size))) / 2) !important;
}

/* Split rows in page content: the buttons sit a step below the copy. */
.split .wp-block-buttons { margin-top: var(--sp-4); }

/* Image style "Plain": logos and marks, which must not wear the ink frame. */
/* Original: the image exactly as uploaded, with no grade and no frame. */
.wp-block-image.is-style-original img { border: 0; }

/* Embedded maps and video fill their column and never set the page width. */
.wp-block-post-content iframe {
	display: block;
	width: 100%;
	max-width: 100%;
	border: var(--wp--custom--rule--width) solid var(--ink);
}

/* ===============================================================
   MOBILE MENU — core/navigation's overlay
   Logo top left, close top right, one row per page with an arrow at the
   right to open its submenu, and the booking button full width at the end.
   Everything is scoped to .is-menu-open, so the desktop menu is untouched.
   The logo and the arrows are added in functions.php; the arrows are an
   Interactivity API store, assets/js/nav-view.js.
   =============================================================== */
.nav-overlay__logo,
.nav-overlay__toggle { display: none; }

/* The menu button stays up to 781px, WordPress's tablet breakpoint. Core
   swaps it for the full menu at 600px, but the full menu is about 500px
   wide and only fits beside the logo from about 700px; below that it
   wrapped under the logo and doubled the header's height. These undo
   core's two 600px rules: button shown, inline menu hidden. */
@media (min-width: 600px) and (max-width: 781px) {
	.masthead .wp-block-navigation__responsive-container-open:not(.always-shown) { display: flex; }
	.masthead .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) { display: none; }
}

body .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	background: var(--paper);
	color: var(--ink);
	padding: var(--sp-2) var(--gutter) var(--sp-5);
}

.is-menu-open .wp-block-navigation__responsive-dialog {
	display: flex;
	flex-direction: column;
	min-height: 100%;
}

.is-menu-open .nav-overlay__logo {
	display: block;
	width: clamp(5.5rem, 24vw, 6.5rem);
	color: var(--ink);
	padding-block: var(--sp-1);
}
.is-menu-open .nav-overlay__logo .logo { width: 100%; }

.is-menu-open .wp-block-navigation__responsive-container-close {
	top: var(--sp-1);
	right: 0;
	width: 2.75rem;
	height: 2.75rem;
	display: grid;
	place-items: center;
}
.is-menu-open .wp-block-navigation__responsive-container-close svg { width: 32px; height: 32px; }

.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
	padding-top: var(--sp-4);
	align-items: stretch;
}

.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container {
	width: 100%;
	gap: 0;
	/* Core aligns overlay items to their content width; rows span the menu. */
	align-items: stretch;
	border-top: var(--wp--custom--rule--width) solid var(--ink);
}

/* One row per top-level page: the link, the arrow, and the submenu below. */
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container > .wp-block-navigation-item {
	display: grid;
	grid-template-columns: 1fr auto;
	align-items: center;
	width: 100%;
	border-bottom: 1px solid var(--ink);
}
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container > .wp-block-navigation-item > .wp-block-navigation-item__content {
	font-size: 1.35rem;
	font-weight: 500;
	letter-spacing: 0.01em;
	padding: 0.8rem 0;
	border: 0;
}
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item.current-menu-item > .wp-block-navigation-item__content,
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:hover {
	color: var(--red);
}

.is-menu-open .nav-overlay__toggle {
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	margin: 0;
	padding: 0;
	background: none;
	border: 0;
	color: var(--ink);
	cursor: pointer;
}
.is-menu-open .nav-overlay__toggle svg { width: 1.25rem; height: 1.25rem; transition: transform 0.15s; }
.is-menu-open .nav-overlay__toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
	.is-menu-open .nav-overlay__toggle svg { transition: none; }
}

/* The submenu spans the row beneath its parent: no card, no shadow. */
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child .wp-block-navigation__submenu-container {
	grid-column: 1 / -1;
	box-shadow: none;
	border: 0;
	min-width: 0;
	padding: 0 0 var(--sp-2) var(--sp-3);
	gap: 0;
}
/* Collapsed unless its arrow says otherwise. The overlay itself only opens
   through core's Interactivity API, which the arrows share, so a menu whose
   arrows cannot run never shows its submenus hidden. */
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child .wp-block-navigation__submenu-container {
	display: none;
}
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child .nav-overlay__toggle[aria-expanded="true"] + .wp-block-navigation__submenu-container {
	display: flex;
}
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	font-size: 1.1rem;
	padding: 0.55rem 0;
	background: none;
}

/* The booking button: full width and large, a clear step below the pages. */
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container > .nav-cta {
	display: block;
	border-bottom: 0;
	margin-top: var(--sp-4);
}
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container > .nav-cta > .wp-block-navigation-item__content {
	display: block;
	box-sizing: border-box;
	width: calc(100% - var(--shadow-off));
	margin: 0;
	padding: 1rem 1.25rem;
	text-align: center;
	font-size: 1.25rem;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--paper);
	background: var(--red);
	border: var(--wp--custom--rule--width) solid var(--ink);
	box-shadow: var(--shadow-off) var(--shadow-off) 0 var(--shadow-col);
}
.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container > .nav-cta > .wp-block-navigation-item__content:hover {
	color: var(--paper);
}

/* ===============================================================
   TEXT LINKS
   Every link in text is underlined, and on hover its colour changes to the
   ground's mark: red on paper (the default, here), blue on newsprint,
   yellow on blue, violet and red, and ink with a thicker underline on
   yellow, where ink is the only colour that reads (the section styles).
   Never a fill: the block behind the words was retired on 2026-09-28. The
   text rules are scoped to text blocks, so logos, image links, menus and
   buttons are never touched.
   =============================================================== */
:where(.wp-block-post-content, .editor-styles-wrapper, .event-main) :where(p, li, dd, td, figcaption, summary) a:where(:not(.wp-element-button)) {
	text-decoration: underline;
	text-underline-offset: 0.12em;
}
:where(.wp-block-post-content, .editor-styles-wrapper, .event-main) :where(p, li, dd, td, figcaption, summary) a:where(:not(.wp-element-button)):hover {
	color: var(--mark, var(--wp--preset--color--red));
	background: none;
	text-decoration-thickness: 0.14em;
}
:is(.is-style-section-blue, .is-style-section-violet, .is-style-section-red, .is-style-section-yellow) a:not(.wp-element-button):hover { background: none; }
.is-style-section-yellow a:hover { text-decoration-thickness: 0.2em; }

/* ===============================================================
   EVENTS — the event archive, one event, and the upcoming list
   (inc/events.php). SPIKE.
   The event templates hold their bands in a constrained <main>, not in
   post content, so the inner-page band rhythm is repeated for them.
   =============================================================== */
.event-main > .is-style-band:first-child { padding-top: var(--sp-5); }
.event-main > .is-style-band + .is-style-band:not([class*="is-style-section-"]) { padding-top: 0; }
.event-main > .is-style-band { padding-bottom: var(--sp-5); }
.event-main > .is-style-section-newsprint { padding-top: var(--sp-5); padding-bottom: var(--sp-6); }

/* The dates line: Jost, a step up from body, in the section's mark. */
.event-when {
	font-family: var(--wp--preset--font-family--jost);
	font-weight: 600;
	letter-spacing: 0.02em;
}
.event-row .event-when { font-size: var(--wp--preset--font-size--large); line-height: 1.2; }
.page-title .eyebrow a { color: inherit; text-decoration: none; }
.page-title .eyebrow a:hover { text-decoration: underline; }

/* Archive grid: three a row on a wide screen, two on a tablet, one on a
   phone. Core's grid is auto-fill by minimum width; this pins the counts. */
.event-archive .wp-block-post-template.is-layout-grid {
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--sp-5);
}
@media (max-width: 900px) {
	.event-archive .wp-block-post-template.is-layout-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 599px) {
	.event-archive .wp-block-post-template.is-layout-grid { grid-template-columns: minmax(0, 1fr); }
}

/* The poster is never cropped: square and portrait posters both sit whole
   in a square frame on the newsprint ground. */
.card > .wp-block-post-featured-image { margin: 0; }
.card > .wp-block-post-featured-image a { display: block; }
.card > .wp-block-post-featured-image img {
	display: block;
	width: 100%;
	aspect-ratio: 1;
	object-fit: contain;
	background: var(--paper-2);
	border: 0;
	border-bottom: var(--wp--custom--rule--width) solid var(--ink);
}
/* An event without a poster gets an empty frame with the logo's half-disc,
   so a row of cards still lines up. */
.event-card:not(:has(> .wp-block-post-featured-image))::before {
	content: "";
	display: block;
	aspect-ratio: 1;
	background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 1'%3E%3Cpath d='M0 1a1 1 0 0 1 2 0z' fill='%23C82E1B'/%3E%3C/svg%3E") center / 22% auto no-repeat, var(--paper-2);
	border-bottom: var(--wp--custom--rule--width) solid var(--ink);
}
.event-card .wp-block-post-title { font-size: var(--wp--preset--font-size--large); line-height: 1.15; }
.event-card .wp-block-post-title a { text-decoration: none; color: inherit; }
.event-card .wp-block-post-title a:hover { text-decoration: underline; }
.event-card .wp-block-post-excerpt__excerpt { margin: 0; }
.card > .wp-block-group.is-layout-constrained > .wp-block-read-more {
	margin-top: auto !important;
	padding-top: 0.9rem;
	font-family: var(--wp--preset--font-family--jost);
	font-size: 0.9rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 0.25em;
	color: var(--blue);
}

/* Pagination: Jost, well clear of the grid. */
.wp-block-query-pagination {
	margin-top: var(--sp-5);
	font-family: var(--wp--preset--font-family--jost);
	font-weight: 600;
}
.wp-block-query-pagination a { color: var(--ink); }
.wp-block-query-pagination .current {
	background: var(--ink);
	color: var(--paper);
	padding: 0 0.4em;
}

/* Inner-page and single-event heroes: the poster. Home alone keeps the
   full-width photograph (.hero). Every other page opens with its title in
   the yellow display type on the left and its picture whole and framed on
   the right. One event stands on a blurred, darkened copy of its poster
   (.event-hero, in templates/single-event.html); a page stands on its
   section's colour (.page-hero with has-spot-*, below), or on a blurred
   copy of its photo when it has none (added by page_hero_ground() in
   functions.php). A has-spot-* class swaps the blur for a
   spot colour: set in the content on a page, from the event's Background
   colour setting on an event (inc/events.php). An event with no poster
   falls back to violet. */
:is(.event-hero, .page-hero) {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	background: var(--ink);
	padding-top: clamp(2rem, 5vw, 4rem);
	padding-bottom: clamp(2.5rem, 6vw, 5rem);
	/* The same rule as the masthead above it, as on home. */
	border-bottom: var(--wp--custom--rule--width) solid var(--ink);
}
:is(.event-hero, .page-hero).is-layout-constrained > :is(.event-hero__bg, .page-hero__bg) {
	position: absolute;
	inset: 0;
	z-index: -2;
	margin: 0 !important;
	max-width: none !important;
}
:is(.event-hero, .page-hero) > :is(.event-hero__bg, .page-hero__bg) img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	border: 0;
	filter: blur(32px) saturate(0.9) brightness(0.62);
	transform: scale(1.25);
}
:is(.event-hero, .page-hero)::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: rgba(18, 18, 26, 0.18);
}
:is(.event-hero, .page-hero)[class*="has-spot-"] > :is(.event-hero__bg, .page-hero__bg),
:is(.event-hero, .page-hero)[class*="has-spot-"]::after { display: none; }
:is(.event-hero, .page-hero).has-spot-blue { background: var(--blue); }
:is(.event-hero, .page-hero).has-spot-violet { background: var(--violet); }
:is(.event-hero, .page-hero).has-spot-red { background: var(--red); }

.event-hero .event-status {
	margin: 0 0 var(--sp-3);
	font-family: var(--wp--preset--font-family--jost);
	font-size: 0.8rem;
	font-weight: 600;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--yellow);
	text-shadow: 2px 2px 0 var(--ink);
}
/* Small yellow type falls short of 4.5:1 on blue (4.22) and red (3.37),
   so the status line is paper there (5.91 and 4.72). Violet keeps yellow
   (4.56). */
.event-hero:is(.has-spot-blue, .has-spot-red) .event-status { color: var(--paper); }
:is(.event-hero__title, .page-hero__title) {
	margin: 0;
	font-family: var(--wp--preset--font-family--jost);
	font-size: clamp(3rem, 7vw, 6.5rem);
	font-weight: 700;
	line-height: 0.96;
	letter-spacing: -0.01em;
	text-transform: uppercase;
	color: var(--yellow);
	text-shadow: 0.04em 0.04em 0 var(--ink);
	overflow-wrap: anywhere;
}
.event-hero .event-when {
	margin: var(--sp-4) 0 0;
	font-size: var(--wp--preset--font-size--large);
	color: var(--paper);
	text-shadow: 2px 2px 0 var(--ink);
}
/* The framed picture: the poster whole, or the page's photo at 4:3. The
   frame and shadow sit on the figure, because the film grade clips
   whatever is inside it. */
.event-hero .event-poster { margin: 0 0 0 auto; max-width: 22rem; }
.event-hero .event-poster img {
	display: block;
	width: 100%;
	height: auto;
	border: var(--wp--custom--rule--width) solid var(--ink);
	box-shadow: var(--wp--preset--shadow--hard-xl);
}
.page-hero .page-hero__photo {
	margin: 0 0 0 auto;
	max-width: 30rem;
	border: var(--wp--custom--rule--width) solid var(--ink);
	box-shadow: var(--wp--preset--shadow--hard-xl);
}
.page-hero .page-hero__photo img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border: 0;
}
@media (max-width: 781px) {
	:is(.event-hero .event-poster, .page-hero .page-hero__photo) { margin: var(--sp-4) 0 0; }
}

/* A page hero holds its title beside the photo, nothing else: the page's
   lead follows in a band under it, and the menu underlines the section
   you are in. The title is centred in a 45 percent column, sized against
   it (cqi) so the longest word, ACCESSIBILITY, stays on one line at every
   width; the photo takes the 55 percent beside it. */
/* On a blur, room photos are lighter than posters, so a page hero's ground
   is darkened more than an event's: at the event's 18 percent the lightest
   ground behind a title was 2.6:1 against the yellow; at 32 it clears 3:1. */
.page-hero::after { background: rgba(18, 18, 26, 0.32); }
.page-hero__cols > .wp-block-column:first-child { container-type: inline-size; }
/* ACCESSIBILITY is 7.23 times its font size wide at 700: 12.8cqi leaves it 7% to spare. */
.page-hero .page-hero__title { font-size: clamp(2.4rem, 12.8cqi, 6.5rem); }

/* From 600px a page hero is shorter and its photo hangs over the bottom
   edge by --hero-overhang, the same overhang as home's card. The section
   after it moves down by that amount, as on home, so its half-rule never
   sits under the photo. The hero lets the photo out, but the blurred
   fallback ground stays clipped. Single events keep their own hero. */
/* 40rem: with the lighter title, the photo takes most of its 55% column
   (646 of 667px at 1880px) and stays clear of the title. */
.page-hero .page-hero__photo { max-width: 40rem; }
@media (min-width: 600px) {
	.page-hero {
		--hero-pad-top: clamp(1.75rem, 4vw, 3.25rem);
		padding-top: var(--hero-pad-top);
		padding-bottom: 0;
		overflow: visible;
	}
	.page-hero > .page-hero__bg { overflow: hidden; }
	.page-hero .page-hero__photo { margin-bottom: calc(-1 * var(--hero-overhang)); }
	.page-hero + * { margin-top: var(--hero-overhang); }
}

/* The lead under a page hero (and under home's cover): the page's intro,
   one size up and inset from both sides, so it reads as a lead-in rather than a line across the page.
   Padding, not margin: core's constrained layout forces a child's side
   margins to auto. From 600px, where the photo hangs over the hero's edge,
   the band opens one step lower, so the intro starts a full step below the
   photo's bottom edge (its shadow is not counted). The padding sits inside
   the band's 78rem content width (border-box): as content-box it widened
   the paragraph outward instead, so wherever the screen was wider than the
   column the text stayed on the column's edges. */
:is(.hero, .page-hero) + .is-style-band > .has-large-font-size {
	font-size: clamp(1.6rem, 2.3vw, 1.95rem) !important; /* over the preset's own !important */
	line-height: 1.4;
	padding-inline: clamp(var(--sp-4), 8vw, 8rem);
	box-sizing: border-box;
}
/* A note that follows the lead in the same band (the meeting rooms' access
   line) keeps the lead's inset. */
:is(.hero, .page-hero) + .is-style-band > .has-large-font-size ~ p {
	padding-inline: clamp(var(--sp-4), 8vw, 8rem);
	box-sizing: border-box;
}
@media (min-width: 600px) {
	:is(.wp-block-post-content, .event-main, main) > :is(.hero, .page-hero) + .is-style-band { padding-top: var(--sp-6); }
}
@media (max-width: 599px) {
	:is(.hero, .page-hero) + .is-style-band > :is(.has-large-font-size, .has-large-font-size ~ p) { padding-inline: var(--sp-3); }
}
/* Side by side, the title is centred on the whole coloured band: its
   column reaches up through the hero's top padding, which has no match
   at the bottom, where the photo hangs over instead. */
@media (min-width: 782px) {
	.page-hero .page-hero__cols > .wp-block-column:first-child {
		align-self: stretch;
		display: flex;
		flex-direction: column;
		justify-content: center;
		margin-top: calc(-1 * var(--hero-pad-top, 0px));
	}
}

/* Section colours: a page hero stands on its section's colour, set in the
   content with has-spot-*. Spaces blue, About red, Events violet (the
   Events page and Past events; one event keeps its poster's blur), Contact
   yellow. The title is yellow everywhere but on yellow, where it is white
   (#fff) and leans on the same ink shadow. */
:is(.event-hero, .page-hero).has-spot-yellow { background: var(--yellow); }
.page-hero.has-spot-yellow .page-hero__title { color: var(--wp--preset--color--white); }


/* Upcoming rows: a rule between events, like a printed listing. */
.event-upcoming .wp-block-post-template { list-style: none; padding: 0; margin: 0; }
.event-upcoming .wp-block-post-template > li + li {
	margin-top: var(--sp-4);
	padding-top: var(--sp-4);
	border-top: 1px solid var(--ink);
}
.event-row .wp-block-post-title { margin: 0; font-size: var(--wp--preset--font-size--large); }
.event-row .wp-block-post-title a { text-decoration: none; color: inherit; }
.event-row .wp-block-post-title a:hover { text-decoration: underline; }
.event-row .wp-block-post-excerpt__excerpt { margin: 0; }

/* Search, 404 and the fallback list: the search form in the theme's square
   inks, and each result a title over its excerpt, ruled off from the next. */
.site-search .wp-block-search__inside-wrapper { max-width: 36rem; gap: var(--sp-2); }
.site-search .wp-block-search__input {
	border: var(--wp--custom--rule--width) solid var(--ink);
	border-radius: 0;
	background: var(--wp--preset--color--white);
	padding: 0.7rem 0.9rem;
	font: inherit;
}
.site-search .wp-block-search__button { margin-left: 0; }
.search-results .wp-block-post-template > li {
	padding-block: var(--sp-3);
	border-top: 1px solid var(--ink);
}
.search-results .wp-block-post-title { text-transform: none; letter-spacing: 0; }
.search-results .wp-block-post-title a { text-decoration: none; }
.search-results .wp-block-post-title a:hover { text-decoration: underline; }

/* ========================================================
   FOCUS RINGS
   One keyboard ring everywhere: 3px solid, 3px clear of the thing, in
   --focus. theme.json draws it on links and buttons (elements.link and
   elements.button, :focus-visible); the rule below adds the menu's own
   controls and the details summary, which are not links. --focus is ink
   (top of this file) and turns paper on the dark grounds: the blue,
   violet and red bands, an ink group (the footer) and the poster heroes,
   which stand on a colour or a darkened blur. A light ground inside one
   of those (Contact's yellow hero, a yellow or newsprint band, a card, a
   paper group) turns it back to ink. The ring is drawn on the ground
   around a button, so a button's own background class never sets it.
   Nothing moves on focus.
   =============================================================== */
.is-style-section-blue,
.is-style-section-violet,
.is-style-section-red,
:is(.page-hero, .event-hero),
:is(.has-ink-background-color, .has-black-background-color, .has-blue-background-color, .has-violet-background-color, .has-red-background-color, .has-dark-gray-background-color):not(.wp-element-button) { --focus: var(--paper); }
.is-style-section-yellow,
.is-style-section-newsprint,
.page-hero.has-spot-yellow,
.card,
:is(.has-paper-background-color, .has-paper-alt-background-color, .has-white-background-color, .has-yellow-background-color):not(.wp-element-button) { --focus: var(--ink); }

.wp-block-details > summary:focus-visible,
.wp-block-navigation .wp-block-navigation-item__content:focus-visible,
.wp-block-navigation__responsive-container-open:focus-visible,
.wp-block-navigation__responsive-container-close:focus-visible,
.nav-overlay__toggle:focus-visible,
.nav-overlay__logo:focus-visible {
	outline: 3px solid var(--focus);
	outline-offset: 3px;
}

/* A caption on a light ground nested in a coloured band (a card, a paper
   group) keeps its normal ink-grey, not the band's paper caption colour. */
:is(.card, .has-paper-background-color, .has-paper-alt-background-color, .has-white-background-color) .wp-element-caption {
	color: var(--wp--preset--color--gray);
=======
/* ---------------------------------------------------------------
   REDUCED MOTION
   Everything that moves under the pointer stays put: buttons pressing
   into their shadow on hover and click (theme.json styles.css), the
   masthead's Bookings, and a linked card. The shadow still changes, so
   the press still reads. The carousel's crossfade and the menu arrow
   have their own rules beside them. No new motion goes in without a
   line here.
   --------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	:root :is(.wp-element-button, .wp-block-button__link, .card, .wp-block-navigation .nav-cta > .wp-block-navigation-item__content) {
		transition: none;
	}
	:root :is(.wp-element-button, .wp-block-button__link):is(:hover, :active),
	:root .wp-block-navigation .nav-cta > .wp-block-navigation-item__content:hover,
	:root .card:has(a):hover {
		transform: none;
	}
}
