/*
Theme Name: BP Base
Theme URI: https://binarypact.com
Author: Binary Pact
Description: The standard Binary Pact client site. A small-business layout built entirely from core blocks — hero, services, service areas, work gallery and a call-to-action — with every colour, size and space named in theme.json so a client's brand replaces it from the registry. This is the Standard design; a Bespoke build overrides it from tenants/<slug>/.
Version: 1.0.0
Requires at least: 6.6
Tested up to: 7.1
Requires PHP: 8.2
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: bp-base
Tags: full-site-editing, block-patterns, custom-colors, custom-logo, custom-menu, featured-images, full-width-template, two-columns
*/

/*
 * WHAT BELONGS IN THIS FILE, NOW THAT BP-BASE HAS A DESIGN.
 *
 * bp-base used to be plumbing with no visual opinion, and this file was
 * therefore almost empty. It has an opinion now — it is the Standard product —
 * but the split has not moved: **theme.json holds every value, this file holds
 * only arrangement.**
 *
 * The test for a rule below is: could a client's brand ever need to change it?
 * If yes it is a preset and belongs in theme.json, because CSS here applies to
 * all 664 sites identically and no registry entry can reach it. That is why
 * every colour below is a var(--wp--preset--color--*) and not a hex — including
 * the derived tints, which follow the client's brand instead of fighting it
 * with somebody else's grey.
 *
 * A tenant's own CSS is tenants/<slug>/custom.css, enqueued after this by
 * plugins/bp-platform.php. It is not a place to fix this file.
 */

:root {
	/*
	 * DERIVED TINTS. The palette is five slugs and never a sixth — a sixth
	 * would be a colour a theme could reference and no tenant could set. But a
	 * design needs quiet section grounds and hairline rules, so they are mixed
	 * from the five at use time: a client with a warm brand gets warm tints, a
	 * client with a cold one gets cold tints, and neither needs a registry line.
	 *
	 * The fallbacks matter. color-mix() is unsupported below Safari 16.2 and
	 * Chrome 111; without them a section ground would resolve to nothing and
	 * text would land on bare white. Declaring the plain value first means an
	 * old browser keeps a usable (if flatter) design rather than a broken one.
	 */
	--bp-tint: var(--wp--preset--color--surface);
	--bp-tint: color-mix(in srgb, var(--wp--preset--color--accent) 6%, var(--wp--preset--color--surface));

	--bp-rule: var(--wp--preset--color--muted);
	--bp-rule: color-mix(in srgb, var(--wp--preset--color--muted) 28%, transparent);
}

/* Never let a long word or a pasted URL break the layout on a phone. */
body {
	overflow-wrap: break-word;
}

/* Client-supplied images are whatever size the client had. */
img,
video {
	max-width: 100%;
	height: auto;
}

/* Keyboard focus must stay visible; several block styles would otherwise remove it. */
:where(a, button, input, select, textarea):focus-visible {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 2px;
}

/* Respect a visitor who has asked for less motion. */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ---------------------------------------------------------------------------
   A link on a coloured ground

   theme.json colours links `primary`, which is right on the page's surface and
   INVISIBLE on a primary-coloured band — a phone number on a brand-coloured bar
   vanishes into it. acme's header had been rendering an invisible phone number
   for exactly this reason, on the one element the whole design exists to show.

   This is one rule rather than a fix per part on purpose: it covers bp-base's
   own call bar and footer, and it covers a TENANT'S custom coloured section
   too, which a `.bp-callbar a` rule never could. Anywhere a block declares its
   own text colour, links take it.

   Buttons are excluded: they carry their own background and text colour from
   theme.json and must not inherit the band's.
   --------------------------------------------------------------------------- */

.has-text-color a:not(.wp-element-button) {
	color: inherit;
}

/* ---------------------------------------------------------------------------
   Page rhythm

   Sections carry their own padding, so nothing between them adds more. The
   root block gap would otherwise put a 1rem strip of page background between
   the header, every full-width section and the footer — visible as a white
   line wherever two tinted or coloured bands meet.
   --------------------------------------------------------------------------- */

.wp-site-blocks > * + *,
main > * + *,
.wp-block-post-content > .alignfull + *,
.wp-block-post-content > * + .alignfull {
	margin-block-start: 0;
}

/* An inside page's own breathing room (templates/page.html), dropped at
 * whichever end is a full-width section that brings its own. */
.bp-page-content {
	padding-block: var(--wp--preset--spacing--40) var(--wp--preset--spacing--80);
}

.bp-page-content:has(> .alignfull:first-child) {
	padding-top: 0;
}

/* A first section on the plain page ground would stack its own top padding
 * under the title's, reading as a hole. One with a ground of its own keeps
 * it — there the padding is inside the colour. */
.bp-page-content > .alignfull:first-child:not(.has-background):not(.bp-tint) {
	padding-top: var(--wp--preset--spacing--30) !important;
}

.bp-page-content:has(> .alignfull:last-child) {
	padding-bottom: 0;
}

/* Plain content on an inside page — text typed in, a contact form — runs the
 * same width as the header and the page title, so it lines up with both edges.
 * Core's constrained layout would hold it to the narrower content size. */
.bp-page-content > :not(.alignfull):not(.alignwide):not(.alignleft):not(.alignright) {
	max-width: var(--wp--style--global--wide-size, 76rem);
}

/* ---------------------------------------------------------------------------
   Section ground
   A quiet alternating band, so a long page has rhythm without needing a second
   background colour in the palette. Applied as a className on a group block.
   Mixed from the ACCENT, not the grey: a warm cream behind an orange brand, a
   cool one behind a teal — a ground that belongs to the brand instead of a
   neutral grey that reads as "unstyled".
   --------------------------------------------------------------------------- */

.bp-tint {
	background-color: var(--bp-tint);
}

/* ---------------------------------------------------------------------------
   Eyebrow
   The label above a section heading, set as an outlined pill: sentence case,
   brand colour, a hairline round it. It names the section the way a tab does,
   so the heading under it can be a statement rather than a category. This is
   the ONE place the brand colour is used on body-size type, which is what
   stops it reading as decoration.
   --------------------------------------------------------------------------- */

.bp-eyebrow {
	width: fit-content;
	margin-bottom: var(--wp--preset--spacing--40);
	padding: 0.3rem 0.9rem;
	border: 1px solid var(--wp--preset--color--primary);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--primary) 45%, transparent);
	border-radius: 999px;
	color: var(--wp--preset--color--primary);
	font-family: var(--wp--preset--font-family--heading);
	font-size: 0.875rem;
	font-weight: 500;
	line-height: 1.4;
}

.bp-eyebrow.has-text-align-center {
	margin-inline: auto;
}

/* ---------------------------------------------------------------------------
   The call bar
   A full-width brand strip carrying the phone number on every page. For a trade
   the site's whole job is to make the phone ring, and a visitor is often
   standing outside holding a broken thing — so the number is above the fold on
   every page, not only on Contact.
   --------------------------------------------------------------------------- */

.bp-callbar a {
	font-weight: 700;
	text-decoration: none;
}

.bp-callbar a:hover,
.bp-callbar a:focus-visible {
	text-decoration: underline;
}

