/**
 * Section 1 - Site header
 *
 * Layout: [ logo ] [ search grows ] [ account | wishlist | cart ]
 * Collapses to two rows on tablet, icon-only actions on small phones.
 */

.medlife-header {
	background: var(--ml-white);
	color: var(--ml-charcoal);
	width: 100%;
}

/*
 * The 48px horizontal inset is deliberate breathing room, not arbitrary: it
 * sets how far the logo sits from the left edge and the actions from the
 * right, and both come from this one value so they cannot drift apart.
 *
 * The responsive rules below keep 20px and 16px. That is not an oversight -
 * a narrow viewport needs the width for content, and the header re-lays-out
 * completely at 1024px anyway (the search drops to its own row), so the step
 * in padding is invisible against that.
 */
.medlife-header__inner {
	max-width: var(--ml-container);
	margin: 0 auto;
	padding: 18px 64px;
	display: flex;
	align-items: center;
	gap: 32px;
}

/* ---------- Logo ---------- */

.medlife-header__logo {
	flex: 0 0 auto;
	display: block;
	line-height: 0;
}

/*
 * The -6px is an OPTICAL correction for the artwork, not a layout fix. Do not
 * remove it as a stray magic number, and do not "fix" the alignment in CSS
 * instead - the CSS is already correct.
 *
 * medlife-logo-dark-900.png is 900x512 and perfectly centred as a file: 27px
 * of transparent margin top AND bottom, bbox offset +0.0px. Flexbox centres
 * that box exactly. The imbalance is INSIDE the artwork:
 *
 *     figure + leaves   x 0-359     ink y  27-484   optical centre 255.5
 *     "Med Life /
 *      HEALTH CARE"     x 360-899   ink y 272-484   optical centre ~378
 *
 * Canvas centre is 255.5, so the figure is dead centre while the wordmark
 * sits in the lower 41% of the canvas - 122px low at source size, ~14.8px low
 * once scaled to 62px. The eye reads the wordmark as "the logo" and aligns it
 * against the search field's text, so a perfectly centred box still looks
 * about 15px low.
 *
 * -6px is a deliberate part-correction, not the full 14.8px. The header's
 * content box is 62px inside 18px padding, so a full correction would leave
 * 3px above the logo and 33px below and read as pinned to the top edge. 6px
 * takes the worst off while keeping the row visually balanced.
 *
 * THE REAL FIX IS A REBALANCED LOGO FILE - artwork whose wordmark is centred
 * against the figure rather than baseline-aligned to it. When new artwork
 * arrives, re-measure with the bbox/band scan (see CLAUDE.md) and delete this
 * offset rather than carrying it forward.
 */
.medlife-header__logo img {
	height: 62px;
	width: auto;
	display: block;
	position: relative;
	top: -6px;
}

/* -------------------------------------------------------------------------
 * Search: grey pill, blue button filling its right end
 *
 * The component lives in assets/css/search.css and is shared with the blog
 * hero search and searchform.php. This section owns the layout wrapper and a
 * handful of tokens - no geometry, no states, no Astra defences.
 *
 * All of that was duplicated here until 2026-08-29, and the duplicate is
 * precisely why the same overflow bug had to be found and fixed twice: once
 * in this file on 2026-08-28, once in blog.css a day later, because nothing
 * connected the two.
 * ---------------------------------------------------------------------- */

/*
 * 600px, down from 735px - roughly half the 1264px content box at full width,
 * so the field reads as one element in the row rather than the row's subject.
 *
 * `margin-inline: auto` is what stops that becoming a layout bug. With
 * `flex: 1 1 auto` and a cap, any space beyond the cap is free space, and
 * with the default `justify-content: flex-start` it all collects at the END
 * of the row - which would leave the actions floating short of the right
 * padding by a margin that changes with the viewport. Auto margins absorb
 * that space evenly on both sides instead: the search centres between the
 * logo and the actions, and the actions sit hard against the 48px inset at
 * every width.
 *
 * Shrinking stays smooth. Auto margins only absorb POSITIVE free space, so
 * once the row is tight they collapse to zero and `flex-shrink: 1` with
 * `min-width: 0` takes over - the field narrows continuously rather than
 * snapping when the cap stops applying. Below 1024px this rule is overridden
 * entirely and the search takes its own full-width row.
 */
.medlife-header__search {
	flex: 1 1 auto;
	min-width: 0;
	max-width: 600px;
	margin-inline: auto;
}

