/*
 * NMC brand layer.
 * Loaded AFTER the HTML5 UP template stylesheet so it wins on specificity ties.
 * Template files stay unedited where possible — override here instead.
 */

/* --- Type ----------------------------------------------------------------
 * Archivo, self-hosted. Google serves this as a single variable file spanning
 * the whole 100–900 weight axis, so one 35 KB request covers every weight the
 * site uses — Spectral asks for 400 (body), 600 (strong, buttons) and 800
 * (headings). Shipping three static cuts would cost more bytes, not fewer.
 *
 * The range below is the file's real axis, verified against its fvar table.
 * This replaces the Open Sans @import that Spectral had in main.css; nothing
 * here touches fonts.googleapis.com or fonts.gstatic.com at runtime.
 *
 * No italic face is shipped: neither page uses em, i or blockquote. If real
 * italic content arrives, add the Archivo italic variable file rather than
 * leaving the browser to synthesise a slant. See CLAUDE.md.
 */

@font-face {
	font-family: 'Archivo';
	src: url('../fonts/archivo-latin-var.woff2') format('woff2');
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
}

:root {
	/* Palette */
	--nmc-deep-teal: #0E2E33;
	--nmc-teal:      #2A7E76;
	--nmc-bone:      #E8E2D6;
	--nmc-copper:    #B8654A;

	/* =========================================================
	 * HERO IMAGE SETTINGS — EDIT THESE
	 * ========================================================= */
	--hero-image:        url('../../images/josh.jpg');
	--hero-tint-color:   #0E2E33;
	--hero-tint-opacity: 0.75;

	/* =========================================================
	 * PHILOSOPHY PULSE — ON/OFF SWITCH
	 *
	 *   nmc-signal  the Sense / Signal / Strengthen diamonds pulse
	 *   none        they do not
	 *
	 * This is the whole switch; nothing else needs touching. It feeds
	 * animation-name, so `none` simply leaves no animation to run. The
	 * copper rule and teal wash on the diamonds are set by separate
	 * rules and are NOT affected — turn the pulse off and the icons
	 * keep exactly the look they have at rest.
	 *
	 * Full explanation in README.md at the repo root.
	 * ========================================================= */
	--nmc-pulse: nmc-signal;

	/* Semantic roles — reference these in site CSS, not the raw palette names */
	--nmc-bg:            var(--nmc-bone);
	--nmc-bg-inverse:    var(--nmc-deep-teal);
	--nmc-text:          var(--nmc-deep-teal);
	--nmc-text-inverse:  var(--nmc-bone);
	--nmc-accent:        var(--nmc-copper);
	--nmc-link:          var(--nmc-teal);

	/* Type — @font-face is at the top of this file. One family throughout;
	 * display and body stay separate variables so they can diverge later. */
	--nmc-font-display-family: 'Archivo', Helvetica, Arial, sans-serif;
	--nmc-font-body-family:    'Archivo', Helvetica, Arial, sans-serif;

	--nmc-font-display: var(--nmc-font-display-family, Georgia, serif);
	--nmc-font-body:    var(--nmc-font-body-family, system-ui, sans-serif);

	/* Spacing scale */
	--nmc-space-xs: 0.5rem;
	--nmc-space-sm: 1rem;
	--nmc-space-md: 1.5rem;
	--nmc-space-lg: 3rem;
	--nmc-space-xl: 5rem;

	--nmc-measure: 34rem; /* readable line length cap */
}

body {
	background: var(--nmc-bg);
	color: var(--nmc-text);
}

/* Mirrors the selector main.css uses for the body font, so form controls pick
 * up Archivo too — they do not inherit it. Kept apart from the rule above so
 * the ground and ink colours are not pushed onto inputs, which the band rules
 * handle separately. */
body,
input,
select,
textarea,
button {
	font-family: var(--nmc-font-body);
}

h1, h2, h3, h4, h5, h6 {
	font-family: var(--nmc-font-display);
}

h1, h2, h3, h4 {
	color: var(--nmc-deep-teal);
}

a {
	color: var(--nmc-link);
}

/* --- Logo lockup ---------------------------------------------------------
 * The mark is ALWAYS the two-part lockup: "NMC" over "Neuromuscular
 * Communication". Never render the initials on their own. Both parts live in
 * the markup so the full name is available to search engines and screen
 * readers; see CLAUDE.md.
 */

.nmc-logo {
	display: inline-block;
	text-decoration: none;
	line-height: 1.1;
}

.nmc-logo__mark {
	display: block;
	font-family: var(--nmc-font-display);
	font-size: 2rem;
	letter-spacing: 0.08em;
	color: var(--nmc-deep-teal);
}

.nmc-logo__name {
	display: block;
	font-size: 0.7rem;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--nmc-teal);
}

/* Lockup on a dark ground */
.nmc-logo--inverse .nmc-logo__mark { color: var(--nmc-bone); }
.nmc-logo--inverse .nmc-logo__name { color: var(--nmc-bone); opacity: 0.85; }

/* --- Philosophy strip ----------------------------------------------------
 * "Sense. Signal. Strengthen." — set as three items, not one sentence, so the
 * cadence survives reflow on narrow viewports.
 */

.nmc-philosophy {
	display: flex;
	flex-direction: column;
	gap: var(--nmc-space-xs);
	margin: 0;
	padding: 0;
	list-style: none;
	font-family: var(--nmc-font-display);
	letter-spacing: 0.04em;
}

.nmc-philosophy li::after {
	content: ".";
	color: var(--nmc-copper);
}

/* Mobile first: single column by default, widen upward only. */
@media (min-width: 40em) {
	.nmc-philosophy {
		flex-direction: row;
		gap: var(--nmc-space-md);
	}
}

/* --- Alternating section grounds -----------------------------------------
 * Spectral's bands, in reading order:
 *
 *   1  #banner               deep teal   (parallax photo, tinted)
 *   2  #philosophy           bone
 *   3  #services .spotlight  deep teal   (all four, see below)
 *   4  #about                bone
 *   5  #contact              deep teal   (parallax photo, tinted)
 *   6  #footer               deep teal
 *
 * The four spotlights in #services are one continuous deep teal block, not an
 * alternation. Each carries a photograph at half the band width, so flipping
 * the ground under them broke the run of images into disconnected cards; on
 * one ground they read as a single section of work. They still alternate
 * which side the image sits on — that is main.css's :nth-child(2n)
 * row-reverse, which is layout, not colour, and is left alone.
 *
 * The footer is deep teal on BOTH the landing page and the interior pages, so
 * the site closes the same way wherever you are. On the landing page that puts
 * it under the deep teal CTA, but the CTA is a tinted window onto the fixed
 * photograph while the footer is flat colour, so the seam still reads.
 *
 * Story could be swept with a single nth-child because every section was a
 * direct child of one wrapper. Spectral cannot: the bands sit at two DOM
 * depths, a fixed nav sits outside the rhythm, and two bands are transparent
 * windows onto a fixed photograph. So the sequence is assigned by name.
 *
 * Each band declares its ground and ink as custom properties and everything
 * inside reads those, so the flip is expressed once rather than duplicated
 * for the light and dark case.
 *
 * Both pairings are the measured 11.2:1. Note what is NOT used: teal on deep
 * teal is 2.98:1 and fails outright, so links on the dark ground take the ink
 * colour and let copper carry the affordance as an underline.
 */

