/**
 * Relaxed — the rules theme.json cannot express.
 *
 * Everything colour-, type-, spacing- or layout-related lives in theme.json so
 * it stays editable in the Site Editor. What is left here is structural: block
 * styles, the overlay header, focus behaviour, motion preferences.
 *
 * Keep this file small. If a rule could be a theme.json value, move it there.
 */

/* -------------------------------------------------------------------------
 * Base
 * ---------------------------------------------------------------------- */

html {
	scroll-behavior: smooth;
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
}

/* Visible, themed focus ring. Never remove without a replacement. */
:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--wp--preset--color--contrast);
	outline-offset: 3px;
}

.is-style-overlay-header :focus-visible,
.has-base-color :focus-visible {
	outline-color: currentColor;
}

/* -------------------------------------------------------------------------
 * Section rhythm
 *
 * WordPress applies its block gap between sibling blocks — at the root, and
 * again between the children of the post content. That is right for prose, and
 * wrong for this theme's sections: every one of them carries its own generous
 * top and bottom padding and is meant to butt against its neighbours. The gap
 * showed up as a 24px strip of page colour between them, most obvious wherever
 * a dark band met a sand one, where it reads as an empty block.
 *
 * The header, footer and notice bar own their padding too, so the same applies
 * at the top level.
 *
 * Scoped to full-width sections only. A paragraph following a paragraph still
 * gets its normal block gap.
 * ---------------------------------------------------------------------- */

.wp-site-blocks > * {
	margin-block-start: 0;
}

:where(.wp-block-post-content, main) > .alignfull + .alignfull {
	margin-block-start: 0;
}

/* The same problem at the ends of the page rather than between sections.
 *
 * `main` carries its own top and bottom padding, which is right for an ordinary
 * page — the title needs air under the header. On a page built from full-bleed
 * sections it is wrong twice over: the first section already has padding, so
 * main's adds a band of page colour under the header, and main's bottom padding
 * puts another one above the footer. Both read as empty blocks, and both are
 * most obvious when the neighbouring section is a dark band or the footer has
 * its own background.
 *
 * Conditioned on the post content being main's only content *and* starting or
 * ending with a full-bleed section, so a page with a visible title keeps the
 * breathing room it needs.
 *
 * `!important` because the templates set that padding as a block attribute,
 * which WordPress renders as an inline style — no selector can outrank it. The
 * alternative was moving the padding into this stylesheet, which would have
 * taken it out of the Site Editor's spacing controls on every page. Keeping it
 * editable is worth one override that only fires when the padding is provably
 * unwanted.
 */
main:has(> .wp-block-post-content:first-child > .alignfull:first-child) {
	padding-block-start: 0 !important;
}

main:has(> .wp-block-post-content:last-child > .alignfull:last-child) {
	padding-block-end: 0 !important;
}

/* -------------------------------------------------------------------------
 * "Hide when signed in"
 *
 * A block style for any Group — put it on the notice bar to keep an opening
 * promotion in front of visitors while staying out of the way of staff and
 * returning customers.
 *
 * CSS rather than a PHP `is_user_logged_in()` check on purpose. Page caches
 * serve one copy of the HTML to everybody, so a server-side conditional would
 * bake whichever state was cached first into every response; the `logged-in`
 * body class WordPress already emits is evaluated per visitor by the browser.
 * The markup is still sent — that is fine for a one-line bar, and it is not a
 * way to hide anything sensitive.
 *
 * The editor canvas has no `logged-in` body class, so the block stays visible
 * while you are editing it.
 * ---------------------------------------------------------------------- */

body.logged-in .is-style-hide-when-signed-in {
	display: none;
}

/* -------------------------------------------------------------------------
 * Branding
 *
 * Every header ships with a Site Logo *and* a Site Title. On a fresh install
 * there is no logo, so the title carries the branding and the header is never
 * empty. The moment a logo is uploaded the title steps aside.
 *
 * Cheaper than shipping two variants of every header, and it means the admin
 * never has to swap blocks to add a logo.
 * ---------------------------------------------------------------------- */

.relaxed-brand:has(.wp-block-site-logo img) .wp-block-site-title {
	display: none;
}