/*
 * Two classes, so these beat search.css's own defaults whatever order the
 * browser sees the stylesheets in.
 *
 * The full-round radius is the header's one real difference from the blog
 * instance, and it needs no button rule of its own: 999px clamps to half the
 * element's own height, and search.css gives the button `align-self: stretch`,
 * so the pill's curve and the button's are identical by construction at 50px
 * and at 46px.
 */
.ml-search.medlife-search {
	--ml-search-radius: 999px;
	--ml-search-height: 50px;
	--ml-search-bg: #f4f6f8;
	--ml-search-btn-width: 62px;
	--ml-search-font: 15px;
}

/* ---------- Account / Wishlist / Cart ---------- */

/*
 * No `margin-left: auto` here - and its removal is a fix, not a tidy-up.
 *
 * It predates the search's `margin-inline: auto`. Once both existed, flexbox
 * had THREE auto margins to feed and it splits free space equally between
 * them, so the search took two thirds and the actions one third. The actions
 * still landed flush right (nothing follows them), so the symptom was subtle:
 * the search sat left of true centre, by one third of the free space.
 *
 * The search's two auto margins alone consume all the free space, which both
 * centres the search between the logo and the actions and leaves the actions
 * against the padding edge - what the `margin-left: auto` was there to do.
 */
.medlife-header__actions {
	flex: 0 0 auto;
	display: flex;
	align-items: flex-start;
	gap: 38px;
}

.medlife-action {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	/* Dark grey on white; the cyan count badges carry the only colour here. */
	color: var(--ml-charcoal);
	text-decoration: none;
	font-size: 13px;
	line-height: 1.2;
	transition: color var(--ml-t-base) var(--ml-e-standard);
}

.medlife-action:hover,
.medlife-action:focus {
	color: var(--ml-cyan);
}

.medlife-action:focus-visible {
	outline: 3px solid var(--ml-cyan);
	outline-offset: 3px;
	border-radius: 4px;
}

.medlife-action__icon {
	position: relative;
	display: block;
	line-height: 0;
}

.medlife-action__label {
	white-space: nowrap;
}

.medlife-icon {
	display: block;
}

/* ---------- Count badge ---------- */

.medlife-badge {
	position: absolute;
	top: -7px;
	right: -11px;
	min-width: 19px;
	height: 19px;
	padding: 0 5px;
	border-radius: 999px;
	background: var(--ml-cyan);
	color: var(--ml-white);
	font-size: 11px;
	font-weight: 700;
	line-height: 19px;
	text-align: center;
	box-sizing: border-box;
}

/* -------------------------------------------------------------------------
 * Responsive
 * ---------------------------------------------------------------------- */

/* Tablet - search drops to its own full-width row. */
@media (max-width: 1024px) {
	.medlife-header__inner {
		flex-wrap: wrap;
		gap: 16px 24px;
		padding: 16px 20px;
	}

	.medlife-header__logo img {
		height: 54px;
	}

	.medlife-header__search {
		order: 3;
		flex: 1 1 100%;
		max-width: none;
		/* Own row, no free space to absorb - reset so the cap above cannot
		   half-apply if either value is ever changed. */
		margin-inline: 0;
	}

	.medlife-header__actions {
		gap: 30px;
	}
}

/* Phone - icon-only actions, tighter spacing. */
@media (max-width: 640px) {
	.medlife-header__inner {
		padding: 14px 16px;
		gap: 14px 16px;
	}

	.medlife-header__logo img {
		height: 44px;
	}

	.medlife-header__actions {
		gap: 22px;
	}

	.medlife-action__label {
		display: none;
	}

	/* Tokens again - the component reads them, so nothing here restates a rule. */
	.ml-search.medlife-search {
		--ml-search-height: 46px;
		--ml-search-btn-width: 58px;
		--ml-search-font: 14px;
		--ml-search-pad: 0 10px 0 18px;
	}
}

@media (max-width: 380px) {
	.medlife-header__logo img {
		height: 38px;
	}

	.medlife-header__actions {
		gap: 16px;
	}
}

/* -------------------------------------------------------------------------
 * Reduced motion
 *
 * The colour still changes on hover and on keyboard focus - it just changes
 * instantly. Nothing scales and nothing eases. Same specificity as the rules
 * above, and last in the file, so it wins on order.
 * ---------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	/*
	 * The search pill's reduced-motion handling moved to search.css with the
	 * rest of the component. Anything left here is header chrome only.
	 */
	.medlife-action {
		transition: none;
	}
}