#banner,
#contact,
#header,
#menu,
#footer,
#services .spotlight {
	--nmc-section-bg:    var(--nmc-bg-inverse);
	--nmc-section-fg:    var(--nmc-text-inverse);
	--nmc-section-rule:  rgba(232, 226, 214, 0.25);
	--nmc-section-muted: rgba(232, 226, 214, 0.72);
	--nmc-section-field: rgba(232, 226, 214, 0.45);
}

#philosophy,
#about {
	--nmc-section-bg:    var(--nmc-bg);
	--nmc-section-fg:    var(--nmc-text);
	--nmc-section-rule:  rgba(14, 46, 51, 0.2);
	--nmc-section-muted: rgba(14, 46, 51, 0.72);
	--nmc-section-field: rgba(14, 46, 51, 0.45);
}

/* Solid bands. The footer is listed three times on purpose, because the
 * template sets its ground at three different specificities and each has to
 * be matched or the bone never lands:
 *   #footer                        interior pages, no .landing class
 *   body.landing #footer           the landing page          (1,1,1)
 *   body.is-mobile.landing #footer phones — main.js adds is-mobile at <=980px
 *                                  and this outranks both of the above (1,2,1)
 * Missing the last one left the footer on its stock near-black ground with
 * deep teal icons on top, i.e. invisible. */
#philosophy,
#about,
#header,
#menu,
#services .spotlight,
#footer,
body.landing #footer,
body.is-mobile.landing #footer {
	background-color: var(--nmc-section-bg);
	color: var(--nmc-section-fg);
}

/* The two parallax bands stay transparent so the fixed photograph still shows
 * through; their ground is the tinted overlay on #page-wrapper below. */
#banner,
#contact {
	background-color: transparent;
	color: var(--nmc-section-fg);
}

/* Spectral tints the fixed photograph with 50% black; this is deep teal at
 * 0.80, chosen to let the photograph read. Measured against the worst case —
 * a fully white area of the photograph under the tint — bone text over this
 * is 5.92:1, comfortably AA. Going darker buys headroom (0.88 is 7.72:1 and
 * AAA) at the cost of hiding the image; do not go lighter, as 0.70 drops to
 * 4.28:1 and fails for anything but large text.
 *
 * The colour underneath matters: the photograph is background-attachment:
 * fixed, so it only ever paints across the viewport. Without a deep teal
 * ground beneath it, any band the fixed layer does not reach falls through to
 * the bone body background — which would leave the CTA bone text on bone. */
body.landing #page-wrapper {
	background-color: var(--nmc-bg-inverse);
	background-image:
		linear-gradient(
			rgb(from var(--hero-tint-color) r g b / var(--hero-tint-opacity)),
			rgb(from var(--hero-tint-color) r g b / var(--hero-tint-opacity))
		),
		var(--hero-image);
}

/* On mobile the template drops the fixed layer and paints the photograph onto
 * the two bands directly, so they need the same tint. */
body.is-mobile.landing #banner,
body.is-mobile.landing .wrapper.style4 {
	background-color: var(--nmc-bg-inverse);
	background-image:
		linear-gradient(
			rgb(from var(--hero-tint-color) r g b / var(--hero-tint-opacity)),
			rgb(from var(--hero-tint-color) r g b / var(--hero-tint-opacity))
		),
		var(--hero-image);
}

/* Headings and body copy follow the band's ink. */
#banner :is(h1, h2, h3, h4, h5, h6),
#philosophy :is(h1, h2, h3, h4, h5, h6),
#about :is(h1, h2, h3, h4, h5, h6),
#contact :is(h1, h2, h3, h4, h5, h6),
#footer :is(h1, h2, h3, h4, h5, h6),
#services .spotlight :is(h1, h2, h3, h4, h5, h6) {
	color: var(--nmc-section-fg);
}

/* Spectral sets section intros in a half-opacity white that disappears on the
 * bone ground; this restates them as a muted version of the band's own ink. */
#philosophy header p,
#about header p,
#contact header p,
#services .spotlight header p {
	color: var(--nmc-section-muted);
}

/* The rule under a .major header. */
#philosophy header.major :is(h1, h2, h3, h4, h5, h6),
#about header.major :is(h1, h2, h3, h4, h5, h6),
#services .spotlight header.major :is(h1, h2, h3, h4, h5, h6) {
	border-color: var(--nmc-section-rule);
}

/* Links take the ink colour so they hold full contrast on either ground;
 * copper carries the affordance as an underline, which keeps copper to accent
 * duty rather than making it the text colour. */
#banner a:not(.button),
#philosophy a:not(.button),
#about a:not(.button),
#contact a:not(.button),
#services .spotlight a:not(.button) {
	color: var(--nmc-section-fg);
	text-decoration-color: var(--nmc-accent);
	text-underline-offset: 0.2em;
}

/* The credit link sits at the same size and muted colour as the copyright it
 * follows, so it reads as a footnote rather than a call to action. Measured
 * at 5.15:1 on bone — AA at this size. It only lifts to full ink on hover.
 *
 * text-transform is reset because the template uppercases the whole line,
 * which mangles a brand name — DenMotion is not DENMOTION. The surrounding
 * copyright text keeps the uppercase treatment. */
#footer .copyright a {
	color: inherit;
	text-transform: none;
	text-decoration-color: var(--nmc-accent);
	text-underline-offset: 0.2em;
}

#footer .copyright a:hover {
	color: var(--nmc-section-fg);
}

/* --- Banner height -------------------------------------------------------
 * Spectral abandons its full-screen hero below 736px — its own rule sets
 * `height: auto; min-height: 0`, which is why the banner was filling exactly
 * half a 844px phone screen. This restores full height at every width.
 *
 * Deliberately NOT in a media query. The template's rule lives inside a
 * max-width block, so an unconditional #banner here — same specificity, later
 * source — beats it on phones while changing nothing on desktop, where 100vh
 * was already in force. A min-width query would leave the mobile case alone,
 * and the mobile case is the one being fixed.
 *
 * svh, not vh: on iOS 100vh is the LARGE viewport, measured as if the browser
 * chrome were hidden. A 100vh hero is therefore taller than what you can
 * actually see, pushing the button below the fold until you scroll. 100svh is
 * the visible area with the chrome showing. vh stays first as the fallback.
 */