/* ---------------------------------------------------------------------------
   Header
   A hairline under the white bar, so the header separates from a pale hero
   without needing a shadow or a second colour.
   --------------------------------------------------------------------------- */

.bp-header {
	border-bottom: 1px solid var(--bp-rule);
}

/*
 * A wordmark logo (theme.logo_wordmark, body class from bp-platform.php). The
 * header's site-logo block is sized for a square mark beside the name; a
 * one-line wordmark at that width would be a few pixels tall. So it is sized
 * by width instead, and the title beside it — the same name again — is hidden
 * visually but kept for screen readers and search engines.
 */
.bp-logo-wordmark .bp-header .wp-block-site-logo img {
	width: clamp(11rem, 42vw, 17rem) !important;
	height: auto !important;
}

.bp-logo-wordmark .bp-header .wp-block-site-title {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

.wp-block-navigation .wp-block-navigation-item__content:hover,
.wp-block-navigation .wp-block-navigation-item__content:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.35em;
}

/*
 * A SUB-MENU OPENS AS A MEGA-MENU: a full-width panel under the header, its
 * children laid out as COLUMNS — the shape of a large retailer's navigation,
 * scaled to a small business's pages. Everything between the panel and the
 * header is made `position: static`, so the header's own full-bleed box is
 * what the panel is placed against: `left: 0; right: 0` with core's
 * `width: auto` stretches it edge to edge, and `top: 100%` puts it on the
 * header's bottom hairline. The columns sit at the page's wide width.
 *
 * A child with children of its own (registry `menu:` `{slug, children}` inside
 * a sub-menu) is a column with a heading: its link in bold, its own links
 * listed under it and always shown while the panel is open — core would hide
 * them behind a second hover. A plain child is a column that is just its link.
 *
 * From 600px only, where the navigation is a row. Below that it is the
 * overlay, which lists every level inline already.
 *
 * The link's ::after is a bridge. Core opens a sub-menu on hover, and the
 * header's bottom padding sits between the item and the panel: without
 * something hoverable across that gap, moving the pointer down to the panel
 * closes it. It hangs under THAT item only — a bridge the width of the panel
 * would lie across the neighbouring items too, and pointing at one of them
 * would hover the open panel's bridge instead of the item.
 */
@media (min-width: 600px) {
	.bp-header {
		position: relative;
	}

	.bp-header .wp-block-navigation,
	.bp-header .wp-block-navigation__responsive-container:not(.is-menu-open),
	.bp-header .wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation__responsive-dialog,
	.bp-header .wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation__responsive-container-content,
	.bp-header .wp-block-navigation__container,
	.bp-header .wp-block-navigation__container > .has-child {
		position: static;
	}

	/* The panel. */
	.bp-header .wp-block-navigation__container > .has-child > .wp-block-navigation__submenu-container {
		left: 0;
		right: 0;
		top: 100%;
		flex-direction: row;
		flex-wrap: wrap;
		align-items: flex-start;
		justify-content: center;
		gap: var(--wp--preset--spacing--40) var(--wp--preset--spacing--70);
		padding: var(--wp--preset--spacing--50) max(var(--wp--preset--spacing--40), calc((100% - var(--wp--style--global--wide-size, 76rem)) / 2));
		background-color: var(--wp--preset--color--surface);
		color: var(--wp--preset--color--ink);
		border: 0;
		border-top: 1px solid var(--bp-rule);
		border-bottom: 1px solid var(--bp-rule);
	}

	/*
	 * Close late, open at once. Core hides a sub-menu the instant the pointer
	 * leaves it, so a hand that overshoots by a few pixels on the way down
	 * loses the whole panel. Here the panel stays laid out (height and width
	 * are never collapsed) and only fades: it waits 250ms before starting to
	 * close — the 200–300ms hover-intent window — and while it is still
	 * visible it is still hoverable, so coming back keeps it open. Opening has
	 * no delay at all.
	 *
	 * The delay is only for leaving the menu. Pointing at ANOTHER top-level
	 * item closes the open panel at once (the :has() rule below), so two
	 * panels never overlap in the same spot and the one under the pointer is
	 * always the one showing.
	 */
	.bp-header .wp-block-navigation__container > .has-child > .wp-block-navigation__submenu-container {
		height: auto;
		width: auto;
		overflow: visible;
		transition: opacity 0.15s ease 0.25s, visibility 0s linear 0.4s;
	}

	.bp-header .wp-block-navigation__container > .has-child:hover > .wp-block-navigation__submenu-container,
	.bp-header .wp-block-navigation__container > .has-child > .wp-block-navigation-submenu__toggle[aria-expanded="true"] ~ .wp-block-navigation__submenu-container {
		transition: opacity 0.15s ease 0s, visibility 0s linear 0s;
	}

	.bp-header .wp-block-navigation__container:has(> .wp-block-navigation-item:hover) > .has-child:not(:hover) > .wp-block-navigation__submenu-container {
		visibility: hidden;
		opacity: 0;
		transition: none;
	}

	/* The arrow turns while the panel is open, so an open menu looks open. */
	.bp-header .wp-block-navigation__container > .has-child > .wp-block-navigation__submenu-icon svg {
		transition: transform 0.15s ease;
	}

	.bp-header .wp-block-navigation__container > .has-child:hover > .wp-block-navigation__submenu-icon svg,
	.bp-header .wp-block-navigation__container > .has-child > .wp-block-navigation__submenu-icon[aria-expanded="true"] svg {
		transform: rotate(180deg);
	}

	.bp-header .wp-block-navigation__container > .has-child > .wp-block-navigation-item__content {
		position: relative;
	}

	/* The bridge: under this item and its arrow, down past the header's edge. */
	.bp-header .wp-block-navigation__container > .has-child > .wp-block-navigation-item__content::after {
		content: "";
		position: absolute;
		top: 100%;
		left: 0;
		right: -1.5em;
		height: calc(var(--wp--preset--spacing--40) + 2rem);
	}

	/* A column. */
	.bp-header .wp-block-navigation__container > .has-child > .wp-block-navigation__submenu-container > .wp-block-navigation-item {
		flex-direction: column;
		align-items: flex-start;
		min-width: 10rem;
	}

	.bp-header .wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
		padding: 0.3em 0;
	}

	/* A column's heading. */
	.bp-header .wp-block-navigation__submenu-container > .has-child > .wp-block-navigation-item__content {
		font-weight: 700;
		padding-bottom: 0.5em;
	}

	/*
	 * A column's links, in flow under the heading. `visibility: inherit`, not
	 * `visible`: a child's visibility overrides its parent's, so `visible`
	 * would leave these showing while the closed panel around them is hidden.
	 */
	.bp-header .wp-block-navigation .wp-block-navigation__submenu-container .has-child > .wp-block-navigation__submenu-container {
		position: static;
		visibility: inherit;
		opacity: 1;
		width: auto;
		min-width: 0;
		height: auto;
		overflow: visible;
		padding: 0;
		border: 0;
		background: transparent;
		color: inherit;
	}

	.bp-header .wp-block-navigation__submenu-container .wp-block-navigation__submenu-icon {
		display: none;
	}
}

/*
 * The mobile overlay inherits the navigation block's own colours, which on a
 * white header means white-on-white once it opens. Core does not solve this for
 * us because it cannot know what the header sits on.
 */
