/*
Theme Name: Next Move Stays
Theme URI: https://nextmovestays.co.uk
Author: Louie Summers
Author URI: https://nextmovestays.co.uk
Description: Custom Full Site Editing block theme for Next Move Stays, a UK B2B corporate accommodation company. Lead generation focused. No page builder, no jQuery, no CSS framework.
Version: 0.28.0
Requires at least: 6.6
Tested up to: 6.8
Requires PHP: 8.2
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: nextmovestays
Tags: full-site-editing, block-patterns, accessibility-ready, business, one-column
*/

/*
 * Design tokens live in theme.json, not here. WordPress turns them into CSS custom
 * properties such as var(--wp--preset--color--brand). Never hardcode a colour, font size
 * or spacing value in this file. `npm run check` fails the build if you do.
 *
 * This file holds what theme.json cannot express: the brand motifs (the gold rule and the
 * eyebrow label taken from the logo), component styling for the homepage patterns, and the
 * scroll reveal.
 *
 * Structure:
 *   1. Accessibility floor
 *   2. Typographic refinements
 *   3. Brand motifs: eyebrow, gold rule
 *   4. Hero
 *   5. Cards, steps, audience tiles
 *   6. FAQ accordion
 *   7. Footer and social icons
 *   8. Motion
 */

/* ==========================================================================
   1. Accessibility floor
   ========================================================================== */

/* Skip link. Visually hidden until focused, so keyboard users can jump past the header. */
.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 999999;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	font-weight: 600;
}

.skip-link:focus {
	left: var(--wp--preset--spacing--30);
	top: var(--wp--preset--spacing--30);
	outline: 3px solid var(--wp--preset--color--brand);
	outline-offset: 2px;
}

/*
 * Visible focus on every interactive element. WCAG 2.4.7. Do not remove, and do not
 * replace with `outline: none`. Two-tone so it stays visible on navy as well as white.
 */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	/*
	 * Brand navy, not brand gold. Gold is 2.92:1 on white and WCAG 2.4.11 needs 3:1 for a
	 * focus indicator, so a gold ring failed on every light section.
	 */
	outline: 3px solid var(--wp--preset--color--brand);
	outline-offset: 3px;
	border-radius: 2px;
}

/* On navy the navy ring would be invisible, so it flips to gold, which is 5.52:1 there. */
.has-brand-background-color :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible,
.has-brand-dark-background-color :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible,
.nms-hero :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline-color: var(--wp--preset--color--accent);
}

/* Images never overflow their container. */
img,
video,
iframe {
	max-width: 100%;
	height: auto;
}

/*
 * No gap between the top-level landmarks. WordPress puts the global blockGap margin
 * between header, main and footer, which painted a white seam between the navy final
 * CTA section and the navy footer. Sections manage their own breathing room with padding.
 */
.wp-site-blocks > * + * {
	margin-block-start: 0;
}

/*
 * The homepage is a real Home page rendered through wp:post-content, so the team can edit
 * its words in wp-admin. Its sections are full-bleed groups, and the flow gap between
 * post-content children would paint the same white seams the rule above removes at the
 * landmark level. Scoped to the front page so ordinary text pages keep normal rhythm.
 */
.home .wp-block-post-content > * + *,
.page .wp-block-post-content > * + * {
	margin-block-start: 0;
}

/*
 * The static page title band (templates/page.html). Navy with the gold hairline on its
 * bottom edge, the same motif as the hero and the footer boundary, so every page opens
 * the way the site does.
 */
.nms-page-header {
	position: relative;
}

.nms-page-header::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-end: 0;
	block-size: 3px;
	background: linear-gradient(
		90deg,
		var(--wp--preset--color--accent) 0%,
		color-mix(in srgb, var(--wp--preset--color--accent) 25%, transparent) 100%
	);
}

/*
 * The GenieAI enquiry form embed.
 *
 * The form itself is an iframe served by leadconnectorhq.com and rendered by the
 * [nms_enquiry_form] shortcode in functions.php. We control the frame around it, nothing
 * inside it: cross origin means no stylesheet of ours reaches the form.
 *
 * The height attribute on the iframe sets the starting height, and GenieAI's form_embed.js
 * then writes the measured height as an inline style. Do NOT set a height here: a
 * stylesheet rule would be overridden by that inline style on desktop and would fight it on
 * mobile, where the form is much taller.
 */
.nms-form-embed {
	margin-block-start: var(--wp--preset--spacing--50);
}

.nms-form-embed__frame {
	display: block;
	inline-size: 100%;
	max-inline-size: 100%;
	border: 0;
}

/*
 * The direct contact route above the form. Always shown, to everyone.
 *
 * It sits ABOVE the iframe on purpose: when the third-party form host is blocked, which a
 * corporate VPN or a tracker blocker does routinely, everything below this line is a blank
 * gap. See the docblock in nextmovestays_enquiry_form_shortcode().
 *
 * The gold is a border only. On this light background brand gold is decorative and must
 * never carry text: see .claude/rules/brand-and-facts.md. The text inherits body colour.
 */
.nms-form-embed__direct {
	margin-block-end: var(--wp--preset--spacing--40);
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background-color: var(--wp--preset--color--base-warm);
	border-inline-start: 3px solid var(--wp--preset--color--accent);
	border-radius: 3px;
	font-size: var(--wp--preset--font-size--small);
}

/* Shown only when JavaScript is off, where the iframe cannot size itself at all. */
.nms-form-embed__fallback {
	padding: var(--wp--preset--spacing--40);
	background-color: var(--wp--preset--color--base-alt);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 3px;
}