/*
 * POINTER FOCUS - ASTRA a:focus { outline: thin dotted } (main.min.css L3).
 * A mouse click leaves :focus set, so every anchor that names no outline of its
 * own kept a thin dotted ring until focus moved. Measured 2026-09-13 by the
 * sitewide anchor sweep (CLAUDE.md, "Anchor pointer-focus sweep").
 *
 * :not(:focus-visible) IS LOAD-BEARING: this only ever applies to pointer focus,
 * so the keyboard ring each family already has is untouched. Outline only -
 * nothing moves, so there is no reduced-motion twin.
 */
a.medlife-action:focus:not(:focus-visible),
a.medlife-header__logo:focus:not(:focus-visible) {
	outline: none;
}

/*
 * KEYBOARD RINGS - 2026-09-14. These families had NO focus ring of their own:
 * keyboard focus showed only Astra's a:focus-visible 1px dotted in the text
 * colour, or nothing at all where a theme rule said outline: none. Measured by
 * the sitewide anchor sweep (CLAUDE.md, "Keyboard ring pass").
 *
 * Light surface: 3px --ml-cyan offset 3px. Navy surface: 2px. border-radius is
 * RESTATED on every ring - a rule wins only the properties it names, and a
 * shared focus rule has squared a round control on this site before. Text links
 * take 4px corners; boxed controls keep their own radius.
 *
 * The pointer pin (:focus:not(:focus-visible)) above is untouched - the two
 * selectors can never match the same state. Contrast: cyan on white 2.50:1 is
 * the owner's recorded decision (CLAUDE.md, "THE FOCUS-RING RULE").
 */
/*
 * THE HEADER LOGO RING GOES ON THE IMAGE, NOT THE ANCHOR. The img carries
 * position: relative; top: -6px as an optical correction (CLAUDE.md, "The logo
 * looks low in the header"), so a ring on the anchor would sit 6px below the
 * artwork. The anchor's own ring is switched off only under :focus-visible and
 * the image draws it instead. Radius 0: the PNG's figure reaches its left edge,
 * and rounding the image would clip it.
 */
a.medlife-header__logo:focus-visible {
	outline: none;
}

a.medlife-header__logo:focus-visible img {
	outline: 3px solid var(--ml-cyan);
	outline-offset: 3px;
	border-radius: 0;
}

/*
 * RING FADE - ASTRA'S INLINE `a { transition: all .2s linear }`. "all" includes
 * outline, so these families' keyboard rings slid and faded in over 200ms
 * instead of appearing at once. Each family now names exactly what its hover /
 * focus-visible state really changes, measured 2026-09-14 (CLAUDE.md, "Ring fade
 * pass"): colour where Astra's a:hover repaints the ink, nothing at all where
 * only the (discrete) underline changes or nothing visible changes.
 * Outline is never in the list. Colour-only fades need no reduced-motion twin.
 */
a.medlife-header__logo {
	transition: none;
}

/* =========================================================================
 * MOBILE HEADER - <= 768px ONLY (2026-09-21)
 *
 * Desktop is untouched by construction: every rule below sits inside the
 * 768px query, and the two new controls are display:none outside it.
 *
 * Before: top bar 60px over a 126px three-row header over a separate 70px
 * "Menu" bar - 256px of chrome before a visitor saw a product. After: one
 * ~32px strip and one ~56px row, sticky, with search on demand.
 * ====================================================================== */

/* Hidden everywhere by default; the phone block below turns them on. */
.medlife-header__burger,
.medlife-header__searchtoggle {
	display: none;
}

/*
 * ASTRA REPAINTS ANY BARE <button> - CLAUDE.md, "Astra repaints any bare
 * button on :hover and :focus". Its inline rules are button:focus /
 * button:hover at (0,1,1) plus padding 10px 20px, border-radius 30px and a
 * box-shadow at (0,0,1). A rest rule at (0,2,0) keeps matching in every
 * state and so wins them all - but the explicit five-state lock is the house
 * idiom and survives someone later adding a .is-active variant.
 *
 * padding: 0 IS LOAD-BEARING on an icon-only button. Astra's 10px/20px inside
 * a 44px box leaves a 4px content box and the SVG renders as a ~3px dot -
 * this file already records two controls that lost to exactly that.
 */
.medlife-header .medlife-header__burger,
.medlife-header .medlife-header__burger:hover,
.medlife-header .medlife-header__burger:focus,
.medlife-header .medlife-header__burger:focus-visible,
.medlife-header .medlife-header__burger:active,
.medlife-header .medlife-header__searchtoggle,
.medlife-header .medlife-header__searchtoggle:hover,
.medlife-header .medlife-header__searchtoggle:focus,
.medlife-header .medlife-header__searchtoggle:focus-visible,
.medlife-header .medlife-header__searchtoggle:active {
	padding: 0;
	border: 0;
	border-radius: 10px;
	background: none;
	box-shadow: none;
	color: var(--ml-charcoal);
	font-size: inherit;
	line-height: 1;
}