.wp-block-navigation__responsive-container.is-menu-open {
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
}

/*
 * The phone menu is a full-screen overlay, so it is set like one: large type
 * for the top level, a step down for everything under it, and every row a
 * comfortable thumb target. Core sets it at the header's small nav size, which
 * on a full screen reads as a list of footnotes.
 */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	padding-block: 0.4em;
	font-size: var(--wp--preset--font-size--large);
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	font-size: var(--wp--preset--font-size--medium);
}

/* ---------------------------------------------------------------------------
   Cards
   The services row. A border rather than a shadow: it survives a dark brand,
   prints legibly, and does not need a blur radius tuned per palette.
   --------------------------------------------------------------------------- */

.bp-card {
	border: 1px solid var(--bp-rule);
	border-radius: 14px;
	padding: var(--wp--preset--spacing--50);
	/*
	 * No height here. .bp-card is always the column itself, a flex item, and
	 * the row already stretches every column to the tallest one. That only
	 * happens while height is auto: height: 100% has no definite parent height
	 * to resolve against, so it cancels the stretch and each card sizes to its
	 * own content.
	 */
}

/*
 * A card that ends in a button (packages, packages-detail) pins it to the
 * bottom, so a row of equal-height cards has its CTAs on one line whatever the
 * copy above them. Scoped by :has() so cards without a button keep plain flow
 * layout and their spacing is untouched.
 */
.bp-card:has(> .wp-block-buttons) {
	display: flex;
	flex-direction: column;
}

/* Padding, not margin: margin-top is spent on the auto push, so without this
 * the tallest card's last list item sits flush against its button. */
.bp-card > .wp-block-buttons {
	margin-top: auto;
	padding-top: var(--wp--preset--spacing--40);
}

/*
 * Raised — the block style registered in functions.php. A shadow from
 * theme.json's `card` preset in place of the hairline, on a surface ground so
 * it still reads as a card on a bp-tint band. Opt-in per block: the border
 * stays the default, for the reasons at the top of this section.
 */
.is-style-bp-raised {
	background-color: var(--wp--preset--color--surface);
	border-color: transparent;
	border-radius: 8px;
	box-shadow: var(--wp--preset--shadow--card);
}

.is-style-bp-raised:not(.bp-card) {
	padding: var(--wp--preset--spacing--50);
}

/* ---------------------------------------------------------------------------
   Scroll row — the block style registered in functions.php, on Columns and
   Gallery. The carousel people ask for, without the parts of a carousel that
   cost calls: nothing auto-advances, every item is in the page, and a phone
   swipes it natively. The next item peeks in at the edge, which is the whole
   signal that there is more.

   Core's own rules are what these beat: columns force `flex-wrap: wrap` and
   `flex-basis: 100%` under 782px with !important, and gallery images carry a
   :not(#individual-image) width. Each selector here is written to outrank
   the one it replaces, not to win by accident of load order.
   --------------------------------------------------------------------------- */

.wp-block-columns.is-style-bp-scroll,
.wp-block-gallery.has-nested-images.is-style-bp-scroll {
	flex-wrap: nowrap !important;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	scroll-padding-inline: var(--wp--preset--spacing--40);
	padding-bottom: var(--wp--preset--spacing--30);
}

.wp-block-columns.is-style-bp-scroll > .wp-block-column {
	flex: 0 0 min(80%, 22rem) !important;
	scroll-snap-align: start;
}

.wp-block-gallery.has-nested-images.is-style-bp-scroll figure.wp-block-image:not(#individual-image) {
	flex: 0 0 min(80%, 22rem);
	width: min(80%, 22rem);
	scroll-snap-align: start;
}

/* ---------------------------------------------------------------------------
   Questions (the faq pattern)
   core/details, ruled between rows. The marker is replaced by a plus that
   turns to a minus, on the summary's own line, so the whole row is the target
   and not a small triangle.
   --------------------------------------------------------------------------- */

.bp-faq .wp-block-details {
	border-bottom: 1px solid var(--bp-rule);
	padding-block: var(--wp--preset--spacing--40);
}

.bp-faq .wp-block-details:first-child {
	border-top: 1px solid var(--bp-rule);
}

.bp-faq .wp-block-details summary {
	display: flex;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--40);
	cursor: pointer;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 700;
	list-style: none;
}

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

.bp-faq .wp-block-details summary::after {
	content: "+";
	color: var(--wp--preset--color--primary);
	font-weight: 700;
}

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

.bp-faq .wp-block-details > :not(summary) {
	margin-top: var(--wp--preset--spacing--30);
}

/* ---------------------------------------------------------------------------
   Hero
   The cover block's own minHeight is set in markup. What is here is the part a
   client's content can break: an overlong headline on a narrow phone.
   --------------------------------------------------------------------------- */

@media (max-width: 599px) {
	.bp-hero {
		min-height: 26rem !important;
	}
}

/*
 * A hero with a video behind it (hero-video, or hero-photo given a video) plays
 * nothing for a visitor who has asked for reduced motion. The video is hidden
 * and the overlay made solid, so they get the brand panel — not the video's
 * first frame under a 60% scrim, which reads as a broken player.
 */
@media (prefers-reduced-motion: reduce) {
	.bp-hero .wp-block-cover__video-background {
		display: none;
	}

	.bp-hero:has(.wp-block-cover__video-background) .wp-block-cover__background {
		opacity: 1;
	}
}

/* ---------------------------------------------------------------------------
   Footer
   --------------------------------------------------------------------------- */

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

.bp-footer a:hover,
.bp-footer a:focus-visible {
	text-decoration: underline;
}

/*
 * THE DEFAULT FOOTER (parts/footer.html): contact on the left, the site map
 * (patterns/footer-sitemap.php) in columns on the right, and a bar underneath.
 * Every label is small, muted and followed by a hairline that runs to the end
 * of its column — the one device that makes a dozen links read as a layout.
 * Tints are mixed from `surface`, so they follow whatever ink the brand sets.
 */
.bp-footer {
	--bp-footer-muted: var(--wp--preset--color--surface);
	--bp-footer-muted: color-mix(in srgb, var(--wp--preset--color--surface) 62%, transparent);
	--bp-footer-rule: var(--wp--preset--color--muted);
	--bp-footer-rule: color-mix(in srgb, var(--wp--preset--color--surface) 16%, transparent);
}

.bp-footer-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--wp--preset--spacing--70);
}

.bp-footer-grid > *,
.bp-footer-sitemap > *,
.bp-footer-contact > *,
.bp-footer-col > * {
	margin-block: 0;
}

@media (min-width: 782px) {
	.bp-footer-grid {
		grid-template-columns: minmax(14rem, 1fr) 3fr;
		gap: var(--wp--preset--spacing--70) clamp(2.5rem, 6vw, 6rem);
	}
}

.bp-footer-sitemap {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
	gap: var(--wp--preset--spacing--60) var(--wp--preset--spacing--60);
}

.bp-footer .bp-footer-label {
	display: flex;
	align-items: center;
	gap: 0.9rem;
	margin-bottom: var(--wp--preset--spacing--50);
	color: var(--bp-footer-muted);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.3;
}