/* Keep both visible while editing, so the title is still selectable. */
.editor-styles-wrapper .relaxed-brand .wp-block-site-title {
	display: block;
}

/* -------------------------------------------------------------------------
 * Header — overlay mode
 *
 * Every template uses the same header part, so the menu is identical on every
 * page. Whether that header sits *above* the page or floats *over* the first
 * section is a per-template decision, made by putting `is-style-overlay-header`
 * on the Template Part block:
 *
 *   <!-- wp:template-part {"slug":"header","tagName":"header",
 *        "className":"is-style-overlay-header"} /-->
 *
 * Add or remove that class in the Site Editor and the page changes; the header
 * itself is untouched, so editing the menu still updates every page at once.
 * ---------------------------------------------------------------------- */

header.is-style-overlay-header {
	position: absolute;
	inset-inline: 0;
	top: 0;
	z-index: 20;
	color: var(--wp--preset--color--base);
}

/* The header is out of flow, but WordPress still applies the root block gap to
   the next top-level block — which shows as a strip of page colour above a
   full-bleed hero. Reclaim it. */
header.is-style-overlay-header + * {
	margin-block-start: 0;
}

/* A hero photograph can be light at the top, where the menu sits. This scrim
   guarantees the header stays legible over any image without darkening the
   whole hero. */
header.is-style-overlay-header::before {
	content: "";
	position: absolute;
	inset: 0 0 -3rem;
	background: linear-gradient(to bottom, rgba(15, 14, 13, 0.45), transparent);
	pointer-events: none;
	z-index: -1;
}

header.is-style-overlay-header a,
header.is-style-overlay-header .wp-block-site-title a,
header.is-style-overlay-header .wp-block-navigation a {
	color: currentColor;
}

/* Site logo goes light over dark imagery. Swap to a real light logo in the
   Site Editor if the mark has colour worth keeping. */
header.is-style-overlay-header .wp-block-site-logo img {
	filter: brightness(0) invert(1);
}

/* The notice bar carries its own solid background, so it needs no scrim and
   must not be washed out by the one above. */
header.is-style-overlay-header .relaxed-notice {
	position: relative;
	z-index: 1;
}

/* The overlay menu opens on a solid surface, so undo the inversion inside it. */
header.is-style-overlay-header .wp-block-navigation__responsive-container.is-menu-open {
	color: var(--wp--preset--color--contrast);
}

header.is-style-overlay-header .wp-block-button__link {
	border-color: currentColor;
	background-color: transparent;
	color: currentColor;
}

header.is-style-overlay-header .wp-block-button__link:hover {
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
}

/* -------------------------------------------------------------------------
 * Header layout
 *
 * The header row is nowrap, so without these the flex algorithm shrinks the
 * brand and the CTA before it shrinks the menu — a long nav breaks the logo
 * onto two lines and stacks the button letter by letter. The navigation is the
 * only thing that should ever give way.
 * ---------------------------------------------------------------------- */

/* The header row is full-width so the logo sits at the left of the *window*
   rather than inside the 820px reading column. A full-width alignment cancels
   the root gutters with negative margins, though, which would leave the logo
   and the CTA flush against the window edge — so put the gutters back. */
.relaxed-header > .alignfull {
	padding-left: var(--wp--style--root-padding-left, var(--wp--preset--spacing--30));
	padding-right: var(--wp--style--root-padding-right, var(--wp--preset--spacing--30));
}

/* Past the wide measure the gutter opens up, so the header keeps pace with the
   content instead of drifting toward the bezel on a very large display. */
@media (min-width: 1600px) {
	.relaxed-header > .alignfull {
		padding-left: var(--wp--preset--spacing--50);
		padding-right: var(--wp--preset--spacing--50);
	}
}

.relaxed-header .relaxed-brand,
.relaxed-header .relaxed-header__cta {
	flex-shrink: 0;
}

.relaxed-header .wp-block-site-title,
.relaxed-header .wp-block-button__link {
	white-space: nowrap;
}

/* -------------------------------------------------------------------------
 * Navigation
 * ---------------------------------------------------------------------- */

.wp-block-navigation .wp-block-navigation-item__content {
	position: relative;
	text-decoration: none;
}