/*
 * Legal pages: privacy, cookies, terms.
 *
 * These are the only pages on the site somebody reads top to bottom rather than scans, and
 * the only ones where a wall of text is the correct answer. The job here is rhythm: enough
 * air above each heading that the eye can find the section it wants, and enough between
 * paragraphs that a long clause does not become a slab.
 *
 * WHY THE MEASURE IS CAPPED HERE AND NOT WITH contentSize. Setting the section's
 * contentSize to 740px does cap the width, but WordPress's constrained layout then CENTRES
 * the column, so the body text sat 230px right of the h1 in the navy title band above it,
 * which is 1200px wide and left aligned. Measured, not guessed. The fix is the same one
 * .nms-intro uses for capped paragraphs: the section stays at the site's 1200px, the
 * content sits in a default-layout group, and the cap plus a zeroed inline margin is
 * applied to the children here. Do not "simplify" this back to contentSize.
 */
.nms-legal-page > * {
	max-inline-size: min(72ch, 100%);
	margin-inline: 0;
}

.nms-legal-page > * + * {
	margin-block-start: var(--wp--preset--spacing--30);
}

.nms-legal-page > .wp-block-heading {
	margin-block-start: var(--wp--preset--spacing--60);
}

.nms-legal-page > ul {
	/* Bullets sit outside the measure so the text edge stays flush with the paragraphs. */
	padding-inline-start: var(--wp--preset--spacing--40);
}

.nms-legal-page > ul li + li {
	margin-block-start: var(--wp--preset--spacing--20);
}

/*
 * The last-updated line reuses the eyebrow motif, but an eyebrow normally sits above a
 * heading and this one opens the page under the navy title band, so it needs its own space
 * below rather than the tight coupling the marketing sections want.
 */
.nms-legal-page > .nms-eyebrow {
	margin-block-end: var(--wp--preset--spacing--40);
}

/*
 * GUIDES.
 *
 * The article body. Deliberately NOT .nms-legal-page reused: a legal page is an unbroken
 * run of clauses, while a guide carries pull-out tiles, an ordered checklist and an FAQ,
 * and those need a different vertical rhythm.
 *
 * SAME MEASURE TRICK AS .nms-legal-page, AND FOR THE SAME MEASURED REASON. The section is
 * 1200px and the cap is applied here, because a constrained group at contentSize 740px gets
 * CENTRED and the prose then starts about 230px right of the h1 in the navy band above it.
 * Read the comment above .nms-legal-page before changing any of this.
 *
 * The one difference: an article has a two-column comparison that must run the full width,
 * so .wp-block-columns opts out of the cap rather than breaking out with alignwide, which
 * would do nothing inside a default-layout group.
 */
.nms-article > * {
	max-inline-size: min(72ch, 100%);
	margin-inline: 0;
}

.nms-article > .wp-block-columns {
	max-inline-size: 100%;
}

.nms-article > * + * {
	margin-block-start: var(--wp--preset--spacing--30);
}

/* h2 opens a new part of the argument, h3 is a subdivision of one. Same margin on both
   reads as a flat list of equal sections and loses the structure. */
.nms-article > h2 {
	margin-block-start: var(--wp--preset--spacing--60);
}

.nms-article > h3 {
	margin-block-start: var(--wp--preset--spacing--50);
}

.nms-article > ul,
.nms-article > ol {
	/* Markers sit outside the measure so the text edge stays flush with the paragraphs. */
	padding-inline-start: var(--wp--preset--spacing--40);
}

.nms-article > ul li + li,
.nms-article > ol li + li {
	margin-block-start: var(--wp--preset--spacing--20);
}

.nms-article > .wp-block-columns,
.nms-article > .nms-faq {
	margin-block-start: var(--wp--preset--spacing--50);
}

/*
 * A linked eyebrow, used as the way back up to /guides/ from an article. The eyebrow already
 * carries its own colour on both navy and white, so the link inherits it rather than picking
 * up the global link colour, which would be navy on navy in the article title band.
 */
.nms-eyebrow a {
	color: inherit;
	text-decoration: none;
	text-underline-offset: 0.25em;
}

.nms-eyebrow a:hover,
.nms-eyebrow a:focus-visible {
	text-decoration: underline;
}

/* The guide cards on the index. The card chrome comes from .nms-card. */
.nms-guide-card .wp-block-post-date.nms-eyebrow {
	margin-block-end: var(--wp--preset--spacing--20);
}

.nms-guide-card .wp-block-post-title {
	margin-block: 0;
}

.nms-guide-card .wp-block-post-title a {
	text-decoration: none;
}

.nms-guide-card .wp-block-post-title a:hover,
.nms-guide-card .wp-block-post-title a:focus-visible {
	text-decoration: underline;
}

.nms-guide-card .wp-block-post-excerpt {
	margin-block-start: var(--wp--preset--spacing--30);
}

.nms-guide-card .wp-block-post-excerpt__more-link {
	display: inline-block;
	margin-block-start: var(--wp--preset--spacing--30);
	font-weight: 700;
	color: var(--wp--preset--color--accent-ink);
}

.nms-guide-pagination {
	margin-block-start: var(--wp--preset--spacing--60);
}

/* The date under an article title, inside the navy band. */
.nms-post-meta .wp-block-post-date {
	margin-block: 0;
	opacity: 0.85;
}

/*
 * The support column beside the form. The form runs to well over 2000px, so a static
 * column would leave the reassurance and the phone number stranded at the top while the
 * visitor is halfway down a long form and starting to hesitate. Sticky keeps both in view
 * for the whole scroll.
 *
 * The offset matches the scroll-padding used for in-page anchors: the sticky header
 * measures 131px at its tallest, so 9.5rem clears it, plus the admin bar for logged-in
 * users. Keep the two values in step if the header height ever changes.
 */
.nms-form-aside {
	position: sticky;
	inset-block-start: calc(var(--wp-admin--admin-bar--height, 0px) + 9.5rem);
}