/*
 * THE STUCK CYAN LOOK. A mouse or finger leaves :focus set, so a control
 * styled only through :focus-visible keeps whatever :focus painted until
 * focus moves. The pin restores the rest appearance for pointer focus only;
 * :not(:focus-visible) is what keeps the keyboard ring below untouched.
 */
.medlife-header .medlife-header__burger:focus:not(:focus-visible),
.medlife-header .medlife-header__searchtoggle:focus:not(:focus-visible) {
	outline: none;
	background: none;
	color: var(--ml-charcoal);
}

.medlife-header .medlife-header__burger:focus-visible,
.medlife-header .medlife-header__searchtoggle:focus-visible {
	outline: 3px solid var(--ml-cyan);
	outline-offset: 2px;
	border-radius: 10px;
}

@media (max-width: 768px) {
	/* Sticky: the strip scrolls away, the row stays. */
	.medlife-header {
		position: sticky;
		top: 0;
		z-index: 60;
		background: var(--ml-white);
	}

	.medlife-header__inner {
		flex-wrap: wrap;
		align-items: center;
		gap: 0;
		padding: 6px 8px;
		min-height: 56px;
	}

	.medlife-header__burger,
	.medlife-header__searchtoggle {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		/* 44px is the WCAG 2.5.8 floor, and these are the two smallest
		   controls in the row - do not shrink them to buy logo width. */
		width: 44px;
		height: 44px;
		flex: 0 0 44px;
		cursor: pointer;
	}

	.medlife-header__burger      { order: 1; }
	.medlife-header__searchtoggle { order: 2; }

	/*
	 * Centred by auto margins rather than by a fixed width: the two controls
	 * on the left and the two on the right are 44px and ~40px, so a hard
	 * centre would drift the moment a badge widened. Auto margins split
	 * whatever is left, which is what "centre" actually means here.
	 */
	.medlife-header__logo {
		order: 3;
		margin-inline: auto;
	}

	.medlife-header__logo img {
		height: 36px;
		/* The -6px optical correction is tuned for the 62px desktop logo and
		   reads as a visible lift at 36px - see "The logo looks low in the
		   header". At this size the artwork sits close enough to centred. */
		top: 0;
	}

	.medlife-header__actions {
		order: 4;
		gap: 2px;
	}

	.medlife-action {
		width: 40px;
		height: 44px;
		justify-content: center;
	}

	/* Moved into the burger menu - see site-nav.php. */
	.medlife-action--wishlist {
		display: none;
	}

	/*
	 * SEARCH ON DEMAND.
	 *
	 * ⚑ THIS IS max-height, NOT THE 0fr -> 1fr GRID TECHNIQUE, AND THAT IS
	 * MEASURED RATHER THAN PREFERRED. The grid technique is what this theme
	 * uses for the accordion and it was written here first; it does not work
	 * on this content, because search.css:117 gives `.ml-search` an EXPLICIT
	 * `height: var(--ml-search-height)`.
	 *
	 * Measured in the browser, container height at 375px:
	 *
	 *     as shipped, grid 0fr                      52px   <- open
	 *     grid-template-rows: 0fr set INLINE        52px   <- not a cascade
	 *                                                         problem
	 *     same, with the form forced to height:auto  8px   <- collapses
	 *     display:block + max-height: 0              0px   <- collapses
	 *
	 * So `0fr` resolves to the item's content size whenever the item carries
	 * an explicit height, and `overflow: hidden` on either element does not
	 * change it. Forcing the form to `height: auto` would collapse the pill
	 * the rest of the component is built around, so max-height it is.
	 *
	 * The cap is DERIVED, not guessed - one custom property feeds both the
	 * pill's height and the cap, so they cannot drift. That is the objection
	 * to max-height ("it clips on content taller than the guess") answered:
	 * the content here is a fixed-height pill, not prose.
	 */
	.medlife-header__search {
		/* The single source for the pill height and the open cap below. */
		--ml-hdr-search-h: 44px;

		order: 5;
		flex: 0 0 100%;
		max-width: none;
		margin-inline: 0;
		max-height: 0;
		overflow: hidden;
		transition: max-height var(--ml-t-panel) var(--ml-e-standard);
	}

	.medlife-header__inner.is-search-open .medlife-header__search {
		/* + 8px = the form's margin-bottom, i.e. the gap under the pill. */
		max-height: calc(var(--ml-hdr-search-h) + 8px);
	}

	.medlife-header__search > form {
		margin-bottom: 8px;
	}

	.ml-search.medlife-search {
		/* Inherited from .medlife-header__search - see the note above. */
		--ml-search-height: var(--ml-hdr-search-h);
		--ml-search-btn-width: 52px;
		--ml-search-font: 14px;
		--ml-search-pad: 0 8px 0 16px;
	}
}