/* The rule under a nav item marks the *current* page, not hover — hover is the
   same thickening used by every other link. Two different signals, so you can
   tell where you are while pointing somewhere else. */
.wp-block-navigation:not(.has-background) .wp-block-navigation-item__content::after {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	bottom: -0.35em;
	width: 100%;
	height: 1px;
	background: currentColor;
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform var(--wp--custom--transition--base);
}

.wp-block-navigation:not(.has-background) .current-menu-item > .wp-block-navigation-item__content::after {
	transform: scaleX(1);
}

/* Core switches the header menu to its overlay at 600px. A studio menu plus a
   booking button plus WooCommerce's account icon needs more room than that, and
   the nav is nowrap so it cannot fold — move the switch to 900px.
   Same technique core uses, just a different breakpoint. */
@media (max-width: 899px) {
	.relaxed-header .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}

	.relaxed-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}
}

/* The overlay menu.
 *
 * Its colours are NOT set here. Core paints the overlay with
 * `.wp-block-navigation:not(.has-background) …is-menu-open:not(…)`, which is
 * five classes deep — a theme rule can only beat it by escalating the
 * specificity war. The Navigation block's own `overlayBackgroundColor` /
 * `overlayTextColor` attributes are the supported lever: setting them in the
 * header parts adds `has-background`, which switches core's rule off at the
 * source, and leaves the colours editable in the Site Editor.
 *
 * What is left here is layout, which core does not fight over. It is centred
 * rather than inheriting the header's `justify: right` — that had the links
 * stacked in a narrow strip against the right edge with two-thirds of the
 * screen empty below them.
 */
.relaxed-header .wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open {
	padding: var(--wp--preset--spacing--40);
}

/* Core nests a `__responsive-dialog` between the overlay and its content, and
   that wrapper — not the overlay — is what the close button is positioned
   against. Centring the overlay's flex children therefore dragged the close
   button into the middle of the screen with the links. Stretching the dialog
   to fill the overlay fixes both halves at once: the links centre inside it,
   and the button has a full-size box to pin its corner to. */
/* Core nests two wrappers, not one: container > __responsive-close >
   __responsive-dialog. The middle one is the actual flex item and ships as
   `display: block`, so growing the dialog alone does nothing — it has to grow
   too, and become a flex parent, before anything inside it can be centred.
   flex-grow rather than height:100%: the overlay is a *column* flex container,
   so filling the free space is growth along the main axis; a percentage height
   resolves to auto here and left the menu sitting near the top. */
.relaxed-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-close {
	display: flex;
	flex-direction: column;
	flex-grow: 1;
	width: 100%;
}

.relaxed-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog {
	align-items: center;
	display: flex;
	flex-grow: 1;
	justify-content: center;
}

.relaxed-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
	top: 0;
	right: 0;
}

.relaxed-header
	.wp-block-navigation
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content {
	align-items: center;
	gap: var(--wp--preset--spacing--30);
	justify-content: center;
	width: 100%;
}

.relaxed-header
	.wp-block-navigation
	.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__container {
	align-items: center;
	gap: var(--wp--preset--spacing--30);
	justify-content: center;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 400;
	letter-spacing: var(--wp--custom--tracking--tight);
	text-transform: none;
}

/* The current-page rule is a header affordance; at overlay size it reads as a
   stray line under one item. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content::after {
	display: none;
}

/* -------------------------------------------------------------------------
 * Links
 *
 * No underline on hover. Instead the text thickens — done with a text-shadow
 * rather than font-weight so nothing reflows: a real weight change alters glyph
 * widths, which nudges every word after the link and makes a whole paragraph
 * twitch as the cursor passes over it. text-shadow is also animatable, so the
 * thickening can ease in instead of snapping.
 * ---------------------------------------------------------------------- */

a {
	transition: text-shadow 180ms ease, color 180ms ease,
		text-decoration-color 180ms ease;
}

a:where(:not(.wp-element-button)):hover,
a:where(:not(.wp-element-button)):focus-visible {
	text-shadow:
		0.018em 0 0 currentColor,
		-0.018em 0 0 currentColor;
}

/* theme.json pins link colour to `contrast`, which is invisible on an inverted
   surface — a dark notice bar, the CTA band, text over a Cover. Anywhere the
   surrounding text has been flipped, links follow it instead. */