/*
 * Below the columns breakpoint the aside stops being a side and becomes the block after
 * the form, where sticking it would trap it over the content underneath.
 */
@media (max-width: 781px) {
	.nms-form-aside {
		position: static;
	}
}

/* ==========================================================================
   2. Typographic refinements
   ========================================================================== */

/*
 * Headings use a serif stack (see theme.json). A serif head against a sans body reads
 * editorial and considered rather than templated, and costs nothing to load. This is a
 * provisional choice: the company has not supplied a brand typeface yet.
 */
:where(h1, h2, h3, .wp-block-heading) {
	text-wrap: balance;
	letter-spacing: -0.015em;
}

p {
	text-wrap: pretty;
}

/*
 * Long-form paragraphs should not run the full wide width.
 *
 * The margin matters as much as the width. WordPress's constrained layout centres any child
 * narrower than the container, so a capped paragraph drifted into the middle of the section
 * and no longer lined up with the heading above it. Pin the start edge, let the end edge go.
 */
.nms-measure {
	/* min() so the cap never exceeds the space available on a narrow screen. */
	max-inline-size: min(58ch, 100%);
	margin-inline: 0 auto;
}

/*
 * Do NOT try to left-align .nms-measure by fighting the constrained layout. Core centres
 * every direct child of .is-layout-constrained with `margin-inline: auto !important`, so a
 * capped paragraph drifts 384px right of its heading, and zeroing the margin instead throws
 * it out to the container padding edge. Both were measured, not guessed.
 *
 * The structural fix is used instead: each section intro sits inside .nms-intro, a
 * default-layout group. The group is what the constrained layout centres, and inside it
 * normal block flow applies, so a capped paragraph lines up with the heading above it.
 */
.nms-intro > .nms-measure {
	margin-inline: 0;
}

/* ==========================================================================
   3. Brand motifs
   ========================================================================== */

/*
 * The eyebrow: a small caps label above a section heading. Paired with the gold rule it is
 * the signature of this site. On light backgrounds it MUST use accent-ink, because the
 * brand gold is only 2.92:1 on white and fails WCAG AA for text.
 */
.nms-eyebrow {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
	margin-block-end: var(--wp--preset--spacing--30);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--wp--preset--color--accent-ink);
}

/*
 * The gold rule, lifted from the logo, where a gold line flanks the word STAYS. Repeating
 * it is what ties the page back to the mark.
 */
.nms-eyebrow::before {
	content: "";
	inline-size: var(--wp--preset--spacing--50);
	block-size: 2px;
	flex: none;
	background-color: var(--wp--preset--color--accent);
}

/* On navy, the brand gold is 5.52:1 and is the correct colour for the label itself. */
.has-brand-background-color .nms-eyebrow,
.nms-hero .nms-eyebrow {
	color: var(--wp--preset--color--accent);
}

/* A centred rule for section headings that sit in the middle of the page. */
.nms-rule::after {
	content: "";
	display: block;
	inline-size: 64px;
	block-size: 2px;
	margin-block-start: var(--wp--preset--spacing--30);
	background-color: var(--wp--preset--color--accent);
}

.nms-rule.has-text-align-center::after {
	margin-inline: auto;
}

/* ==========================================================================
   4. Hero
   ========================================================================== */

/*
 * Full bleed photograph with a navy scrim. The scrim is what makes white text legible on
 * a photograph: without it, contrast depends on whatever happens to be behind the words.
 * It is a gradient rather than a flat wash so the image still reads as a real room.
 */
.nms-hero {
	position: relative;
	isolation: isolate;
	overflow: hidden;
}

/*
 * The scrim is the core cover block's own overlay (overlayColor brand, dimRatio 80), NOT a
 * pseudo-element of ours. That matters: text legibility must never depend on a CSS override
 * landing correctly. An earlier version used a ::after at a negative z-index and the overlay
 * silently did not paint, leaving white text on a bright photograph.
 *
 * This rule only ENHANCES the flat overlay into a directional gradient, so the photograph
 * stays visible on the right where there is no text. If it fails for any reason, the flat
 * 80 percent navy underneath still protects contrast.
 */
/*
 * The cover block's inner container computed 393.9px inside a 346px content box on a 375px
 * viewport, so the headline, the lead paragraph and the second button were all clipped by
 * the overflow:hidden above. Pin it to the available width so content wraps instead.
 */
.nms-hero .wp-block-cover__inner-container {
	inline-size: 100%;
	max-inline-size: 100%;
	/*
	 * Centre a 1200px content column inside the full-bleed cover, so on a wide monitor
	 * the hero copy lines up with the column every other section uses instead of hugging
	 * the viewport edge. Done with padding, not max-width plus auto margins: the cover
	 * positions this container as a flex item and core zeroes its margins, so an auto
	 * margin never wins. The 100 percent basis stays; it fixed the 375px clipping bug.
	 */
	padding-inline: max(0px, calc((100% - 1200px) / 2));
}

.nms-hero .wp-block-cover__background {
	background-image: linear-gradient(
		100deg,
		var(--wp--preset--color--brand) 0%,
		var(--wp--preset--color--brand) 38%,
		color-mix(in srgb, var(--wp--preset--color--brand) 55%, transparent) 100%
	);
}

/* A hairline of gold along the bottom edge, tying the hero to the brand mark. */
.nms-hero::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-end: 0;
	block-size: 3px;
	z-index: 1;
	background: linear-gradient(
		90deg,
		var(--wp--preset--color--accent) 0%,
		color-mix(in srgb, var(--wp--preset--color--accent) 25%, transparent) 100%
	);
}

/* ==========================================================================
   5. Cards, steps and tiles
   ========================================================================== */

.nms-card {
	block-size: 100%;
	padding: var(--wp--preset--spacing--40);
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 3px;
	transition: transform 220ms ease, box-shadow 220ms ease, border-color 220ms ease;
}