.bp-footer .bp-footer-label::after {
	content: "";
	flex: 1;
	height: 1px;
	background-color: var(--bp-footer-rule);
}

.bp-footer .bp-footer-label a {
	color: inherit;
}

.bp-footer-links {
	display: grid;
	gap: 0.6rem;
	padding: 0;
	list-style: none;
}

.bp-footer-nav .wp-block-navigation__container {
	gap: 0.6rem;
}

.bp-footer-nav .wp-block-navigation-item__content,
.bp-footer-links a {
	color: var(--wp--preset--color--surface);
	font-family: var(--wp--preset--font-family--body);
	font-size: 1.125rem;
	font-weight: 400;
}

.bp-footer-contact {
	display: grid;
	gap: 0.5rem;
	align-content: start;
}

.bp-footer-contact .bp-footer-label {
	margin-bottom: var(--wp--preset--spacing--30);
}

.bp-footer .bp-footer-phone a {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.5rem;
	font-weight: 700;
	letter-spacing: -0.01em;
}

.bp-footer .bp-footer-address {
	margin-top: var(--wp--preset--spacing--30);
	color: var(--bp-footer-muted);
	font-size: var(--wp--preset--font-size--small);
	max-width: 16rem;
}

.bp-footer-bar {
	margin-top: var(--wp--preset--spacing--80) !important;
	padding-top: var(--wp--preset--spacing--50);
	border-top: 1px solid var(--bp-footer-rule);
	gap: var(--wp--preset--spacing--40) var(--wp--preset--spacing--60);
	color: var(--bp-footer-muted);
}

.bp-footer-bar > * {
	margin-block: 0;
}

.bp-footer-bar a {
	color: var(--wp--preset--color--surface);
}

/*
 * Footer links are small type in a stack, so on a touch screen each one is
 * padded out to a 44px-tall target — the minimum a thumb hits reliably —
 * without changing how they look.
 */
@media (pointer: coarse) {
	.bp-footer .wp-block-navigation-item__content,
	.bp-footer-links a,
	.bp-footer .wp-block-bp-contact a {
		display: inline-block;
		min-height: 44px;
		padding-block: 0.6em;
	}
}

/*
 * No expanding menus in the footer, in any footer variant: it lists the top
 * level only. The footer is the last stop on the page, and a menu that opens
 * there pushes the copyright around or covers it. Every parent is a link to
 * its own page, and the header's menu has the rest.
 */
.bp-footer .wp-block-navigation__submenu-container,
.bp-footer .wp-block-navigation__submenu-icon {
	display: none;
}


/* ---------------------------------------------------------------------------
   Call bar alignment
   The tagline is optional — a tenant with none renders no site-tagline block at
   all, and a lone phone number in a space-between row then lands on the LEFT,
   under the logo, looking like a mistake. `margin-right: auto` on the tagline
   does the work instead of the flex rule: with a tagline it pushes the number
   right, without one the number is the only child and sits right anyway.
   --------------------------------------------------------------------------- */

.bp-callbar .wp-block-group {
	justify-content: flex-end;
	column-gap: var(--wp--preset--spacing--40);
}

.bp-callbar .wp-block-site-tagline {
	margin-right: auto;
	margin-block: 0;
}

/* ---------------------------------------------------------------------------
   A photograph the client has not supplied yet

   The hero and services patterns ship an image block with no image in it, on
   the rule that a plausible stock photo is worse than an obvious gap: stock
   imagery on a local trade reads as a company with nothing to show, and once it
   is there nobody ever replaces it.

   But core's render_block_core_image returns an EMPTY STRING when the <img> has
   no src, so there is no element left to style — a two-column section with one
   empty column collapses to a hole that reads as a broken layout rather than a
   missing photo. Which is what a client sees on their draft, and what they ring
   about.

   So the pattern wraps the image in a slot that survives the image rendering to
   nothing, and the slot takes the shape the photograph will have. Once a
   photograph is uploaded :has(img) matches and every rule here switches off, so
   a live site pays nothing for it.

   :has() and color-mix() above share a browser floor of roughly 2023. Both
   degrade to a flatter design rather than a broken one.
   --------------------------------------------------------------------------- */

.bp-photo-slot:not(:has(img)),
.wp-block-gallery:not(:has(img)) {
	min-height: 20rem;
	background-color: var(--bp-tint);
	border: 1.5px dashed var(--bp-rule);
	border-radius: 12px;
}

/*
 * A picture icon in the middle of an empty slot, so it reads as "a photo
 * goes here" rather than as a grey box. Drawn with a mask so it takes the
 * rule colour, which follows the brand. Gone the moment an image is added.
 */
.bp-photo-slot:not(:has(img)) {
	display: grid;
	place-items: center;
}

.bp-photo-slot:not(:has(img))::before {
	content: "";
	width: 2.25rem;
	height: 2.25rem;
	background-color: var(--wp--preset--color--muted);
	opacity: 0.45;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='16' rx='2.5'/%3E%3Ccircle cx='9' cy='10' r='1.75'/%3E%3Cpath d='m21 16-5-5-9 9'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='16' rx='2.5'/%3E%3Ccircle cx='9' cy='10' r='1.75'/%3E%3Cpath d='m21 16-5-5-9 9'/%3E%3C/svg%3E") center / contain no-repeat;
}

.wp-block-gallery:not(:has(img)) {
	min-height: 14rem;
}

/*
 * The per-service slots in services-detail and services-cards are placeholders
 * too, but in the 4:3 shape their photo will have rather than the 20rem block
 * a hero gets — a card or a row is too small for that to read as a photo.
 */
.bp-card-photo:not(:has(img)),
.bp-service-media .bp-photo-slot:not(:has(img)) {
	min-height: 0;
	aspect-ratio: 4 / 3;
}

.bp-card-photo {
	margin-bottom: var(--wp--preset--spacing--40);
}

/* A package card is one of two or three across, so 4:3 would push its price
 * below the fold. */
.bp-package-photo.bp-photo-slot:not(:has(img)) {
	aspect-ratio: 16 / 9;
}

/* The about story's photo — the owner, the van, the shop front — is 4:3. */
.bp-about-photo.bp-photo-slot:not(:has(img)) {
	min-height: 0;
	aspect-ratio: 4 / 3;
}

/* A person on the team is a 4:5 portrait. */
.bp-portrait-photo.bp-photo-slot:not(:has(img)) {
	min-height: 0;
	aspect-ratio: 4 / 5;
}

/* ---------------------------------------------------------------------------
   Price list rows (price-list, price-list-grouped)

   Read like a shop's search results: a square thumbnail on the left, and
   beside it the name, one muted line and the price, large, as the last thing
   the eye lands on. A hairline between rows and even padding inside them, so a
   long rate card scans as a list and not one run of text. The thumbnail stays
   beside the text on a phone, only smaller — stacking it would turn seven
   services into seven screens.
   --------------------------------------------------------------------------- */

.bp-price-list > .bp-price-item {
	padding-block: var(--wp--preset--spacing--50);
	border-bottom: 1px solid var(--bp-rule);
}

.bp-price-list > .bp-price-item:first-child {
	border-top: 1px solid var(--bp-rule);
}