#banner {
	height: 100vh;
	height: 100svh;
	min-height: 35em;
}

/* --- Banner headline weight ----------------------------------------------
 * The logo artwork is drawn in Archivo Regular (400) — verified by matching
 * its NMC against the variable font at each weight. Spectral sets every
 * heading to 800, so the same three letters appeared at 400 in the corner and
 * 800 in the middle of the hero, which read as an inconsistency rather than a
 * hierarchy.
 *
 * 600 rather than 400: it closes most of the gap to the mark while keeping
 * the headline dominant over the strapline beneath it. Scoped to the banner,
 * so section headings elsewhere keep the template's 800.
 */

#banner h2 {
	font-weight: 600;
}

/* --- Banner rhythm -------------------------------------------------------
 * The template gives the headline and the strapline different bottom margins,
 * so the two gaps came out at 18px and 29px — visibly lopsided on a phone,
 * where the three items sit close together. One value for both.
 *
 * The trailing margin under the actions list goes too. It is invisible, but
 * it makes the content BOX taller than what you can see, so flex centring
 * balanced the box while the visible block sat off centre.
 */

#banner .inner h2,
#banner .inner p {
	margin-bottom: var(--nmc-space-md);
}

#banner .inner ul.actions {
	margin-bottom: 0;
}

/* The template's mobile banner padding is 7em top against 5em bottom. That
 * asymmetry was harmless when the banner was auto-height, but now that it is
 * full-screen and centring its content, it pushed the block 11px below the
 * middle. Same total, split evenly. Horizontal padding is left alone. */
#banner {
	padding-block: 6em;
}

/* Below 480px the template stretches every actions button to width:100%.
 * That suits a stacked list of equal choices, but in the banner it made the
 * single call to action as wide as the strapline above it — much heavier than
 * the desktop treatment. Sized to its label here instead, matching desktop.
 *
 * Scoped to the banner deliberately: the contact form's submit keeps the
 * full-width behaviour, where a large tap target is worth having. */
#banner ul.actions:not(.fixed) li .button {
	width: auto;
}

/* Spectral also hides the scroll cue below 736px. That was reasonable for an
 * auto-height banner, but a full-screen one with nothing peeking below it is
 * a false bottom — the page looks like it ends here. Restoring the cue is
 * part of making the change above work, not a separate decision. */
#banner .more {
	display: block;
}

/* The pair of rules that draw in above and below the banner headline on load.
 * Copper, matching the divider in the lockup — this is exactly the accent's
 * job: rules and marks, never text. It measures 3.43:1 on the deep teal,
 * which clears the 3:1 floor for non-text, and the headline itself is
 * unaffected at 11.2:1. The template's width transition is left alone. */
/* The page-load fade. #banner:after is a full-banner veil that sits at opacity
 * 1 while body.is-preload is on and fades to 0 over 3s once main.js drops the
 * class — that IS the fade-in on load. The template paints it in its stock
 * slate #2e3842, which lifts as a grey haze that belongs to no palette here.
 * Deep teal instead, matching the tint over the photograph, so the hero reads
 * as emerging from its own ground rather than from behind a dust sheet. */
#banner:after {
	background: var(--nmc-bg-inverse);
}

#banner h2:before,
#banner h2:after {
	background: var(--nmc-accent);
}

/* --- Buttons -------------------------------------------------------------
 * Outlined buttons carry the band's ink. The primary button fills with that
 * ink and reverses the label, which is the same 11.2:1 pairing read the other
 * way — copper is not used as a fill, since deep teal on copper is only
 * 3.43:1 and that is large-text territory, not a button label.
 */

#banner .button,
#philosophy .button,
#about .button,
#contact .button,
#services .spotlight .button {
	box-shadow: inset 0 0 0 2px var(--nmc-section-fg);
	color: var(--nmc-section-fg) !important;
}

#banner .button:hover,
#philosophy .button:hover,
#about .button:hover,
#contact .button:hover,
#services .spotlight .button:hover {
	background-color: var(--nmc-section-rule);
}

#banner .button.primary,
#philosophy .button.primary,
#about .button.primary,
#contact .button.primary,
#services .spotlight .button.primary {
	background-color: var(--nmc-section-fg) !important;
	color: var(--nmc-section-bg) !important;
	box-shadow: none !important;
}

/* The primary button on a parallax band: --nmc-section-bg is the deep teal
 * the overlay paints, so the label reads against the bone fill. */
#banner .button.primary:hover,
#contact .button.primary:hover {
	background-color: var(--nmc-bone) !important;
	color: var(--nmc-deep-teal) !important;
}

/* --- Contact form --------------------------------------------------------
 * Scoped to .nmc-form, not #contact, because the form is moved into the booking
 * dialog when that opens and has to keep its styling there. The band custom
 * properties it reads are set by whichever container it currently sits in —
 * #contact or .nmc-modal, both dark.
 *
 * Spectral gives inputs a translucent grey fill and `border: none`. Measured
 * on the deep teal ground that fill is 1.45:1 against it — well under the 3:1
 * WCAG 1.4.11 floor for a UI component boundary, so the fields were near
 * invisible. They get a real edge here at 3.44:1. Text inside was never the
 * problem: bone on the fill is 7.73:1.
 */

.nmc-form label {
	color: var(--nmc-section-fg);
}

.nmc-form .nmc-optional {
	font-weight: 400;
	color: var(--nmc-section-muted);
}

/* Spectral's field styles list text, password, email, select and textarea —
 * but not tel, which did not exist as a type when the template was written.
 * Without this the phone field falls back to the browser default: a plain
 * white box at its own intrinsic width. These are Spectral's own values,
 * repeated for tel only. */
.nmc-form input[type="tel"] {
	appearance: none;
	-webkit-appearance: none;
	background-color: rgba(144, 144, 144, 0.25);
	border-radius: 3px;
	display: block;
	outline: 0;
	padding: 0 1em;
	text-decoration: none;
	width: 100%;
	height: 2.75em;
}

.nmc-form input[type="text"],
.nmc-form input[type="email"],
.nmc-form input[type="tel"],
.nmc-form select,
.nmc-form textarea {
	border: 1px solid var(--nmc-section-field);
	color: var(--nmc-section-fg);
}

/* Spectral's focus ring is its stock cyan. Copper is the brand's accent and
 * still clears the non-text floor at 3.43:1 on this ground. */
.nmc-form input[type="text"]:focus,
.nmc-form input[type="email"]:focus,
.nmc-form input[type="tel"]:focus,
.nmc-form select:focus,
.nmc-form textarea:focus {
	border-color: var(--nmc-accent);
	box-shadow: 0 0 0 1px var(--nmc-accent);
}

.nmc-form ::placeholder {
	color: var(--nmc-section-muted);
	opacity: 1;
}