.nms-card:hover,
.nms-card:focus-within {
	transform: translateY(-3px);
	border-color: color-mix(in srgb, var(--wp--preset--color--accent) 55%, transparent);
	box-shadow: 0 10px 30px -12px color-mix(in srgb, var(--wp--preset--color--brand) 35%, transparent);
}

/* Photo cards: the image sits flush to the card edge. */
.nms-card--media {
	padding: 0;
	overflow: hidden;
	background-color: var(--wp--preset--color--base);
}

.nms-card--media .wp-block-image {
	margin: 0;
}

/*
 * The logo patterns render a figure. Core centres a resized image figure with
 * `.wp-block-image.is-resized { margin-inline: auto }`, which pushed the header logo into
 * the middle of the row. The width attribute has been removed from the markup and the size
 * is set here instead, with matching specificity so nothing can re-centre it.
 */
.wp-block-image.nms-brand-logo,
.wp-block-image.nms-brand-logo-reversed {
	margin: 0;
	/*
	 * flex: none and an explicit width matter. As a plain block the figure stretched to the
	 * full row, which pushed the navigation onto its own line and left the logo centred in
	 * the middle of the header.
	 */
	flex: 0 0 auto;
	line-height: 0;
}

.wp-block-image.nms-brand-logo {
	inline-size: 170px;
}

.wp-block-image.nms-brand-logo-reversed {
	inline-size: 220px;
}

.wp-block-image.nms-brand-logo img,
.wp-block-image.nms-brand-logo-reversed img {
	display: block;
	inline-size: 100%;
	block-size: auto;
}

/* ==========================================================================
   5b. Header
   ========================================================================== */

/*
 * Sticky header, so the phone number and the Find Accommodation button stay in reach
 * however far the page scrolls. The offset variable keeps it below the admin bar for
 * logged-in users and is zero for visitors. The header group already has an opaque
 * base background and a bottom border, so nothing shows through.
 */
header.wp-block-template-part {
	position: sticky;
	inset-block-start: var(--wp-admin--admin-bar--height, 0px);
	z-index: 100;
}

/*
 * In-page anchors (#enquiry) must land below the stuck header, not underneath it.
 * The header measures 131px in its tallest state (measured, all verified widths), so
 * 9.5rem (152px) clears it with breathing room.
 */
html {
	scroll-padding-block-start: calc(var(--wp-admin--admin-bar--height, 0px) + 9.5rem);
}

/*
 * The tools cluster: navigation, phone number, call to action. It takes all the row space
 * the logo does not use and keeps its content on the right. flex-grow matters: without it
 * the cluster is sized to its content, and the moment content plus logo exceed the row the
 * cluster wraps to a new line and sits LEFT-aligned under the logo, which looked broken.
 * With it, a wrapped cluster still hugs the right edge and reads as a deliberate second row.
 */
.nms-header__tools {
	flex: 1 1 auto;
	min-inline-size: 0;
}

/*
 * THE HEADER CONTACT BLOCK: phone on top, email beneath it. Added 27 August 2026 at the
 * director's request (REQUESTS row 2).
 *
 * It is a VERTICAL STACK rather than a second item in the header's flex row, and that is
 * the whole design. "hello@nextmovestays.co.uk" is 25 characters; placed beside the phone
 * it added roughly 190px to a row that already had to hide the phone below 1120px, and the
 * header wrapped onto a second line. Stacked, the block is only as wide as the email, the
 * phone sits inside that width for free, and the row keeps its single line.
 *
 * align-items:flex-end because the block sits at the right-hand end of the row: ragged-left
 * text hugging the button reads as deliberate, ragged-right leaves a gap against the button.
 */
.nms-header__contact {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	line-height: 1.25;
	/*
	 * THE GOLD RULE SEPARATES TWO GROUPS, and it is here because of a measurement. The
	 * header's flex gap is 24px, and the gap BETWEEN nav items is also 24px, so with
	 * spacing alone the contact block sat exactly as far from "Contact" as "Contact" sat
	 * from "FAQs". The eye read "Contact 01733 964574" as one run and the phone number
	 * scanned as a seventh menu item.
	 *
	 * The 24px padding here rides on top of the existing 24px gap, so the nav and the
	 * contact block are 48px apart against 24px between nav items: a 2:1 distinction that
	 * still reads if the rule itself is never seen. The rule is therefore reinforcement,
	 * not the only signal, which is the point of WCAG 1.4.1.
	 *
	 * Gold is correct here and is not a text-contrast problem: the brand gold is decorative
	 * only on light backgrounds, and FOUNDATION section 2 lists rules, dividers and
	 * flourishes as exactly its approved decorative job. It carries no meaning of its own
	 * and it rhymes with the gold rule under the logo a few centimetres to the left.
	 */
	border-inline-start: 1px solid var(--wp--preset--color--accent);
	padding-inline-start: var(--wp--preset--spacing--40);
}

/*
 * The two paragraphs are set tight against each other. Core gives a block paragraph a
 * default block margin, which at this size opened a visible gap and made the pair read as
 * two unrelated items rather than one contact block.
 */
.nms-header__contact > p {
	margin-block: 0;
}

/*
 * Bold, brand coloured and already obvious; the underline read as clutter.
 *
 * inline-block plus the block padding lifts each link's hit box to the WCAG 2.2 minimum
 * of 24px (Lighthouse measured the bare line boxes at 22.5px and 18.4px on a touchscreen
 * laptop). Padding on a plain inline element paints a clickable area without reserving
 * room for it, so the two hit boxes would overlap each other instead of separating;
 * inline-block makes the layout honour the padding. The block grows taller but no wider,
 * so the 1194px hide breakpoint is unaffected, and the header row held its measured
 * 130.9px single line at every width from 1195 to 1920: the logo and button govern it.
 */