.bp-price-media {
	flex: 0 0 9rem;
	width: 9rem;
}

.bp-price-media.bp-photo-slot:not(:has(img)) {
	min-height: 0;
	aspect-ratio: 1;
}

.bp-price-media .wp-block-image {
	margin: 0;
}

.bp-price-body {
	flex: 1 1 auto;
	min-width: 0;
}

.bp-price-body > * {
	margin-bottom: 0;
}

/* Lighter than a section's h3, so the price is what carries the row. */
.bp-price-name {
	font-size: 1.1875rem;
	font-weight: 600;
	letter-spacing: 0;
	margin-top: 0;
}

/*
 * A fixed size, not the `large` preset: a brand's type scale can stretch that
 * to 36px for section headings, which is a shout in a row this size.
 */
.bp-price {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.5rem;
	font-weight: 700;
	line-height: 1.2;
}

.bp-price-body > .bp-price {
	margin-top: var(--wp--preset--spacing--30);
}

@media (max-width: 600px) {
	.bp-price-media {
		flex-basis: 6rem;
		width: 6rem;
	}

	.bp-price-name {
		font-size: var(--wp--preset--font-size--medium);
	}

	.bp-price {
		font-size: 1.25rem;
	}
}

/* Rows of services-detail: a hairline between each, none above the first. */
.bp-service-list > .bp-service + .bp-service {
	border-top: 1px solid var(--bp-rule);
}

/* ---------------------------------------------------------------------------
   Food menu (food-menu)

   A printed menu, not a price list: no thumbnails, two columns of items on a
   wide screen, the name and price on one line with the price pushed right,
   and the description under them. Section headings are ruled off so eighty
   items still read as ten groups. The jump row sticks nowhere — a sticky bar
   over a phone's short screen costs more reading room than it saves.
   --------------------------------------------------------------------------- */

.bp-menu-jump a {
	color: inherit;
	text-decoration: none;
}

.bp-menu-section {
	margin-top: var(--wp--preset--spacing--70);
}

.bp-menu-heading {
	padding-bottom: var(--wp--preset--spacing--30);
	border-bottom: 2px solid var(--wp--preset--color--primary);
	/* Reached from the jump row, the heading lands with room above it. */
	scroll-margin-top: var(--wp--preset--spacing--60);
}

.bp-menu-note {
	margin-top: var(--wp--preset--spacing--30);
}

.bp-menu-items {
	display: grid;
	gap: 0 var(--wp--preset--spacing--60);
	margin-top: var(--wp--preset--spacing--40);
}

@media (min-width: 782px) {
	.bp-menu-items {
		grid-template-columns: 1fr 1fr;
	}
}

/*
 * margin-block 0 is the fix for the columns: the items group is a flow layout,
 * which gives every item but the first a top margin — so in a grid the first
 * right-hand item sat lower than its neighbour, and every row after it too.
 */
.bp-menu-items > .bp-menu-item {
	margin-block: 0;
	padding-block: var(--wp--preset--spacing--40);
	border-bottom: 1px solid var(--bp-rule);
}

.bp-menu-item > * {
	margin-block: 0;
}

/* The same weight as a price-list name: the price, not the dish, is bold. */
.bp-menu-name {
	margin: 0;
	font-size: 1.125rem;
	font-weight: 600;
	letter-spacing: 0;
}

.bp-menu-price,
.bp-menu-sizes {
	margin: 0;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 700;
	white-space: nowrap;
}

.bp-menu-sizes {
	white-space: normal;
}

.bp-menu-tags {
	color: var(--wp--preset--color--primary);
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
}

/* Delivery apps (bp/contact `delivery`): outlines in whatever colour the
   section's text is, so they read on a brand band and on the page alike. The
   padding gives back the border's 2px, so an outline button stands exactly as
   tall as the solid Order button in the same row. */
.bp-delivery-app .wp-block-button__link {
	padding: calc(0.85rem - 2px) calc(1.6rem - 2px);
	border: 2px solid currentColor;
	background: transparent;
	color: inherit;
}

.bp-delivery-app .wp-block-button__link:hover,
.bp-delivery-app .wp-block-button__link:focus {
	border-color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--surface);
}

/* ===========================================================================
   COMPONENTS

   The shared pieces the sections are built from. Each is a class on a core
   block (list, group, quote, column), so the client still edits plain blocks
   and a tenant's custom.css can restyle any one of them by name.

   Radii step up with size: 999px chips, 12px photos, 14px cards, 18px for the
   one coupon card that should feel like an object. Colours are all mixed
   from the five palette slugs, so every piece follows the brand.
   =========================================================================== */

:root {
	--bp-radius-card: 14px;
	--bp-soft-primary: var(--bp-tint);
	--bp-soft-primary: color-mix(in srgb, var(--wp--preset--color--primary) 10%, var(--wp--preset--color--surface));
}

/* A lead paragraph under a section heading: bigger than body, never a shout. */
.bp-lead {
	max-width: 40rem;
	margin-inline: auto;
	font-size: 1.1875rem;
	line-height: 1.6;
}

/* Buttons: a touch rounder, and a small lift on hover. */
.wp-element-button,
.wp-block-button__link {
	border-radius: 999px;
	transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

.wp-element-button:hover,
.wp-block-button__link:hover {
	transform: translateY(-1px);
	box-shadow: var(--wp--preset--shadow--card);
}

/* ---------------------------------------------------------------------------
   Chips — brands, payments, service areas, credentials. A list block, so the
   client adds or removes one as a line in the editor.
   --------------------------------------------------------------------------- */

.bp-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.55rem;
	margin-top: var(--wp--preset--spacing--50);
	padding: 0;
	list-style: none;
}

.bp-chips.is-centered {
	justify-content: center;
	max-width: 52rem;
	margin-inline: auto;
}

.bp-chips > li {
	margin: 0;
	padding: 0.5rem 1.05rem;
	border: 1px solid var(--bp-rule);
	border-radius: 999px;
	background-color: var(--wp--preset--color--surface);
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	line-height: 1.3;
}

/* ---------------------------------------------------------------------------
   Card grids — process steps, testimonials, and the team. Core's grid layout
   uses auto-fill, which leaves empty tracks when there are fewer items than
   fit; auto-fit lets three steps share the row instead of stopping short.
   --------------------------------------------------------------------------- */

.wp-block-group.bp-steps.is-layout-grid {
	grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
}

.wp-block-group.bp-quotes.is-layout-grid {
	grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
}

/* People stay a sensible size: a team of two does not become two posters. */
.wp-block-group.bp-people.is-layout-grid {
	grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 16rem));
	justify-content: center;
}

.bp-step,
.bp-panel,
.bp-feature {
	border-radius: var(--bp-radius-card);
	padding: var(--wp--preset--spacing--50);
}

.bp-step {
	border: 1px solid var(--bp-rule);
	background-color: var(--wp--preset--color--surface);
}

.bp-step > *,
.bp-feature > *,
.bp-person > * {
	margin-block: 0;
}

.bp-step-num {
	margin-bottom: var(--wp--preset--spacing--40) !important;
	color: var(--wp--preset--color--primary);
	font-family: var(--wp--preset--font-family--heading);
	font-size: 2.25rem;
	font-weight: 800;
	letter-spacing: -0.03em;
	line-height: 1;
}