/* The submit is an <input>, so it misses the .button rules above; Spectral's
 * .primary fill is its stock red-orange. Bone fill, deep teal label — the
 * same 11.2:1 pairing read the other way. */
.nmc-form input[type="submit"] {
	background-color: var(--nmc-section-fg) !important;
	color: var(--nmc-section-bg) !important;
	box-shadow: none !important;
}

.nmc-form input[type="submit"]:hover {
	background-color: var(--nmc-bone) !important;
	color: var(--nmc-deep-teal) !important;
}

/* Held while the request is in flight, so the button has to read as
 * unavailable without going invisible on the dark ground. */
.nmc-form input[type="submit"]:disabled {
	opacity: 0.55;
	cursor: default;
}

/* The status line nmc.js writes after a submit. It is created by the script,
 * so :empty never matches in practice — the rule is there so the element
 * cannot leave a gap if a future change appends it before there is a message.
 *
 * The state is carried by a copper rule down the side, not by coloured text:
 * copper is 3.23:1 on bone and 3.43:1 on this deep teal, which clears the 3:1
 * floor for a non-text indicator but not the 4.5:1 one for body copy. So the
 * words stay bone at 11.2:1 and the accent does affordance duty only — the
 * same division the focus ring above uses.
 *
 * That means colour is never the only channel: the message itself says which
 * state it is, which is what WCAG 1.4.1 asks for. */
.nmc-form-status {
	margin: var(--nmc-space-sm) 0 0 0;
	padding-left: var(--nmc-space-sm);
	border-left: 2px solid var(--nmc-section-muted);
	color: var(--nmc-section-fg);
	font-size: 0.9em;
	line-height: 1.6;
	max-width: var(--nmc-measure);
}

.nmc-form-status:empty {
	display: none;
}

.nmc-form-status.is-pending {
	color: var(--nmc-section-muted);
}

.nmc-form-status.is-ok {
	border-left-color: var(--nmc-section-fg);
}

.nmc-form-status.is-error {
	border-left-color: var(--nmc-accent);
}

/* --- Booking dialog ------------------------------------------------------
 * A native <dialog> opened with showModal(), which gives the focus trap,
 * Escape-to-close, the inert background and the ::backdrop for free. Hand
 * rolling those is where most modals get accessibility wrong.
 *
 * The form is not duplicated here — assets/js/nmc.js moves the one in #contact
 * into this dialog on open and puts it back on close. Two copies would mean
 * duplicate ids and two elements with the same field names.
 *
 * The dark band variables are repeated because the dialog sits outside every
 * section, so it inherits no band context and the form would otherwise render
 * with no ground and unreadable text.
 */

/* The dialog itself is a transparent, full-viewport SCROLL CONTAINER; the
 * visible panel is .nmc-modal__inner inside it. Sizing the dialog to the panel
 * pinned it dead centre with no give — once it fitted the viewport there was
 * nothing to scroll, and anything taller (landscape, larger text settings) got
 * clipped. As a scroller with margin:auto on the panel, it centres when it
 * fits and scrolls whenever it does not, with nothing ever cut off.
 */
.nmc-modal {
	--nmc-section-bg:    var(--nmc-bg-inverse);
	--nmc-section-fg:    var(--nmc-text-inverse);
	--nmc-section-rule:  rgba(232, 226, 214, 0.25);
	--nmc-section-muted: rgba(232, 226, 214, 0.72);
	--nmc-section-field: rgba(232, 226, 214, 0.45);

	width: 100%;
	max-width: none;
	height: 100%;
	max-height: none;
	margin: 0;
	padding: var(--nmc-space-md) var(--nmc-space-sm);
	border: 0;
	background: transparent;
	color: var(--nmc-section-fg);
	overflow-y: auto;
	overscroll-behavior: contain;
}

/* Only when open — the UA rule display:none on a closed dialog has to keep
 * winning, or the dialog would be visible before it is opened. */
.nmc-modal[open] {
	display: flex;
}

/* nmc.js focuses the dialog on open so the phone keyboard stays down. That
 * focus draws the browser's default ring — the bright blue box. The dialog is
 * a container, not a control, and was never focused by the user's own action,
 * so suppressing it loses nothing: every real control inside still shows its
 * own copper focus ring. */
.nmc-modal:focus,
.nmc-modal:focus-visible {
	outline: none;
}

/* margin:auto rather than align-items:center — centring a flex item taller
 * than its scroll container clips the top and makes it unreachable. */
.nmc-modal__inner {
	width: min(38rem, 100%);
	margin: auto;
	background: var(--nmc-section-bg);
	border-radius: 4px;
	box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.45);
}

.nmc-modal::backdrop {
	background: rgba(14, 46, 51, 0.72);
}

/* Fade both the panel and the dimmed page in. allow-discrete lets the
 * transition run against display, which <dialog> toggles. Browsers without
 * it just get the open state immediately, which is fine. */
@media (prefers-reduced-motion: no-preference) {
	.nmc-modal,
	.nmc-modal::backdrop {
		opacity: 0;
		transition: opacity 0.25s ease, display 0.25s allow-discrete,
		            overlay 0.25s allow-discrete;
	}

	.nmc-modal[open],
	.nmc-modal[open]::backdrop {
		opacity: 1;
	}

	@starting-style {
		.nmc-modal[open],
		.nmc-modal[open]::backdrop {
			opacity: 0;
		}
	}
}

.nmc-modal__inner {
	padding: var(--nmc-space-md);
}

/* No longer needed: the scroll container fills the viewport and the panel
 * sizes itself, so nothing caps its height. */

/* Tightening for the dialog only — the same form inline in #contact keeps the
 * template's roomier spacing. Between these and the shorter textarea the
 * panel fits a 640px-tall phone without scrolling. */
.nmc-modal .nmc-form label {
	margin-bottom: 0.35em;
}

.nmc-modal .nmc-form textarea {
	height: 5.5em;
}

/* Below 480px the grid stacks every field full width, which made the dialog
 * taller than a 640px phone — the send button fell off the bottom. The two
 * optional short fields share a row inside the dialog instead. Name and email
 * stay full width, where a cramped field would actually hurt. The same form
 * inline in #contact is untouched, since this is scoped to .nmc-modal. */
.nmc-modal .nmc-pair {
	width: 50%;
}

.nmc-modal__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--nmc-space-sm);
	margin-bottom: var(--nmc-space-sm);
}

.nmc-modal__title {
	color: var(--nmc-section-fg);
	margin: 0;
}

/* A real button, so it is keyboard reachable and announced. 44px square is
 * the minimum comfortable touch target. */
/* Deliberately quiet: no border or fill, and the same muted ink as the
 * "(optional)" hints, so it reads as a dismissal rather than an action
 * competing with Send. Still a 44px target — the box is invisible, not
 * small. It brightens to full ink on hover and focus. */
