/* ============================================================
   Site header - utility bar + main bar (logo, primary nav with the
   mega-menu toggles, Book pill, hamburger).
   Designs: home-desktop-v4 y 0-128 (1440), home-mobile-v4 y 0-127 (402).
   Spec: docs/homepage-build-brief.md 3.1, 3.2, 3.4, 3.5.
   Mobile-first:
     < 768     rating-only utility bar; logo + Book + hamburger
     768-1023  tablet: the desktop utility split, the mobile bar with the
               logo at its desktop size (208 x 68), overlay menu
     >= 1024   desktop bar with the five nav items and mega menus
   In its own place at the top of the page; scrolled past, it comes back
   floating when the page is scrolled up (Miles 2026-10-07; QH9 had it
   static) - "On scroll" at the end. Panels: mega-menu.css. Overlay:
   mobile-menu.css. z-index: header 40 (so the soft shadow and the mega
   panels sit over the hero and the page), panels 50 inside it (the
   opening one 51).
   ============================================================ */

.site-header {
	position: relative;
	z-index: 40;
	background-color: var(--color-surface-dark);
	color: var(--color-text-on-dark);
	box-shadow: var(--shadow-header);
}

/* ---------- Utility bar: 33px + 1px Grey Dark line ---------- */

.site-header__utility {
	border-bottom: var(--border-hairline) solid var(--color-divider-on-dark);
	font-size: var(--fs-label);
	line-height: var(--lh-body);
}

/* 1px top padding: the design centres the row on y 17 of the 33px bar. */
.site-header__utility-inner {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: var(--header-utility-h);
	padding-top: 1px;
}

/* Email + WhatsApp: tablet and desktop only (the mobile design shows the
   rating alone). */