.bp-step-title,
.bp-feature h3,
.bp-person-name {
	font-size: 1.25rem;
	letter-spacing: -0.01em;
}

.bp-step-title {
	margin-bottom: var(--wp--preset--spacing--20) !important;
}

/* ---------------------------------------------------------------------------
   Testimonials — a card per quote, a large accent quote mark, and the name
   under it in small type. Overrides theme.json's left-rule quote style.
   --------------------------------------------------------------------------- */

.wp-block-quote.bp-quote-card {
	display: flex;
	flex-direction: column;
	margin: 0;
	padding: var(--wp--preset--spacing--50);
	border: 1px solid var(--bp-rule);
	border-radius: var(--bp-radius-card);
	background-color: var(--wp--preset--color--surface);
}

.wp-block-quote.bp-quote-card::before {
	content: "\201C";
	height: 2.25rem;
	color: var(--wp--preset--color--accent);
	font-family: Georgia, "Times New Roman", serif;
	font-size: 4rem;
	line-height: 1;
}

.wp-block-quote.bp-quote-card p {
	margin: 0;
	font-size: 1.125rem;
	line-height: 1.6;
}

.wp-block-quote.bp-quote-card cite {
	margin-top: auto;
	padding-top: var(--wp--preset--spacing--40);
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	font-style: normal;
	font-weight: 600;
}

/* ---------------------------------------------------------------------------
   Why us — three features on a soft brand tint, each with a check badge.
   --------------------------------------------------------------------------- */

.bp-feature {
	background-color: var(--bp-soft-primary);
}

.bp-feature::before {
	content: "\2713";
	display: grid;
	place-items: center;
	width: 2.5rem;
	height: 2.5rem;
	margin-bottom: var(--wp--preset--spacing--40);
	border-radius: 50%;
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--surface);
	font-weight: 800;
}

.bp-feature > p {
	margin-top: var(--wp--preset--spacing--20);
}

/* ---------------------------------------------------------------------------
   The team — portrait, name, role. No card frame: the photos are the frame.
   --------------------------------------------------------------------------- */

.bp-person-name {
	margin-top: var(--wp--preset--spacing--40) !important;
}

.bp-person .has-small-font-size {
	margin-top: 0.2rem !important;
}

/* ---------------------------------------------------------------------------
   Hours and contact — two surface panels on the tint band. Hours are rows
   with the time pushed right; contact lines are large but not underlined.
   --------------------------------------------------------------------------- */

.bp-panel {
	background-color: var(--wp--preset--color--surface);
	padding: var(--wp--preset--spacing--60);
}

.bp-hours {
	margin-top: var(--wp--preset--spacing--50);
	padding: 0;
	list-style: none;
}

.bp-hours > li {
	display: flex;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--40);
	padding-block: 0.8rem;
	border-bottom: 1px solid var(--bp-rule);
}

.bp-hours > li:first-child {
	border-top: 1px solid var(--bp-rule);
}

.bp-hours > li strong {
	font-weight: 600;
	text-align: right;
}

.bp-contact-line {
	margin: 0;
}

.bp-panel .bp-contact-phone {
	margin-top: var(--wp--preset--spacing--50);
}

.bp-contact-line a {
	text-decoration: none;
}

.bp-contact-line a:hover,
.bp-contact-line a:focus-visible {
	text-decoration: underline;
}

.bp-contact-phone a {
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--heading);
	font-size: clamp(1.5rem, 1.2rem + 1vw, 1.875rem);
	font-weight: 800;
	letter-spacing: -0.02em;
}

.bp-contact-email a {
	font-size: 1.125rem;
	font-weight: 600;
}

.bp-contact-address {
	margin-top: var(--wp--preset--spacing--30) !important;
	color: var(--wp--preset--color--muted);
}

/* ---------------------------------------------------------------------------
   Location — the address with a pin, in brand accent.
   --------------------------------------------------------------------------- */

/* Inline, not flex: a long address wraps under its own centre line with the
 * pin still beside its first word, rather than stranded on the far left. */
.bp-address {
	font-size: 1.25rem;
	font-weight: 600;
}

.bp-address::before {
	content: "";
	display: inline-block;
	width: 1.35rem;
	height: 1.35rem;
	margin-right: 0.45rem;
	vertical-align: -0.2em;
	background-color: var(--wp--preset--color--accent);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a7 7 0 0 0-7 7c0 5.25 7 13 7 13s7-7.75 7-13a7 7 0 0 0-7-7Zm0 9.5A2.5 2.5 0 1 1 12 6.5a2.5 2.5 0 0 1 0 5Z'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a7 7 0 0 0-7 7c0 5.25 7 13 7 13s7-7.75 7-13a7 7 0 0 0-7-7Zm0 9.5A2.5 2.5 0 1 1 12 6.5a2.5 2.5 0 0 1 0 5Z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ---------------------------------------------------------------------------
   Offer — a coupon: a surface card with a dashed accent edge on the tint.
   --------------------------------------------------------------------------- */

.bp-offer-card {
	max-width: 44rem;
	margin-inline: auto;
	padding: var(--wp--preset--spacing--60) var(--wp--preset--spacing--50);
	border: 2px dashed var(--wp--preset--color--accent);
	border: 2px dashed color-mix(in srgb, var(--wp--preset--color--accent) 60%, transparent);
	border-radius: 18px;
	background-color: var(--wp--preset--color--surface);
}

/* ---------------------------------------------------------------------------
   Services with a photo — the list as a two-column checklist.
   --------------------------------------------------------------------------- */

.bp-checklist {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
	gap: 0.7rem var(--wp--preset--spacing--50);
	padding: 0;
	list-style: none;
}

.bp-checklist > li {
	display: flex;
	gap: 0.65rem;
	align-items: baseline;
	margin: 0;
	font-weight: 500;
}

/* An accent asterisk: lighter than a badge, and unmistakably a list mark. */
.bp-checklist > li::before {
	content: "*";
	flex: none;
	color: var(--wp--preset--color--accent);
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.6rem;
	font-weight: 700;
	line-height: 0.8;
	transform: translateY(0.3rem);
}

/* ---------------------------------------------------------------------------
   Before and after — the label as a badge on the photo's corner.
   --------------------------------------------------------------------------- */

.bp-ba {
	position: relative;
}

.bp-ba-label {
	position: absolute;
	top: 0.85rem;
	left: 0.85rem;
	margin: 0;
	padding: 0.3rem 0.8rem;
	border-radius: 999px;
	background-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--surface);
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

/* ---------------------------------------------------------------------------
   Brand bands — the call-to-action strips. A soft light from one corner and
   a shade in the other, mixed from the palette, so a flat block of brand
   colour reads as lit rather than painted.
   --------------------------------------------------------------------------- */

.bp-band {
	background-image:
		radial-gradient(ellipse 60% 90% at 100% 0%, rgba(255, 255, 255, 0.14), transparent 70%),
		radial-gradient(ellipse 50% 80% at 0% 100%, rgba(0, 0, 0, 0.18), transparent 70%);
}

/* ---------------------------------------------------------------------------
   Inside-page title (templates/page.html) — display type in the brand colour.
   --------------------------------------------------------------------------- */

.bp-page-title .wp-block-post-title {
	margin: 0;
	color: var(--wp--preset--color--primary);
	font-size: clamp(2.25rem, 1.7rem + 2.2vw, 3.5rem);
	letter-spacing: -0.04em;
	line-height: 1.02;
}

/* ---------------------------------------------------------------------------
   Process steps as "approach" rows: number and title on the left in the
   accent, the explanation on the right, hairlines between. On a phone the
   row stacks. Overrides the card look set above.
   --------------------------------------------------------------------------- */

.wp-block-group.bp-steps.is-layout-grid {
	grid-template-columns: 1fr;
	gap: 0;
}

.bp-steps > .bp-step {
	display: grid;
	grid-template-columns: 1fr;
	padding: var(--wp--preset--spacing--60) 0;
	border: 0;
	border-top: 1px solid var(--bp-rule);
	border-radius: 0;
	background: none;
}

.bp-steps > .bp-step:last-child {
	border-bottom: 1px solid var(--bp-rule);
}

.bp-steps .bp-step-num {
	margin-bottom: var(--wp--preset--spacing--20) !important;
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: 0;
}

.bp-steps .bp-step-title {
	color: var(--wp--preset--color--accent);
	font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2.125rem);
	font-weight: 600;
	letter-spacing: -0.03em;
	line-height: 1.12;
}