@media (max-width: 380px) {
	/* The 380 block above this one shrinks the desktop-era logo; at phone
	   width the row is already minimal, so only the logo gives way. */
	.medlife-header__logo img {
		height: 32px;
	}
}

@media (prefers-reduced-motion: reduce) {
	/*
	 * The panel still opens and closes - it just arrives at its height
	 * instantly. WCAG 2.3.3 is about motion, not about hiding the control.
	 */
	.medlife-header__search {
		transition: none;
	}
}

/* -------------------------------------------------------------------------
 * <= 768px TAP TARGETS (2026-09-21 mobile audit)
 *
 * Measured, not guessed: `.medlife-action` came out 40 x 44 and the logo
 * anchor 56.1 x 32. WCAG 2.5.8 asks for 44 x 44, and both are the controls a
 * phone visitor reaches for first.
 *
 * The 40px width is MINE, from the 2026-09-21 header rebuild - it was chosen
 * to fit five controls on a 375px row and the row has 7px of slack per side,
 * so 44 costs nothing.
 * ---------------------------------------------------------------------- */
@media (max-width: 768px) {
	.medlife-header__actions .medlife-action {
		width: 44px;
	}

	/*
	 * The logo's BOX grows to 44px; the artwork does not. `line-height: 0` on
	 * the anchor means its height was exactly the image's 36px, so centring a
	 * 44px box around the same image leaves the logo painted where it was -
	 * verified by measuring the img rect before and after, not by eye.
	 */
	.medlife-header__inner .medlife-header__logo {
		display: flex;
		align-items: center;
		min-height: 44px;
	}
}

/* -------------------------------------------------------------------------
 * <= 768px: A BIGGER, CLEANER MOBILE LOGO (2026-09-23)
 *
 * Appended last, so it wins over the 768 and 380 tiers above without raising
 * anyone's specificity. Every rule is inside the query - desktop keeps its
 * 62px logo and its -6px optical correction untouched.
 * ---------------------------------------------------------------------- */
@media (max-width: 768px) {
	/*
	 * 42px, up from 36 (and from 32 below 380). The row's 56px min-height is
	 * unchanged and so is the 44px anchor box, so the icons either side do
	 * not move: the logo grows INSIDE a box that was already 44px tall.
	 *
	 * `top: 0` is inherited from the 768 tier above and still right - the
	 * -6px correction is tuned for the 62px desktop artwork and reads as a
	 * visible lift at this size.
	 */
	.medlife-header__inner .medlife-header__logo img {
		height: 42px;
	}

	/*
	 * THE TAP HIGHLIGHT IS A BOX, AND IT IS NOT THE FOCUS RING. Mobile
	 * engines paint their own translucent rectangle over a tapped link; on a
	 * logo it reads as a panel stuck around the artwork. The keyboard ring
	 * below is the only box this control should ever draw.
	 */
	a.medlife-header__logo {
		-webkit-tap-highlight-color: transparent;
	}
}

/*
 * THE POINTER PIN WAS ON THE ANCHOR ONLY, AND THE RING IS ON THE IMAGE.
 *
 * `a.medlife-header__logo:focus:not(:focus-visible)` (further up this file)
 * clears the ANCHOR's outline, but the 3px cyan ring is deliberately drawn on
 * the `img` instead - the image carries the -6px optical offset, so a ring on
 * the anchor would sit below the artwork. The image therefore needs the same
 * pin, or any engine that decides a tap counts as :focus-visible leaves a cyan
 * box around the logo until focus moves.
 *
 * Measured in Chrome at 375 and 414 with a real dispatched tap: both the
 * anchor and the image already computed `outline-style: none`, so this did NOT
 * reproduce here - it is hardening for the engines that behave otherwise, not
 * a fix for something this browser does. :not(:focus-visible) means the
 * keyboard ring is untouched either way.
 */
a.medlife-header__logo:focus:not(:focus-visible) img {
	outline: none;
}