.nms-header__phone a,
.nms-header__email a {
	display: inline-block;
	padding-block: 3px;
	text-decoration: none;
}

/* The email is a size smaller, so it needs one more pixel each side to clear 24px. */
.nms-header__email a {
	padding-block: 4px;
}

.nms-header__phone a:hover,
.nms-header__phone a:focus-visible,
.nms-header__email a:hover,
.nms-header__email a:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

/*
 * Between the full navigation appearing (600px) and a comfortably wide desktop, there is
 * not enough room for nav, contact block and button beside the logo, so the contact block
 * gives way first. Nothing is lost at any width when it does: the phone is repeated in the
 * hero, the final CTA and the footer, the email is in the footer, and BOTH are in the
 * mobile overlay menu below (.nms-nav-phone and .nms-nav-email).
 *
 * THE BREAKPOINT IS MEASURED, NOT GUESSED, AND IT HAS MOVED TWICE.
 *   1099px, original.
 *   1119px, 25 August 2026, when FAQs became a sixth nav item.
 *   1169px, 27 August 2026, when the email joined the phone in a stacked
 *     .nms-header__contact block. The block was 170px wide against the old phone's 119px.
 *   1194px, 27 August 2026, CURRENT, when the gold rule and its 24px of padding were added
 *     to separate the contact block from the nav. That took the block from 170px to 195px,
 *     so the row needs another 25px. Measured with the hide rule overridden, to find the
 *     true fit point rather than merely where the previous breakpoint happened to hide it:
 *     the header holds its normal 131px single row down to 1195px and wraps to 216px, two
 *     rows, at 1190px.
 *
 * Both earlier moves were made because the header had ALREADY shipped a silent two-row
 * wrap. Re-measure this number in the same phase as anything added to the nav or to the
 * contact block, rather than after somebody notices.
 *
 * It hides the whole .nms-header__contact block, not just .nms-header__phone: hiding only
 * the phone would leave the email alone in the row, which is both odd looking and wider
 * than the thing that was hidden.
 *
 * Ordering matters and is correct: 1194px hides the contact block, then 1099px tightens
 * the nav gap and compacts the button, then 600px shrinks the logo and hands over to the
 * hamburger.
 */
@media (max-width: 1194px) {
	.nms-header__contact {
		display: none;
	}
}

/*
 * The mobile overlay menu. Without this the overlay inherits the header row styling:
 * 14px links pushed to the right edge, which read as footnotes rather than a menu.
 * In the overlay the links become the page: serif, large, left aligned, well spaced.
 */
/*
 * Every selector is prefixed with `header` on purpose: WordPress prints the navigation
 * block's own CSS after this stylesheet, so an equal-specificity rule here silently loses.
 * The extra type selector wins the tie without resorting to !important.
 */
header .wp-block-navigation__responsive-container.is-menu-open {
	padding: var(--wp--preset--spacing--60) var(--wp--preset--spacing--40);
}

/*
 * Core aligns the overlay list with a custom property derived from the block's
 * justifyContent, which is "right" in the header row, and it re-declares that property on
 * the list itself. It is overridden at both levels, and both list shapes are covered: a
 * hand-built menu renders items directly in .wp-block-navigation__container, while the
 * fresh-install fallback nests a .wp-block-page-list inside it.
 */
header .wp-block-navigation__responsive-container.is-menu-open,
header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container,
header .wp-block-navigation__responsive-container.is-menu-open .wp-block-page-list {
	--navigation-layout-justification-setting: flex-start;
	--navigation-layout-justify: flex-start;
	align-items: flex-start;
}

header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
	align-items: flex-start;
}

header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container,
header .wp-block-navigation__responsive-container.is-menu-open .wp-block-page-list {
	gap: var(--wp--preset--spacing--40);
}

header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item a {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 700;
	color: var(--wp--preset--color--brand);
	text-decoration: none;
}

/*
 * The phone number and email live in the navigation purely for the mobile overlay menu:
 * hidden whenever the overlay is closed, so they never appear in the horizontal row (the
 * row has its own .nms-header__phone above, hidden under 1120px in favour of the button).
 * One rule with :not() rather than a hide and show pair, so nothing depends on source
 * order, and when the overlay opens the items fall back to core's own flex styling and
 * lay out identically to their sibling links. Specificity 0,3,1 on purpose: core prints
 * .wp-block-navigation .wp-block-navigation-item { display: flex } after this stylesheet.
 */
header .wp-block-navigation__responsive-container:not(.is-menu-open) .nms-nav-phone,
header .wp-block-navigation__responsive-container:not(.is-menu-open) .nms-nav-email {
	display: none;
}

/*
 * The email address is 25 characters of serif at the overlay's x-large size, which
 * overflows a 375px screen. One size down keeps it on a single tappable line.
 */
header .wp-block-navigation__responsive-container.is-menu-open .nms-nav-email a {
	font-size: var(--wp--preset--font-size--large);
}

/*
 * Mid widths, roughly tablet: the full navigation is visible (the hamburger only takes
 * over at 600px) but the row is too narrow for nav, button and generous gaps. Tighten the
 * nav gap and compact the button so they share one row instead of stacking three high.
 * Raised from 900px to 1099px on 25 August 2026 when FAQs joined the menu: at the old
 * breakpoint the sixth item wrapped the header onto two rows between 901 and 1099px,
 * measured 183px against the normal 98px.
 */
@media (max-width: 1099px) {
	header.wp-block-template-part .wp-block-navigation .wp-block-navigation__container,
	header.wp-block-template-part .wp-block-navigation .wp-block-page-list {
		gap: var(--wp--preset--spacing--30);
	}

	.nms-header__tools .wp-block-button__link {
		padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
		font-size: var(--wp--preset--font-size--small);
	}
}