@media (min-width: 782px) {
	.bp-steps > .bp-step {
		grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
		column-gap: var(--wp--preset--spacing--70);
	}

	.bp-steps > .bp-step > :not(.bp-step-num):not(.bp-step-title) {
		grid-column: 2;
		grid-row: 1 / span 2;
		align-self: center;
	}
}

/* ---------------------------------------------------------------------------
   Prices on service cards and rows, and on packages.
   --------------------------------------------------------------------------- */

.bp-service-price {
	color: var(--wp--preset--color--primary);
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 700;
}

.bp-package-price {
	margin-top: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--primary);
	font-family: var(--wp--preset--font-family--heading);
	font-size: clamp(1.75rem, 1.4rem + 1.2vw, 2.375rem);
	font-weight: 800;
	letter-spacing: -0.03em;
	line-height: 1.1;
}

/* ---------------------------------------------------------------------------
   Split sections (why-us): a pill and a statement on the left, a stack of
   points on the right with accent titles and hairlines between. The
   statement is set large and light — it is a sentence, not a label.
   --------------------------------------------------------------------------- */

.bp-statement {
	font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.5rem);
	font-weight: 600;
	letter-spacing: -0.035em;
	line-height: 1.12;
}

.bp-points > .bp-point {
	margin: 0;
	padding-block: var(--wp--preset--spacing--50);
	border-top: 1px solid var(--bp-rule);
}

.bp-points > .bp-point:first-child {
	padding-top: 0;
	border-top: 0;
}

.bp-point > * {
	margin-block: 0;
}

.bp-point > h3 {
	color: var(--wp--preset--color--accent);
	font-size: clamp(1.25rem, 1.05rem + 0.7vw, 1.5rem);
	font-weight: 600;
	letter-spacing: -0.02em;
}

.bp-point > :not(h3) {
	margin-top: var(--wp--preset--spacing--20);
}

@media (max-width: 781px) {
	.bp-points {
		margin-top: var(--wp--preset--spacing--50);
	}
}

/* ===========================================================================
   HEROES

   Four, one job each: hero-photo (one strong photo behind the words),
   hero-video (the same, moving), hero-split (the words beside a photo) and
   hero-statement (the words ARE the design, the photo follows). All four set
   the headline as display type — bp-display — so they read as one family.
   =========================================================================== */

.bp-display {
	font-size: clamp(2.5rem, 1.4rem + 4.4vw, 5rem);
	font-weight: 700;
	letter-spacing: -0.045em;
	line-height: 0.98;
	text-wrap: balance;
}

.bp-hero-intro {
	max-width: 36rem;
	font-size: clamp(1.125rem, 1rem + 0.4vw, 1.3125rem);
	line-height: 1.55;
}

/*
 * Photo and video heroes: the words sit bottom-left at the page's wide edge,
 * over a shade that deepens toward them, so a busy photograph never fights
 * the headline and the top of the picture stays clear.
 */
/* Core pins a positioned cover's content with margin: 0 and width: auto at
 * (0,4,0); this has to outrank it to line the words up with the header. */
.wp-block-cover.bp-hero.has-custom-content-position.is-position-bottom-left .wp-block-cover__inner-container {
	width: 100%;
	max-width: var(--wp--style--global--wide-size, 76rem);
	margin-inline: auto;
}

.bp-hero .wp-block-cover__inner-container > .wp-block-group {
	max-width: 48rem;
	margin-left: 0;
}

.bp-hero .wp-block-cover__inner-container > .wp-block-group > * {
	margin-left: 0 !important;
}

.bp-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(to top, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0) 65%);
	pointer-events: none;
}

.bp-hero .wp-block-cover__inner-container {
	z-index: 2;
}

/* Statement hero: the intro column reads at display scale's side. */
.bp-hero-statement .bp-display {
	font-size: clamp(2.75rem, 1.2rem + 5.6vw, 6rem);
}

.bp-hero-statement p {
	font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);
	line-height: 1.55;
	opacity: 0.92;
}

/* The full-width photo under it: edge to edge, no frame. */
.bp-wide-photo.bp-photo-slot:not(:has(img)) {
	min-height: 0;
	aspect-ratio: 21 / 9;
	border-width: 0;
	border-radius: 0;
}

.bp-wide-photo .wp-block-image {
	margin: 0;
}

.bp-wide-photo img {
	border-radius: 0;
}

/* ---------------------------------------------------------------------------
   Work gallery — a bento grid. The first photo takes a double cell; the rest
   fill in. Two columns on a phone, three from 782px.
   --------------------------------------------------------------------------- */

.wp-block-gallery.has-nested-images.bp-work:has(img) {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	grid-auto-rows: clamp(9rem, 22vw, 17rem);
	grid-auto-flow: dense;
	gap: var(--wp--preset--spacing--40);
}

.wp-block-gallery.has-nested-images.bp-work figure.wp-block-image:not(#individual-image) {
	width: auto;
	height: 100%;
	margin: 0;
}

.wp-block-gallery.has-nested-images.bp-work figure.wp-block-image:first-child {
	grid-column: span 2;
	grid-row: span 2;
}

.wp-block-gallery.has-nested-images.bp-work figure.wp-block-image img {
	height: 100%;
	border-radius: 12px;
	object-fit: cover;
}

@media (min-width: 782px) {
	.wp-block-gallery.has-nested-images.bp-work:has(img) {
		grid-template-columns: repeat(3, 1fr);
	}

	.wp-block-gallery.has-nested-images.bp-work figure.wp-block-image:nth-child(5n + 4) {
		grid-column: span 2;
	}
}

/* ---------------------------------------------------------------------------
   Footer variants in the same language as the standard footer.
   --------------------------------------------------------------------------- */

.bp-footer .has-text-align-center.bp-footer-address {
	max-width: none;
}