.nmc-modal__close {
	flex-shrink: 0;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	/* Spectral styles every <button> element as one of its buttons, and draws
	 * the outline with an inset box-shadow rather than a border — so border:0
	 * alone left a white ring around the X. */
	box-shadow: none !important;
	background: transparent;
	color: var(--nmc-section-muted);
	font-size: 1rem;
	line-height: 1;
	cursor: pointer;
	transition: color 0.15s ease;
}

.nmc-modal__close:hover {
	color: var(--nmc-section-fg);
}

.nmc-modal__close:focus-visible {
	outline: 2px solid var(--nmc-accent);
	outline-offset: 2px;
}

/* Everything below the moved-in form: the WhatsApp fallback on the left, the
 * follow links on the right, under one hairline. Grouping them is the point —
 * both are "other ways to reach or follow", and giving them a rule of their own
 * keeps them from reading as a stray appendix to the submit row.
 *
 * Wraps rather than crushes: on a narrow dialog the icons drop below the line
 * and the row gap separates them. */
.nmc-modal__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--nmc-space-sm);
	margin-top: var(--nmc-space-md);
	padding-top: var(--nmc-space-md);
	border-top: 1px solid var(--nmc-section-rule);
}

/* The rule above now owns the spacing, so the paragraph's own top margin would
 * only push it off centre from the icons beside it. */
.nmc-modal__foot .nmc-alt-contact {
	margin: 0;
}

/* showModal() makes the background inert but does not stop it scrolling
 * behind the dialog on every browser. nmc.js sets this while open. */
body.nmc-modal-open {
	overflow: hidden;
}

/* --- #contact layout ---------------------------------------------------------
 * Two columns: the intro on the left, the form on the right. This is what the
 * template's own #contact flex was for — it just sized the second column at 30%,
 * which fits a pair of buttons but not a form. Widening the inner from 45em
 * to 60em (matching every other section) and splitting 45/55 takes the band
 * from 973px to roughly 570px, so it no longer overruns the viewport.
 *
 * Mobile first: stacked by default, two columns only from 981px. That value
 * is the top of Spectral's `medium` breakpoint — above it the template's own
 * max-width rules have stopped applying, so nothing fights this. A plain
 * `display: flex` with no query would beat the template's stacking rule at
 * every width, because it wins on source order inside their media query.
 */

#contact .inner {
	display: block;
}

#contact .nmc-form {
	margin-top: var(--nmc-space-md);
}

@media (min-width: 981px) {
	#contact .inner {
		display: flex;
		align-items: flex-start;
		max-width: 60em;
	}

	/* Both orders are set explicitly. The template puts order:1 on the header
	 * for its buttons-on-the-right layout; the form would otherwise default to
	 * order:0 and sort ahead of it, putting the fields on the left. */
	#contact .inner > header {
		order: 1;
		width: 45%;
		flex-shrink: 0;
		padding-right: var(--nmc-space-lg);
	}

	#contact .nmc-form {
		order: 2;
		width: 55%;
		margin-top: 0;
	}
}

/* Not scoped to #contact: the same line appears beside the form in #contact AND inside
 * the booking dialog, and both grounds are deep teal, so one rule serves both.
 * It reads --nmc-section-* either way — #contact gets them from the band lists, the
 * dialog declares its own because it sits outside every section. */
.nmc-alt-contact {
	margin-top: var(--nmc-space-md);
	color: var(--nmc-section-muted);
	font-size: 0.9em;
}

.nmc-alt-contact a {
	color: var(--nmc-section-fg);
}

/* Visually hidden but still rendered and still submitted — the honeypot has
 * to stay in the layout, because bots skip display:none and hidden inputs.
 * Absolute positioning also keeps it out of the .row grid flow. */
.nmc-visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* --- Icons ---------------------------------------------------------------
 * Spectral colours these with its stock cyan/blue accents, which fail against
 * both NMC grounds. The circled icons take the band's ink; the small feature
 * icons take copper, which is accent duty and never carries the text itself.
 */

#philosophy .icon.major,
#about .icon.major {
	border-color: var(--nmc-section-rule);
	color: var(--nmc-section-fg);
}

#philosophy .icon.style1,
#philosophy .icon.style2,
#philosophy .icon.style3 {
	color: var(--nmc-section-fg);
}

#about .features li:before {
	color: var(--nmc-accent);
}

/* --- Icon captions -------------------------------------------------------
 * Spectral hides every .icon > .label as screen-reader-only text. In #philosophy
 * those three words ARE the philosophy line, so they are shown — but only for
 * .icons.major, which keeps the footer's social labels and the #about feature
 * icons hidden as the template intends.
 *
 * .icon.major is a square rotated -45deg into a diamond, and a transform makes
 * that element the containing block for anything absolutely positioned inside
 * it — so the caption cannot be hung off the <li>, it has to be placed from
 * within the rotated frame. It is counter-rotated 45deg to sit upright, then
 * anchored at the local point that maps to dead centre below the diamond:
 * with the parent at -45deg, a local offset of (-k, +k) from the box centre
 * lands at (0, k√2) on screen. Keep left and top mirrored about 50% if the gap
 * is ever retuned, or the caption drifts sideways.
 *
 * Colour is the band's own ink, not bone: #philosophy is a BONE ground (see the band
 * lists above), so bone text would be invisible on it. This is the same value
 * the .icon.style1/2/3 rule above already gives the icons themselves.
 *
 * font-size resolves against .icon.major's own 1.35em, so the caption tracks
 * the template's ≤736px step down to 1em without a max-width query of its own.
 * At both sizes the 9em box is narrower than the gap between icon centres, so
 * neighbouring captions cannot collide.
 */

.icons.major .icon > .label {
	display: block;
	position: absolute;
	left: -20%;
	top: 120%;
	width: 9em;
	transform: translate(-50%, -50%) rotate(45deg);
	font-size: 0.5em;
	font-weight: 600;
	letter-spacing: 0.12em;
	line-height: 1.2;
	text-align: center;
	text-transform: uppercase;
	white-space: nowrap;
	color: var(--nmc-section-fg);
}

/* The diamond is √2 times taller than its layout box and already overhangs the
 * li; the caption is out of flow and adds no height at all. This makes room for
 * both, replacing the bottom half of the template's `padding: 1em 0`. */
ul.icons.major {
	padding-bottom: 2.75em;
}