:where(.has-base-color, .wp-block-cover__inner-container)
	a:not(.wp-element-button):not(.wp-block-navigation-item__content) {
	color: currentColor;
}

/* Prose links keep a permanent underline, because a link inside a paragraph has
   to be identifiable without hovering and without relying on colour alone
   (WCAG 1.4.1). It is drawn in the accent so it reads as a hairline rather than
   a hard rule, and firms up to full strength on hover. Nav, footer and card
   links get none of this — position already marks them as links. */
.wp-block-post-content p a:not(.wp-element-button),
.wp-block-post-content li a:not(.wp-element-button) {
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--accent);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.22em;
}

.wp-block-post-content p a:not(.wp-element-button):hover,
.wp-block-post-content li a:not(.wp-element-button):hover {
	text-decoration-color: currentColor;
}

/* -------------------------------------------------------------------------
 * Buttons
 * ---------------------------------------------------------------------- */

.wp-block-button__link {
	transition: background-color var(--wp--custom--transition--base),
		color var(--wp--custom--transition--base),
		border-color var(--wp--custom--transition--base);
}

/* Core's own outline style, restyled to the theme's hairline language. */
.wp-block-button.is-style-outline > .wp-block-button__link {
	border-width: 1px;
	border-color: currentColor;
}

.wp-block-button.is-style-outline > .wp-block-button__link:hover,
.wp-block-button.is-style-outline > .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	border-color: var(--wp--preset--color--contrast);
}

/* A text link that still behaves like a button block. */
.wp-block-button.is-style-link-arrow > .wp-block-button__link {
	background: none;
	border: 0;
	border-bottom: 1px solid currentColor;
	color: inherit;
	padding: 0 0 0.5em;
}

.wp-block-button.is-style-link-arrow > .wp-block-button__link::after {
	content: " \2192";
	display: inline-block;
	transition: transform var(--wp--custom--transition--base);
}

.wp-block-button.is-style-link-arrow > .wp-block-button__link:hover::after {
	transform: translateX(0.35em);
}

/* -------------------------------------------------------------------------
 * Group styles
 * ---------------------------------------------------------------------- */

.wp-block-group.is-style-card {
	background-color: var(--wp--preset--color--base-3);
	box-shadow: var(--wp--preset--shadow--soft);
	padding: var(--wp--preset--spacing--40);
}

.wp-block-group.is-style-bordered {
	border: 1px solid var(--wp--preset--color--accent-2);
	padding: var(--wp--preset--spacing--40);
}

/* -------------------------------------------------------------------------
 * Image styles
 * ---------------------------------------------------------------------- */

.wp-block-image.is-style-frame img {
	outline: 1px solid var(--wp--preset--color--accent-2);
	outline-offset: 0.75rem;
}

.wp-block-image.is-style-portrait img {
	aspect-ratio: 3 / 4;
	object-fit: cover;
	width: 100%;
}

/* Opt-in zoom for linked cards. Applied by patterns via an extra class. */
.relaxed-zoom {
	overflow: hidden;
}

.relaxed-zoom img {
	transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
	will-change: transform;
}

.relaxed-zoom:hover img,
.relaxed-zoom:focus-within img {
	transform: scale(1.04);
}

/* -------------------------------------------------------------------------
 * Grids
 *
 * WordPress's Grid layout in "Auto" mode emits
 * `repeat(auto-fill, minmax(min(Xrem, 100%), 1fr))`. auto-fill keeps empty
 * tracks, so four people in a grid wide enough for five sit in the left 4/5 of
 * the row with a hole on the right — which reads as "not centred".
 *
 * The theme's own patterns avoid it by setting an explicit column count. For
 * hand-built grids, the "Centre items" block style below fixes it, and core's
 * Layout panel offers Manual columns as the other way out.
 * ---------------------------------------------------------------------- */

/* Manual column counts do not collapse on their own, so give every grid a
   sensible floor on small screens. Two class selectors, which outranks the
   generated `.wp-container-*` rule holding the desktop count. */