/* Below the header breakpoint the logo shrinks rather than forcing a wrap. */
@media (max-width: 600px) {
	.wp-block-image.nms-brand-logo {
		inline-size: 100px;
	}

	/* Keep logo, menu toggle and call to action on one 375px row. */
	header.wp-block-template-part .wp-block-group.alignwide,
	header.wp-block-template-part .nms-header__tools {
		gap: var(--wp--preset--spacing--20);
	}

	.nms-header__tools .wp-block-button__link {
		padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--20);
	}
}

.nms-card--media .wp-block-image img {
	inline-size: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	display: block;
	transition: transform 500ms ease;
}

.nms-card--media:hover .wp-block-image img {
	transform: scale(1.04);
}

.nms-card--media .nms-card__body {
	padding: var(--wp--preset--spacing--40);
}

/*
 * Numbered process steps. The number is a large ghosted serif numeral rather than a filled
 * circle: quieter, and it matches the serif headings.
 */
.nms-step {
	position: relative;
	padding-block-start: var(--wp--preset--spacing--40);
	border-block-start: 2px solid var(--wp--preset--color--border);
}

/*
 * The step number is REAL block content, not a CSS ::before with attr(). A custom data
 * attribute on a core block fails WordPress block validation, and the editor then offers to
 * discard the markup. Keeping it as a paragraph also means the CEO can edit it.
 */
/*
 * Step headings sit in a five column row, so they get very little width. At the large size
 * the serif broke mid-word ("requiremen t"). Cap the size and forbid mid-word breaks.
 */
.nms-step .wp-block-heading {
	font-size: var(--wp--preset--font-size--medium);
	overflow-wrap: normal;
	word-break: normal;
	hyphens: none;
	text-wrap: balance;
}

.nms-step__number {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--xx-large);
	line-height: 1;
	font-weight: 700;
	/*
	 * accent-ink, not accent. The step numbers are content, not decoration, and they sit on
	 * white, where the brand gold is only 2.92:1. accent-ink is 4.97:1.
	 */
	color: var(--wp--preset--color--accent-ink);
	margin-block-end: var(--wp--preset--spacing--20);
}

/* On a navy section the brand gold is correct and reads better. */
.has-brand-background-color .nms-step__number {
	color: var(--wp--preset--color--accent);
}

/* On navy sections the step rule and numeral shift to work on the dark ground. */
.has-brand-background-color .nms-step {
	border-block-start-color: color-mix(in srgb, var(--wp--preset--color--base) 28%, transparent);
}

/* Audience tiles: a compact list of who we help. */
.nms-tile {
	block-size: 100%;
	padding: var(--wp--preset--spacing--40);
	background-color: var(--wp--preset--color--base-warm);
	border-inline-start: 3px solid var(--wp--preset--color--accent);
	border-radius: 0 3px 3px 0;
}

/*
 * The talk-it-through card in the final CTA. Without it the block floated in the navy with
 * nothing anchoring it: no edge, no fill, centred against a taller neighbour. A soft border
 * and a slightly lifted navy fill give it weight, and the gold top rule ties it to the
 * eyebrow motif used everywhere else.
 */
.nms-cta-card {
	padding: var(--wp--preset--spacing--50);
	/*
	 * 4 percent white, not more. The gold links inside sit at 5.52:1 on pure navy and AA
	 * needs 4.5:1; at a 7 percent lift they measured 4.58:1, which passes with no margin.
	 * At 4 percent they measure just under 5:1.
	 */
	background-color: color-mix(in srgb, var(--wp--preset--color--base) 4%, var(--wp--preset--color--brand));
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--base) 22%, transparent);
	border-block-start: 2px solid color-mix(in srgb, var(--wp--preset--color--accent) 80%, transparent);
	border-radius: 3px;
}

/* The CARE promise blocks, shown on navy. */
.nms-care {
	block-size: 100%;
	padding-block-start: var(--wp--preset--spacing--40);
	border-block-start: 2px solid color-mix(in srgb, var(--wp--preset--color--accent) 70%, transparent);
}

.nms-care__letter {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--xx-large);
	line-height: 1;
	color: var(--wp--preset--color--accent);
}

/* A quiet stat or proof point in the trust strip. */
.nms-proof {
	padding-block: var(--wp--preset--spacing--20);
}

/*
 * Tabular figures on the headline line, because count-up.js animates the numbers and
 * proportional digits would make the line width jiggle on every frame. Applied always,
 * not just mid-animation: on these short lines the difference is invisible and a static
 * rule cannot race the script.
 */
.nms-proof > p:first-child {
	font-variant-numeric: tabular-nums;
}

.nms-proof__label {
	display: block;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-soft);
}

/* ==========================================================================
   6. FAQ accordion
   ========================================================================== */

/*
 * Styling the CORE DETAILS BLOCK (.wp-block-details), which renders real details and
 * summary elements. No JavaScript, keyboard accessible for free, editable by a
 * non-developer, and the answers stay in the page source so search engines and Rank Math
 * FAQ schema can read them.
 */
.nms-faq {
	border-block-end: 1px solid var(--wp--preset--color--border);
}

.nms-faq summary {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--40);
	padding-block: var(--wp--preset--spacing--40);
	cursor: pointer;
	list-style: none;
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 700;
	color: var(--wp--preset--color--brand);
	transition: color 160ms ease;
}

.nms-faq summary::-webkit-details-marker {
	display: none;
}

.nms-faq summary:hover {
	color: var(--wp--preset--color--accent-ink);
}

/* The plus and minus indicator, drawn in CSS so there is no icon file to load. */
.nms-faq summary::after {
	content: "";
	flex: none;
	inline-size: 14px;
	block-size: 14px;
	margin-block-start: 0.4em;
	background:
		linear-gradient(var(--wp--preset--color--accent-ink) 0 0) center / 100% 2px no-repeat,
		linear-gradient(var(--wp--preset--color--accent-ink) 0 0) center / 2px 100% no-repeat;
	transition: transform 240ms ease;
}