/* ===========================================================================
   HEADER — the business name and the main menu, in the same language as the
   rest: a tight wordmark, a lighter menu with room between items, and a dot
   in the accent beside the page you are on.
   =========================================================================== */

/*
 * A fixed scale, not the `large` preset: a brand's type scale can stretch
 * that to 36px, which turns a wordmark into a headline and pushes the menu
 * into a second row on a laptop.
 */
.bp-header .wp-block-site-title {
	font-size: clamp(1.25rem, 1.05rem + 0.7vw, 1.625rem);
	font-weight: 800;
	letter-spacing: -0.035em;
	line-height: 1.1;
}

.bp-header .wp-block-site-title a {
	text-decoration: none;
}

/* The centered header's name is the brand, so it is set larger. */
.bp-header.is-layout-flex.is-vertical .wp-block-site-title {
	font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.5rem);
	text-align: center;
}

.bp-header .wp-block-navigation {
	--navigation-layout-justification-setting: flex-end;
	gap: clamp(1rem, 0.4rem + 1.4vw, 2rem);
	font-size: 0.9375rem;
	font-weight: 500;
}

.bp-header .wp-block-navigation .wp-block-navigation__container {
	gap: clamp(1rem, 0.4rem + 1.4vw, 2rem);
}

/* The page you are on: a small accent dot before its name. */
.bp-header .wp-block-navigation__container > .current-menu-item > .wp-block-navigation-item__content,
.bp-header .wp-block-navigation__container > .current-menu-ancestor > .wp-block-navigation-item__content {
	position: relative;
}

.bp-header .wp-block-navigation__container > .current-menu-item > .wp-block-navigation-item__content::before,
.bp-header .wp-block-navigation__container > .current-menu-ancestor > .wp-block-navigation-item__content::before {
	content: "";
	position: absolute;
	top: 50%;
	left: -0.7em;
	width: 0.35em;
	height: 0.35em;
	border-radius: 50%;
	background-color: var(--wp--preset--color--accent);
	transform: translateY(-50%);
}

/* The call bar reads as a quiet strip, not a second header. */
.bp-callbar {
	font-size: 0.875rem;
}

.bp-callbar .wp-block-site-tagline {
	opacity: 0.85;
}

@media (min-width: 600px) {
	/* The mega-menu panel: lifted off the page, labels muted like the footer's. */
	.bp-header .wp-block-navigation__container > .has-child > .wp-block-navigation__submenu-container {
		border-bottom: 0;
		box-shadow: 0 24px 48px -24px rgba(20, 24, 29, 0.25);
	}

	.bp-header .wp-block-navigation__submenu-container > .has-child > .wp-block-navigation-item__content {
		margin-bottom: 0.35em;
		color: var(--wp--preset--color--muted);
		font-size: 0.8125rem;
		font-weight: 600;
	}

	.bp-header .wp-block-navigation .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
		font-size: 1rem;
		font-weight: 500;
	}
}

/* A button in the header (header-minimal's Call) is sized to the bar, not to
 * a section. */
.bp-header .wp-block-button__link {
	padding: 0.55rem 1.25rem;
	font-size: 0.9375rem;
}

/* ---------------------------------------------------------------------------
   Forms — Contact Form 7, which site_init puts on every site with a form.
   CF7 ships browser-default controls: 40-character boxes, a grey system
   button, and its own green/red/orange notices. Here they take the theme's
   type, palette and button, so a client's brand reaches the form like every
   other block. Scoped to .wpcf7 so nothing else on the site changes.
   --------------------------------------------------------------------------- */

.wpcf7-form > p {
	margin: 0 0 var(--wp--preset--spacing--50);
}

/* CF7 puts a <br> between the label text and its control; the control is a
   block below, so the break only adds a blank line. */
.wpcf7-form label > br {
	display: none;
}

.wpcf7-form label {
	display: block;
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

.wpcf7-form-control-wrap {
	display: block;
	margin-top: 0.4rem;
}

/* Full width of the text column whatever CF7's size/cols attributes say.
   1.0625rem (the medium preset) keeps the text at 17px — under 16px, iOS
   zooms the page on focus. The border is muted at full strength: a field's
   edge needs 3:1 against the page to be found, which --bp-rule is too faint
   to give. */
.wpcf7-form .wpcf7-text,
.wpcf7-form .wpcf7-textarea,
.wpcf7-form .wpcf7-select {
	box-sizing: border-box;
	width: 100%;
	margin: 0;
	padding: 0.8rem 1rem;
	border: 1px solid var(--wp--preset--color--muted);
	border-radius: 8px;
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 400;
	line-height: 1.5;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.wpcf7-form .wpcf7-textarea {
	height: 11rem;
	min-height: 7rem;
	resize: vertical;
}

.wpcf7-form .wpcf7-text:hover,
.wpcf7-form .wpcf7-textarea:hover {
	border-color: var(--wp--preset--color--ink);
}

/* The focus outline itself comes from the :focus-visible rule at the top;
   this also marks the field the visitor clicked into. */
.wpcf7-form .wpcf7-text:focus,
.wpcf7-form .wpcf7-textarea:focus {
	border-color: var(--wp--preset--color--accent);
	box-shadow: 0 0 0 1px var(--wp--preset--color--accent);
	outline: none;
}

.wpcf7-form .wpcf7-text:focus-visible,
.wpcf7-form .wpcf7-textarea:focus-visible {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 2px;
}

/* The submit is an <input>, not a .wp-element-button, so theme.json's button
   styles never reach it. The same values, from the same presets. */
.wpcf7-form .wpcf7-submit {
	padding: 0.85rem 1.6rem;
	border: 0;
	border-radius: 999px;
	background-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--surface);
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	line-height: 1.2;
	cursor: pointer;
	transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

.wpcf7-form .wpcf7-submit:hover,
.wpcf7-form .wpcf7-submit:focus {
	background-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--surface);
	transform: translateY(-1px);
	box-shadow: var(--wp--preset--shadow--card);
}

.wpcf7-form .wpcf7-submit:disabled {
	opacity: 0.6;
	cursor: wait;
	transform: none;
	box-shadow: none;
}

/* Validation and the result line, in the brand instead of CF7's own colours.
   Accent marks what needs fixing; ink frames a success. */
.wpcf7-form .wpcf7-not-valid,
.wpcf7-form .wpcf7-not-valid:hover {
	border-color: var(--wp--preset--color--accent);
}

.wpcf7 .wpcf7-not-valid-tip {
	display: block;
	margin-top: 0.35rem;
	color: var(--wp--preset--color--accent);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

/* CF7's own stylesheet colours each state at .wpcf7 form.<state> .output; these
   match that specificity and come later, so the brand wins. */
.wpcf7 form .wpcf7-response-output,
.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output,
.wpcf7 form.payment-required .wpcf7-response-output,
.wpcf7 form.failed .wpcf7-response-output,
.wpcf7 form.aborted .wpcf7-response-output,
.wpcf7 form.spam .wpcf7-response-output {
	margin: var(--wp--preset--spacing--40) 0 0;
	padding: 0.8rem 1rem;
	border: 1px solid var(--wp--preset--color--accent);
	border-radius: 8px;
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--small);
}

.wpcf7 form.sent .wpcf7-response-output {
	border-color: var(--wp--preset--color--ink);
}