/* --- Philosophy diamonds --------------------------------------------------
 * Sense / Signal / Strengthen. Two things going on here, and the first has to
 * stand up alone because the second may never run.
 *
 * RESTING STATE. Spectral's .icon.major is an outline only, and at
 * --nmc-section-rule (deep teal at 0.2 on #philosophy's bone) that outline barely
 * registered — full-strength glyphs floating in nothing. So the diamond gets a
 * ground of its own: teal at 0.08, which is a tint rather than a fill, plus the
 * border promoted from the hairline rule to copper. Copper as a rule is exactly
 * its sanctioned accent duty and never carries text; the glyph inside stays
 * --nmc-section-fg at the measured 11.2:1.
 *
 * Scoped to #philosophy .icons.major so it cannot reach the .icon list items in
 * #about, which are a different treatment entirely.
 *
 * THE PULSE. The three words are a sequence, not a set, so the glow travels —
 * Sense, then Signal, then Strengthen, one third of a cycle apart — and then
 * repeats, so it reads as a signal running the chain continuously rather than
 * as three things blinking together.
 *
 * It is keyed off .is-revealed, which nmc.js puts on #philosophy .inner when the
 * section scrolls into view, so this inherits that script's guarantees for
 * free: no JS, no IntersectionObserver, or reduced-motion requested means the
 * class never lands, the animation never runs, and the resting state above is
 * what you get. Nothing here hides anything, so there is no blank-page failure
 * mode to protect against.
 *
 * WHAT PULSES IS THE LINE, NOT A HALO. The first attempt blurred a box-shadow
 * by 1.5em. On a diamond only ~65px across that is a 40px blur — wider than
 * the corners, so it bled past them and read as a soft circle sitting behind
 * the mark rather than as the mark itself lighting up. Blur has to stay small
 * RELATIVE TO THE BOX to hold an edge. Everything here is in em precisely so
 * that ratio survives the template's step down to 1em under 736px.
 *
 * So ::after restates the 2px copper rule exactly on top of the real one and
 * fades in and out. The effect is the copper line brightening and dimming,
 * with the light coming off the line itself.
 *
 * The glow is in two stops rather than one, which is what makes it vivid
 * without going back to a blob: a near-opaque core at 0.18em sits hard on the
 * line and does the brightening, and a softer 0.6em falloff carries the light
 * outward. One wide blur at high alpha would just re-round the corners — the
 * intensity has to go into the tight stop, not the wide one. A third, inset,
 * throws a little of it back inside the diamond so the line reads as lit from
 * both sides rather than edged.
 *
 * WHY A PSEUDO-ELEMENT. Animating border-color or box-shadow repaints the
 * element every frame. That was acceptable when the bloom fired once; running
 * forever it is a permanent repaint next to body copy, on phones included. On
 * ::after the border and both glows are STATIC and only OPACITY animates,
 * which the compositor handles without repainting. ::before is not available —
 * that is where Font Awesome puts the glyph.
 *
 * The base border underneath stays full copper, so the floor of the cycle is
 * the resting state exactly as it appears with no JS: the line never drops
 * below solid, it only lifts above it.
 *
 * 3.6s is deliberately slow: 0.28Hz, nowhere near the >3Hz flash threshold,
 * and slow enough to sit at the edge of vision instead of pulling the eye off
 * the paragraph above it.
 *
 * Delays are positive, so on arrival the three light up in order before
 * settling into the loop. After the first cycle a positive and a negative
 * delay are indistinguishable, and positive is the one you can read. */

#philosophy .icons.major .icon.major {
	background-color: rgba(42, 126, 118, 0.08);
	border-color: var(--nmc-accent);
}

/* inset: -2px puts this box exactly on the element's BORDER box — an absolutely
 * positioned child resolves against the padding box, so without it the line
 * would sit 2px inside the real one and read as a double rule. Its own 2px
 * border then lands precisely over the copper rule beneath it.
 *
 * No background: the diamond's teal tint belongs to the element, and filling
 * this as well would double it up at every point in the cycle. */
#philosophy .icons.major .icon.major::after {
	content: '';
	position: absolute;
	inset: -2px;
	border: solid 2px var(--nmc-accent);
	border-radius: 3px;
	box-shadow:
		0 0 0.18em rgba(184, 101, 74, 0.95),
		0 0 0.6em 0.03em rgba(184, 101, 74, 0.6),
		inset 0 0 0.4em rgba(184, 101, 74, 0.45);
	opacity: 0;
	pointer-events: none;
}

@keyframes nmc-signal {
	0%, 100% { opacity: 0; }
	50%      { opacity: 1; }
}

/* Longhand rather than the animation shorthand, because the name has to come
 * from the --nmc-pulse switch at the top of this file and the shorthand cannot
 * take a variable for just one part of itself. Set that to `none` and this
 * rule resolves to no animation at all. */
#philosophy .inner.is-revealed .icons.major .icon.major::after {
	animation-name: var(--nmc-pulse);
	animation-duration: 3.6s;
	animation-timing-function: ease-in-out;
	animation-delay: 0.45s;
	animation-iteration-count: infinite;
	animation-fill-mode: both;
}

/* Sense, then Signal, then Strengthen — a third of the cycle apart. */
#philosophy .inner.is-revealed .icons.major li:nth-child(2) .icon.major::after {
	animation-delay: 1.65s;
}

#philosophy .inner.is-revealed .icons.major li:nth-child(3) .icon.major::after {
	animation-delay: 2.85s;
}

/* Belt and braces, matching .nmc-reveal above: the script already bails before
 * adding the class, so this only matters if the setting changes after load.
 * This one earns its keep more than most — an animation that never ends is
 * exactly what someone sets that preference to stop. */
@media (prefers-reduced-motion: reduce) {
	#philosophy .inner.is-revealed .icons.major .icon.major::after {
		animation: none;
	}
}

/* Spectral steps each feature cell through progressively darker black tints.
 * Those muddy the bone ground, so the cells are flattened and separated by a
 * hairline instead. */
#about .features li {
	background-color: transparent !important;
}

/* Below 737px the template stacks these one-up and draws its own border-top,
 * so that only needs recolouring. */
#about .features li {
	border-top-color: var(--nmc-section-rule);
}

/* From 737px they sit two-up, so the rule belongs above each ROW — that is
 * every cell from the third on. Using li + li would put a rule above the
 * top-right cell but not the top-left one. */
@media (min-width: 737px) {
	#about .features li:nth-child(n + 3) {
		box-shadow: inset 0 1px 0 0 var(--nmc-section-rule);
	}
}

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

/* Spectral hides every .icon > .label with display: none. That takes the text
 * out of the accessibility tree as well as off the screen — and since the only
 * other thing inside these links is a font icon drawn in a :before, each one
 * reached a screen reader as an unnamed "link". Three links, all announced as
 * "link", one of which is the WhatsApp contact route.
 *
 * Visually hidden instead: off-screen but still announced. Same technique as
 * .nmc-visually-hidden further up, applied by selector rather than by class
 * because these spans are template markup — this way index.html and
 * generic.html both pick it up with no markup change.
 *
 * Scoped to #footer on purpose. The .icons.major labels in #philosophy are captions
 * that are meant to be seen, and the #about feature icons carry a real <h3>,
 * so neither wants this treatment. */