.nms-faq[open] summary::after {
	transform: rotate(90deg);
	background:
		linear-gradient(var(--wp--preset--color--accent-ink) 0 0) center / 100% 2px no-repeat;
}

.nms-faq__answer {
	padding-block-end: var(--wp--preset--spacing--40);
	max-width: 68ch;
}

/* ==========================================================================
   6b. Links on dark sections
   ========================================================================== */

/*
 * theme.json sets the global link colour to brand navy, which is correct on white and
 * INVISIBLE on the navy sections: measured at rgb(4,30,79) text on rgb(4,30,79) background,
 * a contrast ratio of 1:1. The footer phone number and email address had disappeared
 * completely.
 *
 * Gold on navy is 5.52:1 and passes AA. Underlined by default so the link is identifiable
 * without relying on colour alone, which is WCAG 1.4.1.
 */
/*
 * .nms-cta-card IS IN THIS LIST, added 27 August 2026, and it has to be. The card paints
 * its own navy background in CSS but carries no has-brand-background-color class, so the
 * rule above it never matched. Every card until now happened to sit inside a navy section
 * and inherited the colour from the section; the Guest Help page put one on a WHITE section
 * and its phone number and email rendered navy on navy at 1.3:1. That is the footer bug of
 * 19 August wearing a different coat, and it was found by measuring the page, not by a gate.
 * Key the colour off the surface that actually paints the background.
 */
.has-brand-background-color a:where(:not(.wp-element-button):not(.wp-block-button__link)),
.has-brand-dark-background-color a:where(:not(.wp-element-button):not(.wp-block-button__link)),
.nms-cta-card a:where(:not(.wp-element-button):not(.wp-block-button__link)),
.nms-hero a:where(:not(.wp-element-button):not(.wp-block-button__link)) {
	color: var(--wp--preset--color--accent);
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.has-brand-background-color a:where(:not(.wp-element-button):not(.wp-block-button__link)):hover,
.has-brand-dark-background-color a:where(:not(.wp-element-button):not(.wp-block-button__link)):hover,
.nms-cta-card a:where(:not(.wp-element-button):not(.wp-block-button__link)):hover,
.nms-hero a:where(:not(.wp-element-button):not(.wp-block-button__link)):hover {
	color: var(--wp--preset--color--base);
}

/* ==========================================================================
   7. Footer and social icons
   ========================================================================== */

/*
 * The footer boundary. The final CTA and the footer are both brand navy, and with the
 * blockGap seam removed they read as one unbroken slab. This hairline marks where the
 * footer starts. It mirrors the gold hairline on the hero's bottom edge, so the page
 * opens and closes on the same motif.
 */
.nms-footer {
	position: relative;
}

.nms-footer::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-start: 0;
	block-size: 3px;
	background: linear-gradient(
		90deg,
		var(--wp--preset--color--accent) 0%,
		color-mix(in srgb, var(--wp--preset--color--accent) 25%, transparent) 100%
	);
}

/*
 * The social row is a flex list that wraps, so adding a sixth or seventh network later is
 * a copy and paste of one list item with no layout work. Deliberately built to grow.
 */
.nms-social {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--30);
	/*
	 * The block-start margin is deliberate: this list lives in a raw HTML block, so the
	 * layout blockGap does not reach it, and a bare margin: 0 left the icons pressed
	 * against the text above.
	 */
	margin: var(--wp--preset--spacing--40) 0 0;
	padding: 0;
	list-style: none;
}

.nms-social__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	inline-size: 44px;
	block-size: 44px;
	border-radius: 50%;
	color: var(--wp--preset--color--base);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--base) 35%, transparent);
	transition: background-color 200ms ease, border-color 200ms ease, transform 200ms ease;
}

/* 44px is the WCAG 2.2 target size minimum, so these stay comfortably tappable. */
.nms-social__link:hover {
	background-color: var(--wp--preset--color--accent);
	border-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--brand);
	transform: translateY(-2px);
}

.nms-social__link svg {
	inline-size: 20px;
	block-size: 20px;
	fill: currentColor;
	display: block;
}

/*
 * Footer navigation links. The global rule for links on navy makes inline links gold and
 * underlined, which is right for links inside sentences (the phone number and email), but
 * a stack of underlined menu items read as clutter. Menu links are white and quiet, and
 * announce themselves on hover the same way the rest of the site does.
 */
.has-brand-background-color .wp-block-navigation a {
	color: var(--wp--preset--color--base);
	text-decoration: none;
}

.has-brand-background-color .wp-block-navigation a:hover {
	color: var(--wp--preset--color--accent);
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

/* The vertical footer menu sits tighter than the default block gap. */
.has-brand-background-color .wp-block-navigation.is-vertical .wp-block-navigation__container {
	gap: var(--wp--preset--spacing--30);
}

/* Footer column headings sit quieter than page headings. */
.nms-footer__heading {
	font-size: var(--wp--preset--font-size--medium);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--accent);
}

/* The legal line: smaller and softer, but still AA against navy. */
.nms-legal {
	font-size: var(--wp--preset--font-size--small);
	color: color-mix(in srgb, var(--wp--preset--color--base) 78%, var(--wp--preset--color--brand));
}

/* ==========================================================================
   7b. Cookie consent banner (inc/consent.php, assets/js/consent.js)
   ========================================================================== */

/*
 * A region pinned to the bottom of the viewport, not a modal: the page stays usable
 * behind it and nothing is dimmed. Navy on white with the gold hairline the site uses
 * everywhere, so it reads as part of the site rather than a third-party overlay. All
 * colours are tokens; the checker verifies the pairings.
 */