@media (max-width: 781px) {
	.wp-block-group.is-layout-grid,
	.wp-block-post-template.is-layout-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 519px) {
	.wp-block-group.is-layout-grid,
	.wp-block-post-template.is-layout-grid {
		grid-template-columns: 1fr;
	}
}

/* -------------------------------------------------------------------------
 * "Centre items" — a block style for Group and Columns
 *
 * Centres the children of a row or grid rather than letting them hug the
 * inline start. Handles all four layout types a Group can have, because which
 * one is active depends on a dropdown the admin may change later.
 * ---------------------------------------------------------------------- */

.is-style-center-items.is-layout-flex {
	justify-content: center;
}

/* For a grid, collapsing empty tracks is what actually centres the row —
   auto-fit does that, auto-fill does not. The minimum track width is inherited
   from the block's own generated rule via this variable, which patterns and the
   Styles panel can override; 14rem matches the theme's default card. */
.is-style-center-items.is-layout-grid {
	grid-template-columns: repeat(
		auto-fit,
		minmax(min(var(--relaxed-grid-min, 14rem), 100%), 1fr)
	);
	justify-content: center;
	justify-items: center;
}

.is-style-center-items.is-layout-constrained > *,
.is-style-center-items.is-layout-flow > * {
	margin-inline: auto;
}

.is-style-center-items :where(p, h1, h2, h3, h4, h5, h6) {
	text-align: center;
}

/* -------------------------------------------------------------------------
 * Columns & lists
 * ---------------------------------------------------------------------- */

.wp-block-columns.is-style-hairline-split > .wp-block-column + .wp-block-column {
	border-inline-start: 1px solid var(--wp--preset--color--accent-2);
	padding-inline-start: var(--wp--preset--spacing--40);
}

@media (max-width: 781px) {
	.wp-block-columns.is-style-hairline-split > .wp-block-column + .wp-block-column {
		border-inline-start: 0;
		border-top: 1px solid var(--wp--preset--color--accent-2);
		padding-inline-start: 0;
		padding-top: var(--wp--preset--spacing--40);
	}
}

.wp-block-list.is-style-ticks {
	list-style: none;
	padding-inline-start: 0;
}

.wp-block-list.is-style-ticks li {
	padding-inline-start: 1.75em;
	position: relative;
}

.wp-block-list.is-style-ticks li::before {
	content: "\2713";
	position: absolute;
	inset-inline-start: 0;
	color: var(--wp--preset--color--accent);
}

/* -------------------------------------------------------------------------
 * Social links
 *
 * Core's "logos only" style drops the coloured pill but keeps each service's
 * brand colour on the glyph — so the footer came out with a magenta Instagram
 * mark and a green WhatsApp one, ignoring the palette entirely and looking
 * worse the darker the variation. Monochrome is also what every reference
 * studio site does.
 *
 * The `:not()` clauses are the escape hatch: set an icon colour on the block
 * and this rule stands down, brand colours included.
 * ---------------------------------------------------------------------- */

.wp-block-social-links.is-style-logos-only:not(.has-icon-color):not(.has-icon-background-color)
	.wp-social-link {
	color: currentColor;
}

/* -------------------------------------------------------------------------
 * Details / FAQ
 * ---------------------------------------------------------------------- */

.wp-block-details summary {
	cursor: pointer;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--large);
	list-style: none;
	padding-inline-end: 2rem;
	position: relative;
}

.wp-block-details summary::-webkit-details-marker {
	display: none;
}

.wp-block-details summary::after {
	content: "+";
	position: absolute;
	inset-inline-end: 0;
	top: 0;
	font-family: var(--wp--preset--font-family--body);
	transition: transform var(--wp--custom--transition--base);
}

.wp-block-details[open] summary::after {
	content: "\2013";
}

/* -------------------------------------------------------------------------
 * Cover heroes
 * ---------------------------------------------------------------------- */

/* Stops a full-height hero from overflowing on mobile browsers whose toolbars
   change the viewport height mid-scroll. */
.wp-block-cover.relaxed-hero-full {
	min-height: 100svh;
}

@supports not (height: 100svh) {
	.wp-block-cover.relaxed-hero-full {
		min-height: 100vh;
	}
}

/* -------------------------------------------------------------------------
 * Motion
 * ---------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}