#footer .icons .icon > .label {
	display: block;
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

#footer .icons a {
	color: var(--nmc-section-muted);
}

#footer .icons a:hover {
	color: var(--nmc-section-fg);
}

#footer .copyright {
	color: var(--nmc-section-muted);
}

#footer .copyright li {
	border-left-color: var(--nmc-section-rule);
}

/* Anchor targets for the in-page nav. main.js offsets .scrolly by the header
 * height, but that only runs with JavaScript; this covers the plain jump, so
 * a section never lands underneath the fixed 3em bar. */
#banner,
#philosophy,
#services,
#about,
#contact {
	scroll-margin-top: 3em;
}

/* --- Interior pages ------------------------------------------------------
 * generic.html is the skeleton future pages are built from (see CLAUDE.md),
 * so it needs the same treatment as the landing page. Its shape is simpler:
 * a photo title band, one reading column, then the footer.
 *
 * The band variables are declared per block here rather than reusing the
 * landing page's lists, because none of those selectors (#philosophy, #services, #contact)
 * exist on an interior page.
 */

/* Page title band — the template gives this its own fixed photograph, so it
 * gets the same deep teal tint as the landing hero. */
#main > header {
	--nmc-section-bg:    var(--nmc-bg-inverse);
	--nmc-section-fg:    var(--nmc-text-inverse);
	--nmc-section-rule:  rgba(232, 226, 214, 0.25);
	--nmc-section-muted: rgba(232, 226, 214, 0.72);

	background-color: var(--nmc-bg-inverse);
	background-image:
		linear-gradient(
			rgb(from var(--hero-tint-color) r g b / var(--hero-tint-opacity)),
			rgb(from var(--hero-tint-color) r g b / var(--hero-tint-opacity))
		),
		var(--hero-image);
	color: var(--nmc-section-fg);
}

#main > header :is(h1, h2, h3, h4, h5, h6),
#main > header p {
	color: var(--nmc-section-fg);
}

/* The reading column: bone ground, deep teal ink. That is the 11.2:1 pairing
 * the right way round for a page that is mostly body copy. */
#main > .wrapper {
	--nmc-section-bg:    var(--nmc-bg);
	--nmc-section-fg:    var(--nmc-text);
	--nmc-section-rule:  rgba(14, 46, 51, 0.2);
	--nmc-section-muted: rgba(14, 46, 51, 0.72);

	background-color: var(--nmc-section-bg);
	color: var(--nmc-section-fg);
}

#main > .wrapper :is(h1, h2, h3, h4, h5, h6),
#main > .wrapper p,
#main > .wrapper li,
#main > .wrapper dt,
#main > .wrapper dd,
#main > .wrapper label,
#main > .wrapper th,
#main > .wrapper td {
	color: var(--nmc-section-fg);
}

/* Pull quotes.
 *
 * Spectral sets blockquote in italic. Only the ROMAN Archivo is shipped — one
 * variable file, deliberately — so an italic blockquote would be synthesised:
 * the browser shears the upright and returns a fake oblique with distorted
 * stroke weights and no true italic letterforms. CLAUDE.md flags this exact
 * trap.
 *
 * The choice was ship a second ~35KB italic file for the sake of two pull
 * quotes, or drop the slant. Dropped — a pull quote does not need italic to
 * read as one. Size, a lighter measure and a copper rule carry it instead,
 * which is precisely copper's remit here: rules and marks, never body text.
 *
 * This is NOT the case CLAUDE.md means by "real italic content". If <em> or
 * <i> ever appear in the prose, that is a different decision and the Archivo
 * italic variable file should be committed then.
 *
 * Spectral's own treatment is a thin rule down the left and a small indent,
 * which on a bone ground reads as one more horizontal line in a page that
 * already has plenty, not as a quote. A pull quote is better served by scale
 * and space than by a border, so the border goes entirely: large, centred,
 * semibold, with room either side. Nothing to draw, nothing extra to look at.
 */
#main > .wrapper blockquote {
	font-style: normal;
	border: 0;
	max-width: 26em;
	margin: 2.5em auto;
	padding: 0;
	font-size: 1.6em;
	font-weight: 600;
	line-height: 1.35;
	text-align: center;
	color: var(--nmc-section-fg);
}

/* ul.alt draws a hairline between items; the template's is white, which is
 * invisible on bone. The blanket border-color rule above does not reach it. */
#main > .wrapper ul.alt li {
	border-top-color: var(--nmc-section-rule);
}

/* A bare <img> in the reading column. Spectral only ever sizes images that are
 * wrapped in its .image element (`.image img { width: 100% }`), so an
 * unwrapped one renders at its intrinsic width — 1600px for the photographs
 * this site ships — bursting the 1200px column AND giving the whole page a
 * horizontal scrollbar. Interior pages are the plain-prose pages, so an
 * unwrapped img is the normal case there, not the exception.
 *
 * DIRECT child only. A > here is load-bearing: an img inside .image.left is
 * already sized by the template at width:100% of a 40% float, and this rule
 * outranks that selector, so without the > it would also stamp its 2em bottom
 * margin inside the float and fight the wrapper's own margins. */
#main > .wrapper .inner > img {
	display: block;
	max-width: 100%;
	height: auto;
	margin-bottom: 2em;
}

/* A float taller than the text beside it hangs past the end of that text and
 * into whatever follows. Both things that START A SECTION have to clear it:
 * an <hr>, or the next heading. Without this the heading is shunted right and
 * indented against the float instead of sitting on the left margin, which
 * reads as broken rather than as a new section. */
#main > .wrapper hr,
#main > .wrapper .inner :is(h2, h3, h4) {
	clear: both;
}

/* Spectral floats .image.left/.right at max-width:40% with no breakpoint at
 * all, so on a phone it leaves a small picture beside a ribbon of text five or
 * six words wide. Mobile first, as everything here is: full width and no float
 * by default, and the float only comes back once there is room for it.
 *
 * 737px is the complement of Spectral's own `small` band (its rules stop at
 * max-width: 736px), and it matches the min-width query already used for the
 * features grid, so the two breakpoints stay in step. */
#main > .wrapper .inner :is(.image.left, .image.right) {
	display: block;
	float: none;
	width: 100%;
	max-width: none;
	margin: 0 0 2em 0;
	top: 0;
}

@media (min-width: 737px) {
	#main > .wrapper .inner :is(.image.left, .image.right) {
		display: inline-block;
		width: auto;
		max-width: 40%;
		top: 0.25em;
	}

	#main > .wrapper .inner .image.left {
		float: left;
		margin: 0 2em 2em 0;
	}

	#main > .wrapper .inner .image.right {
		float: right;
		margin: 0 0 2em 2em;
	}
}

#main > .wrapper a:not(.button) {
	color: var(--nmc-section-fg);
	text-decoration-color: var(--nmc-accent);
	text-underline-offset: 0.2em;
}