.site-header__contacts {
	display: none;
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-header__contact {
	display: flex;
	align-items: center;
	gap: 4px;
	color: var(--color-text-on-dark);
	text-decoration: none;
	white-space: nowrap;
	transition: color var(--transition);
}

.site-header__contact-icon {
	color: var(--color-accent);
}

.site-header__contact:hover {
	color: var(--color-link-hover-on-dark);
}

/* Google G + five stars + "5.0 Stars based on 70 reviews". */
.site-header__rating {
	display: flex;
	align-items: center;
	gap: 7px;
	white-space: nowrap;
}

.site-header__google {
	width: 17px;
	height: 17px;
}

/* Gaps as drawn: G to stars 8px, stars to text 9px (ink to ink; each
   star box carries about 1.3px of side bearing). */
.site-header__stars {
	display: inline-flex;
	color: var(--color-rating);
}

/* 14 x 13 stars on a 15.5px pitch, 76px across (design): 16.5px boxes
   overlapping by 1px. */
.site-header__stars .icon {
	width: 16.5px;
	height: 16.5px;
}

.site-header__stars .icon + .icon {
	margin-left: -1px;
}

.site-header__rating-text strong {
	font-weight: var(--fw-bold);
}

.site-header__rating-text a {
	color: inherit;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
	transition: color var(--transition);
}

.site-header__rating-text a:hover {
	color: var(--color-link-hover-on-dark);
}

/* Tablet keeps the desktop split. It fits at 768 with the current details;
   if a longer email or review count ever runs out of room, the email text
   gives way first (ellipsis; the link and its full text stay intact for
   screen readers) and the rating never shrinks. */
@media (min-width: 768px) {
	.site-header__utility-inner {
		justify-content: space-between;
		gap: 24px;
	}

	.site-header__contacts {
		display: flex;
		gap: 26px;
		min-width: 0;
	}

	.site-header__contacts-item {
		flex: none;
	}

	.site-header__contacts-item--email,
	.site-header__contacts-item--email .site-header__contact {
		flex: 0 1 auto;
		min-width: 0;
	}

	.site-header__contacts-item--email .site-header__contact-text {
		overflow: hidden;
		text-overflow: ellipsis;
	}

	.site-header__rating {
		flex: none;
	}
}

/* ---------- Main bar: 92px (95px from 1024), everything centred ---------- */

/* Positioning context for the mega panels, which hang below the bar and
   line up with the container (mega-menu.css). */
.site-header__bar-inner {
	position: relative;
	display: flex;
	align-items: center;
	min-height: var(--header-bar-h);
}

/* Lockup 182.5 x 60 on phones, 208 x 68 from tablet up. It may shrink on
   very narrow phones so the Book pill and hamburger always fit. */
.site-header__logo {
	flex: 0 1 182.5px;
	min-width: 0;
	margin-right: auto;
	line-height: 0;
}

.site-header__logo img {
	width: 100%;
	height: auto;
}

.site-header__book {
	flex: none;
	margin-left: 12px;
}

/* The account link (2026-10-25, inc/account.php): "Login", or "Hi, {name}",
   left of the Book pill from 1024px (account designs: a White person and
   SemiBold label, 14px before the pill); on phones and tablets it is the
   menu's last row. */
.site-header__account {
	display: none;
}

@media (min-width: 1024px) {
	.site-header__account {
		display: inline-flex;
		flex: none;
		align-items: center;
		gap: 6px;
		margin-left: 40px;
		color: var(--color-heading-on-dark);
		font-size: var(--fs-body);
		font-weight: var(--fw-semibold);
		text-decoration: none;
		white-space: nowrap;
	}

	.site-header__account + .site-header__book {
		margin-left: 14px;
	}

	.site-header__account[aria-current] span,
	.site-header__account:focus-visible span {
		text-decoration: underline;
		text-decoration-color: var(--color-accent);
		text-underline-offset: 0.3em;
	}
}

@media (hover: hover) and (min-width: 1024px) {
	.site-header__account:hover span {
		text-decoration: underline;
		text-decoration-color: var(--color-accent);
		text-underline-offset: 0.3em;
	}
}

/* Hamburger: three White 29.8 x 2 bars (rounded ends, 9.3px pitch) in a
   44 x 44 tap target. The negative right margin keeps the bars where the
   design draws them (16.6px from the edge at 402) with the gutter at 14. */
.site-header__menu-toggle {
	flex: none;
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 7.3px;
	width: var(--tap-target);
	height: var(--tap-target);
	margin: 0 -4.5px 0 12.5px;
	padding: 0;
	border: 0;
	background: none;
	color: var(--color-white);
	transition: color var(--transition);
}

.site-header__menu-bar {
	display: block;
	width: 29.8px;
	height: 2px;
	border-radius: 1px;
	background-color: currentColor;
}

.site-header__menu-toggle:hover {
	color: var(--color-link-hover-on-dark);
}

@media (min-width: 768px) {
	.site-header__logo {
		flex-basis: 208px;
	}
}

/* ---------- Primary navigation (desktop) ---------- */

.primary-nav {
	display: none;
}

.primary-nav__list {
	display: flex;
	align-items: center;
	gap: 24px;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Static on purpose: the panels position against .site-header__bar-inner. */
.primary-nav__item {
	display: flex;
	align-items: center;
}

/* Labels and chevrons answer at once (--transition-quick), and the
   chevron flips with the panel's own opening curve. */
.primary-nav__link {
	color: var(--color-link-on-dark);
	font-size: var(--fs-body);
	font-weight: var(--fw-semibold);
	line-height: 24px;
	text-decoration: none;
	white-space: nowrap;
	transition: color var(--transition-quick);
}

/* Separate chevron button (the label is a real link). 24 x 24 target; the
   thin 9 x 5 chevron sits about 6px after the label as designed. */
.primary-nav__toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 24px;
	margin-left: -1px;
	padding: 0;
	border: 0;
	background: none;
	color: var(--color-link-on-dark);
	transition: color var(--transition-quick);
}

/* The button starts right where the label ends, so its focus ring sits
   inside the 24px box instead of cutting through the label's last letter. */
.primary-nav__toggle:focus-visible {
	outline-offset: -4px;
}

.primary-nav__chevron {
	transition: transform var(--menu-in-duration) var(--ease-out-cubic);
}

.primary-nav__link:hover,
.primary-nav__toggle:hover {
	color: var(--color-link-hover-on-dark);
}

/* Open (designed) and current page (proposal, QH10): Light Orange label and
   chevron; the open chevron flips up. */
.primary-nav__item.is-open > .primary-nav__link,
.primary-nav__item.is-open > .primary-nav__toggle,
.primary-nav__item.is-current > .primary-nav__link,
.primary-nav__item.is-current > .primary-nav__toggle {
	color: var(--color-accent);
}

.primary-nav__item.is-open > .primary-nav__toggle .primary-nav__chevron {
	transform: rotate(180deg);
}

/* ---------- Desktop (>= 1024px) ---------- */

@media (min-width: 1024px) {
	.primary-nav {
		display: block;
	}

	.site-header__book {
		margin-left: 40px;
	}

	.site-header__menu-toggle {
		display: none;
	}
}

/* Touch screens at desktop width (iPad landscape): a 44 x 44 chevron
   target without moving anything. */
@media (min-width: 1024px) and (pointer: coarse) {
	.primary-nav__toggle {
		width: var(--tap-target);
		height: var(--tap-target);
		margin: -10px -10px -10px -11px;
	}

	/* Same 20px ring as above, inside the larger target. */
	.primary-nav__toggle:focus-visible {
		outline-offset: -14px;
	}
}

/* ---------- Without JS ---------- */

/* Phones and tablets get the five links as a plain row under the bar
   instead of the hamburger (the overlay needs JS). */
html:not(.has-js) .site-header__bar-inner {
	flex-wrap: wrap;
	row-gap: 12px;
	padding-top: 16px;
}

html:not(.has-js) .site-header__menu-toggle,
html:not(.has-js) .primary-nav__toggle {
	display: none;
}

html:not(.has-js) .primary-nav {
	display: block;
	order: 1;
	flex-basis: 100%;
	padding-bottom: 16px;
}

html:not(.has-js) .primary-nav__list {
	flex-wrap: wrap;
	gap: 4px 24px;
}

@media (min-width: 1024px) {
	html:not(.has-js) .site-header__bar-inner {
		flex-wrap: nowrap;
		padding-top: 0;
	}

	html:not(.has-js) .primary-nav {
		order: 0;
		flex-basis: auto;
		padding-bottom: 0;
	}

	html:not(.has-js) .primary-nav__toggle {
		display: inline-flex;
	}

	/* CSS-only panels (mega-menu.css) open on hover / focus: the open
	   colours follow. */
	html:not(.has-js) .primary-nav__item--mega:hover > .primary-nav__link,
	html:not(.has-js) .primary-nav__item--mega:hover > .primary-nav__toggle,
	html:not(.has-js) .primary-nav__item--mega:focus-within > .primary-nav__link,
	html:not(.has-js) .primary-nav__item--mega:focus-within > .primary-nav__toggle {
		color: var(--color-accent);
	}
}

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

/* ---------- On scroll: floating and leaving (navigation.js) ----------
   Scrolled past, the header waits above the page; scrolling up brings it
   back floating at the top with only the main bar in view (the utility bar
   sits above the edge), as on Northumberland Cheese (Miles 2026-10-07): it
   slides down a little as it fades in, and slides up as it fades away.
   Under the WordPress toolbar when there is one (main.css
   --toolbar-fixed-h: none on phones, where it scrolls away with the page).
   Reduced motion: fades only.
   The motion is a transition on the header itself, never a keyframe: the
   script sets the arrival's start (.is-arriving, transitions off) and lets
   go of it, so a change of mind half-way - scrolling down again during the
   arrival, or reaching the top of the page - carries on from wherever the
   header is, in every engine. */

.site-header {
	/* The utility bar's real height (navigation.js measures it, so text zoom
	   never lets a sliver show); the same figure decides when it is back in
	   its own place. */
	--header-utility-total: var(--header-utility-measured, calc(var(--header-utility-h) + var(--border-hairline)));
	--header-float-top: calc(var(--toolbar-fixed-h) - var(--header-utility-total));
	transition:
		opacity var(--header-slide-duration) var(--ease-out-cubic),
		transform var(--header-slide-duration) var(--ease-out-cubic);
}

.site-header.is-floating,
.site-header.is-leaving {
	position: sticky;
	top: var(--header-float-top);
}

/* Keyboard focus in the utility bar (Shift+Tab back from the logo) brings
   the whole header into view. In CSS, so the browser sees the header in
   place before it scrolls to the focus; engines without :has() show the
   whole header whenever focus is anywhere in it. */
.site-header:has(.site-header__utility :focus-visible) {
	--header-float-top: var(--toolbar-fixed-h);
}

@supports not selector(:has(*)) {
	.site-header:focus-within {
		--header-float-top: var(--toolbar-fixed-h);
	}

	.site-header:is(.is-floating, .is-leaving):focus-within .site-header__utility {
		border-bottom-color: var(--color-divider-on-dark);
	}
}

/* Floating, the utility bar's hairline sits just above the edge; at some
   device pixel ratios Chromium bleeds it into the bar's top row. It is
   back when the whole header shows. */
.site-header:is(.is-floating, .is-leaving) .site-header__utility {
	border-bottom-color: transparent;
}

.site-header:is(.is-floating, .is-leaving):has(.site-header__utility :focus-visible) .site-header__utility {
	border-bottom-color: var(--color-divider-on-dark);
}

.site-header.is-arriving {
	opacity: 0;
	transform: translateY(-40%);
	transition: none;
}

.site-header.is-leaving {
	opacity: 0;
	transform: translateY(-100%);
	pointer-events: none;
}

/* Keyboard focus arriving in a header that is sliding away puts it straight
   back (resolved before the browser scrolls to the focus; the script then
   makes it float). */
.site-header.is-leaving:has(:focus-visible) {
	opacity: 1;
	transform: none;
	transition: none;
}

/* Focus inside the header needs no room above it (main.css): the header
   moves to show it, not the page. Nor does the mobile menu, which scrolls
   on its own with no bar over it. */
html.has-js .site-header :focus,
html.has-js .mobile-menu :focus {
	scroll-margin-top: 0;
}

/* The header's own place is navy underneath, so an arrival still running
   when the page reaches the top (or the fade under reduced motion) never
   shows the cream page through it. navigation.js measures the header
   (--header-slot-h on <html>); logged in, the page starts under the
   toolbar. A real element just before the header (header.php), not a
   pseudo-element on body: accessibility checkers cannot work out text
   contrast under an ancestor's pseudo-element background. */
.header-underlay {
	display: none;
}

html.has-js .header-underlay {
	display: block;
	position: absolute;
	top: var(--wp-admin--admin-bar--height, 0px);
	right: 0;
	left: 0;
	height: var(--header-slot-h, calc(var(--header-utility-h) + var(--border-hairline) + var(--header-bar-h)));
	background-color: var(--color-surface-dark);
}

@media (prefers-reduced-motion: reduce) {
	.site-header {
		transition: opacity var(--header-slide-duration) var(--ease-out-cubic);
	}

	.site-header.is-arriving,
	.site-header.is-leaving {
		transform: none;
	}
}

/* Printed, the header is simply at the top of the first page, wherever it
   was floating. */
@media print {
	html.has-js .header-underlay {
		display: none;
	}

	.site-header.is-floating,
	.site-header.is-leaving {
		position: relative;
		top: auto;
		opacity: 1;
		transform: none;
	}
}

/* A floating header's mega panels fit the window: a tall one scrolls
   (only short windows, e.g. Workshops at 1024 x 768), and at its end the
   wheel moves the page on (no overscroll containment: in Chromium that
   also held a panel with nothing to scroll). Kept while the header slides
   away, so a panel fading out with it does not change size. */
@media (min-width: 1024px) {
	.site-header:is(.is-floating, .is-leaving) .mega-panel {
		max-height: calc(100vh - var(--toolbar-fixed-h) - var(--header-bar-h) - var(--mega-gap) - 16px);
		max-height: calc(100dvh - var(--toolbar-fixed-h) - var(--header-bar-h) - var(--mega-gap) - 16px);
		overflow-y: auto;
	}
}