.nms-consent {
	position: fixed;
	inset-inline: 0;
	inset-block-end: 0;
	z-index: 200;
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	border-block-start: 3px solid var(--wp--preset--color--accent);
	box-shadow: 0 -8px 24px color-mix(in srgb, var(--wp--preset--color--brand) 12%, transparent);
	padding-block: var(--wp--preset--spacing--40);
	padding-inline: var(--wp--preset--spacing--40);
}

.nms-consent[hidden] {
	display: none;
}

.nms-consent__inner {
	max-width: 1200px;
	margin-inline: auto;
	display: grid;
	gap: var(--wp--preset--spacing--30);
}

.nms-consent__heading {
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--brand);
	margin: 0;
}

/*
 * The heading receives focus programmatically when the banner opens (tabindex="-1"). It
 * keeps the site-wide :focus-visible ring on purpose: focus styling is never removed.
 */
.nms-consent__text {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	max-width: 70ch;
}

.nms-consent__summary {
	cursor: pointer;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--brand);
	text-decoration: underline;
	text-underline-offset: 0.15em;
	width: fit-content;
}

.nms-consent__options {
	display: grid;
	gap: var(--wp--preset--spacing--20);
	margin-block-start: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--small);
}

.nms-consent__option {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: var(--wp--preset--spacing--20);
	align-items: start;
	max-width: 70ch;
}

.nms-consent__option input {
	margin-block-start: 0.35em;
	accent-color: var(--wp--preset--color--brand);
}

.nms-consent__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
}

/* Equal weight for accept and refuse: the refuse button is navy outline, not a text link. */
.nms-consent__button--secondary {
	background: transparent;
	color: var(--wp--preset--color--brand);
	border: 2px solid var(--wp--preset--color--brand);
}

.nms-consent__button--secondary:hover,
.nms-consent__button--secondary:focus-visible {
	background: var(--wp--preset--color--base-warm);
	color: var(--wp--preset--color--brand-dark);
}

@media (min-width: 782px) {
	.nms-consent__inner {
		grid-template-columns: 1fr auto;
		grid-template-areas:
			"heading actions"
			"text actions"
			"details actions";
		column-gap: var(--wp--preset--spacing--60);
		align-items: center;
	}

	.nms-consent__heading { grid-area: heading; }
	.nms-consent__text { grid-area: text; }
	.nms-consent__details { grid-area: details; }
	.nms-consent__actions { grid-area: actions; flex-direction: column; align-items: stretch; }
}

/* ==========================================================================
   8. Motion
   ========================================================================== */

/*
 * Scroll reveal using a scroll-driven animation. No JavaScript and no layout thrash.
 * Wrapped in @supports so that in a browser without animation-timeline the content is
 * simply visible from the start, which is the correct fallback: never hide content behind
 * an effect the browser cannot run.
 */
@supports (animation-timeline: view()) {
	@media (prefers-reduced-motion: no-preference) and (min-width: 782px) {
		.nms-reveal {
			animation: nms-fade-up linear both;
			animation-timeline: view();
			/*
			 * The range finishes while the section is still ENTERING the viewport, so a
			 * section has settled before the reader can properly read it. The animation
			 * moves transform only (see the keyframes below), so even at range start the
			 * content is fully visible and at full contrast; the tight range is kept
			 * because an 18px offset lingering across the whole entry reads as lag, not
			 * polish.
			 */
			animation-range: entry 0% entry 55%;
		}
	}
}

/* Printing and PDF export never run scroll-driven animations. Force everything visible. */
@media print {
	.nms-reveal {
		animation: none !important;
		opacity: 1 !important;
		transform: none !important;
	}
}

/*
 * Transform only, no opacity, since 2 September 2026. The reveal used to fade from 0.15
 * as well as rise, and the fade made every automated contrast audit report failures that
 * were not real: the checker samples mid-animation, reads the text part-blended towards
 * the background, and the six false findings buried the one genuine one. No opacity
 * floor can fix that, because accent-ink text starts at 4.97:1 and any blend at all
 * drops it under the 4.5 threshold. Moving only the position keeps the motion, keeps
 * text at full contrast at every instant a tool or a slow device could sample it, and
 * makes an unscrolled snapshot (crawler, print, full-page screenshot) show every section
 * complete. The keyframe name stays nms-fade-up so nothing else needs to know.
 */
@keyframes nms-fade-up {
	from {
		transform: translateY(18px);
	}
	to {
		transform: none;
	}
}

/* Buttons get a small lift, which reads as responsive without being playful. */
.wp-block-button__link {
	transition: transform 180ms ease, background-color 180ms ease, box-shadow 180ms ease;
}

.wp-block-button__link:hover {
	transform: translateY(-2px);
	box-shadow: 0 8px 20px -10px color-mix(in srgb, var(--wp--preset--color--brand) 60%, transparent);
}

/* The gold accent button: navy text on gold is 5.52:1 and passes AA. */
.nms-button-accent .wp-block-button__link {
	background-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--brand);
}

.nms-button-accent .wp-block-button__link:hover {
	background-color: color-mix(in srgb, var(--wp--preset--color--accent) 82%, var(--wp--preset--color--base));
}

/* Outline button, for the secondary call to action on navy. */
.nms-button-outline .wp-block-button__link {
	background-color: transparent;
	color: var(--wp--preset--color--base);
	box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--wp--preset--color--base) 70%, transparent);
}

.nms-button-outline .wp-block-button__link:hover {
	background-color: color-mix(in srgb, var(--wp--preset--color--base) 14%, transparent);
	box-shadow: inset 0 0 0 2px var(--wp--preset--color--base);
}

/* Respect a reduced motion preference. */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}

	.nms-card:hover,
	.nms-card--media:hover .wp-block-image img,
	.wp-block-button__link:hover,
	.nms-social__link:hover {
		transform: none;
	}
}