/* Spectral's style5 rules are near-white and vanish on bone.
 *
 * blockquote is deliberately NOT in this list. It declares its own copper
 * border above, and this rule sits later at equal specificity — leaving it in
 * silently repainted the pull quote's rule back to the hairline grey. */
#main > .wrapper hr,
#main > .wrapper table th,
#main > .wrapper table td,
#main > .wrapper .box {
	border-color: var(--nmc-section-rule);
}

#main > .wrapper .button {
	box-shadow: inset 0 0 0 2px var(--nmc-section-fg);
	color: var(--nmc-section-fg) !important;
}

#main > .wrapper .button.primary {
	background-color: var(--nmc-section-fg) !important;
	color: var(--nmc-section-bg) !important;
	box-shadow: none !important;
}

/* --- Scroll reveal -------------------------------------------------------
 * Sections rise and fade as they come into view. Paired with assets/js/nmc.js.
 *
 * .nmc-reveal is added BY THE SCRIPT, never written on the elements in the
 * markup. That is the whole safety mechanism: with JavaScript off nothing here
 * ever matches, so every section renders at full opacity and the page is
 * completely usable. A stylesheet that hid sections by default and relied on JS
 * to show them would hand a no-JS visitor a blank page.
 *
 * The banner is not in the list — it has its own load animation from
 * body.is-preload in main.css, and running both would fight.
 */

.nmc-reveal {
	opacity: 0;
	transform: translateY(1.5rem);
	transition: opacity 0.7s ease, transform 0.7s ease;
}

.nmc-reveal.is-revealed {
	opacity: 1;
	transform: none;
}

/* Belt and braces: nmc.js already bails out before adding the class, so this
 * only matters if the setting is changed after load. */
@media (prefers-reduced-motion: reduce) {
	.nmc-reveal {
		opacity: 1;
		transform: none;
		transition: none;
	}
}

/* --- Fixed nav -----------------------------------------------------------
 * The nav is not part of the alternation: it is fixed over whichever band
 * happens to be under it, so it holds one ground. It starts transparent over
 * the banner (.alt) and the template swaps that class on scroll.
 */

/* The h1 itself is included, not just the link inside it. The base brand layer
 * colours every heading deep teal, which on this deep teal bar would leave any
 * bare text in the h1 invisible. The h1 carries the lockup image rather than
 * text now, but this keeps any fallback text legible. */
#header h1,
#header h1 a,
#header nav a {
	color: var(--nmc-section-fg);
}

/* --- Header lockup -------------------------------------------------------
 * Two files side by side: nmc-logo-plain.svg is the NMC mark, and
 * nmc-logo-writing-2.svg is the copper rule plus "Neuromuscular Communication".
 * Both are 205.53 units tall, so matching their heights butts them together
 * into the full lockup with no manual nudging.
 *
 * The mark is present from first paint and never hides. The writing fades in
 * when the header leaves .alt — the transparent-over-the-banner state that
 * main.js drops once you scroll past the hero. Previously Spectral hid the
 * whole h1 in that state, which is why the entire logo only appeared on
 * scroll.
 *
 * Sizing in em rather than px means it tracks the header if that ever changes.
 */

#header h1 a {
	display: flex;
	align-items: center;
	height: 100%;
}

.nmc-lockup__mark,
.nmc-lockup__writing {
	display: block;
	height: 1.4em;
	width: auto;
}

/* Legacy single-file form, kept as a safety net: the whole lockup as ONE file,
 * nmc-lockup-dark.svg on an <img class="nmc-lockup">. No shipped page uses it
 * any more — index.html, womens-health.html and generic.html all carry the
 * two-part mark + writing above — but a page written the old way would
 * otherwise show nothing, which is exactly what happened before this rule
 * existed: the class had no sizing of its own, and an <img> with no height, as
 * a flex item inside a shrink-to-fit absolutely positioned h1, resolved to
 * 0x0. Same 1.4em as above so either form reads at one size.
 *
 * The selector is img.nmc-lockup, not .nmc-lockup, because the name means two
 * different elements on the two pages: on index.html .nmc-lockup is the <a>
 * WRAPPING the two images, and it already takes height:100% from the rule
 * above at equal specificity. A bare .nmc-lockup here would win on source
 * order and squash the landing header to 1.4em. */
#header h1 img.nmc-lockup {
	display: block;
	height: 1.4em;
	width: auto;
}

/* Undo the template's blanket hide, so the mark stays put over the banner.
 * pointer-events comes back with it, or the visible mark would not be
 * clickable there. */
#header.alt h1 {
	opacity: 1;
	pointer-events: auto;
}

/* The writing holds its space at all times and only fades. Collapsing its
 * width would reflow the header mid-scroll, which reads as a glitch. */
.nmc-lockup__writing {
	opacity: 0;
	transition: opacity 0.2s ease;
}

#header:not(.alt) .nmc-lockup__writing {
	opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
	.nmc-lockup__writing {
		transition: none;
	}
}

#header.alt {
	background: transparent;
}

#menu a {
	color: var(--nmc-section-fg);
}

/* --- Follow links in the dialog foot --------------------------------------
 * Instagram and TikTok, opposite the WhatsApp line under the hairline. They
 * are follow links; WhatsApp stays a worded link rather than joining them as a
 * third icon, because it is the contact route and should not be reduced to
 * something you have to recognise by glyph.
 *
 * Dialog-only markup, so there is no visibility to scope — an earlier version
 * put these inside the form to sit beside Send message, which meant they rode
 * along to #contact and had to be hidden there by ancestor. Off the form, that
 * whole problem disappears.
 *
 * No .label class on purpose — main.css hides .icon > .label with
 * display:none, which takes it out of the accessibility tree and leaves a link
 * whose only content is a :before glyph, i.e. announced as an unnamed "link".
 * The markup uses .nmc-visually-hidden instead, which no template rule touches.
 */
.nmc-modal__social {
	display: flex;
	align-items: center;
	gap: var(--nmc-space-md);
	margin: 0;
	padding: 0;
	list-style: none;
}

.nmc-modal__social li {
	padding: 0;
}

.nmc-modal__social a.icon {
	display: block;
	font-size: 1.25em;
	line-height: 1;
	color: var(--nmc-section-fg);
	border-bottom: 0;
	opacity: 0.85;
	transition: opacity 0.2s ease, color 0.2s ease;
}

/* Copper on hover keeps the accent doing affordance duty rather than colouring
 * the resting state, matching the footer icons. */
.nmc-modal__social a.icon:hover {
	color: var(--nmc-accent);
	opacity: 1;
}

.nmc-modal__social a.icon:focus-visible {
	outline: 2px solid var(--nmc-accent);
	outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
	.nmc-modal__social a.icon {
		transition: none;
	}
}
