/* ---------------------------------------------------------------------------
 * The site header bar.
 *
 * WHAT THIS FILE IS FOR. Two things live in parts/header.html that theme.json
 * cannot reach: the cart link, whose markup is a theme block's server render
 * (see inc/header.php), and the "My account" item inside the navigation block,
 * which has to read as a different KIND of thing from the five section links
 * beside it. Neither is a core block with a styles.blocks entry, and the second
 * needs a media query, which WP_Theme_JSON::process_blocks_custom_css() drops.
 *
 * Loaded site-wide by pickleball_header_enqueue(): every template on this site
 * renders the header part, so gating it would cost a conditional and save
 * nothing.
 *
 * IT INVENTS NO COLOURS AND NO CURVES. Every value resolves to a theme.json
 * token with a literal fallback, so a renamed token leaves the header readable
 * while somebody notices.
 *
 * FOCUS RINGS ARE NOT SET HERE. motion.css carries a site-wide
 * :where(...):focus-visible ring at zero specificity; anything stated here
 * would win silently and give the header a different ring from the rest of
 * the site.
 * ------------------------------------------------------------------------ */

.pickleball-cart-link {
	--pb-cart-ink: var(--wp--preset--color--contrast, #142826);
	--pb-cart-hover: var(--wp--preset--color--base-sunken, #eeece4);
	--pb-cart-badge: var(--wp--preset--color--accent, #d8e84a);
	--pb-cart-badge-ink: var(--wp--preset--color--accent-deep, #2b3a19);
	--pb-cart-display: var(--wp--preset--font-family--archivo, system-ui, sans-serif);

	flex: 0 0 auto;
	line-height: 0;
}

/* The empty cart.
 *
 * inc/header.php always prints this wrapper, even with nothing in the cart,
 * because WooCommerce's cart fragments replace an element that is already in
 * the document - with no wrapper there is nothing for the first add-to-cart to
 * replace. `:empty` is what keeps that promise free: the wrapper is printed
 * with no children AND no whitespace, so it matches here and leaves the header
 * exactly as it was before the cart existed. A `display: none` on a class
 * toggled server-side would have done the same job while still occupying a
 * line in the accessibility tree of every page on the site. */
.pickleball-cart-link:empty {
	display: none;
}

/* A square target rather than a pill with the count beside the icon.
 *
 * Measured on the live header at 360px, the narrowest viewport any phone in
 * common use reports. The row is 320px wide there,
 * and the logo, the navigation toggle and the "Find a trip" button leave
 * 63.62px of it once the 12px gaps this file sets there are paid for. A cart
 * with the count beside the icon runs to about 72px and, with its own gap,
 * asks for 84 - twenty pixels more than there are, which comes out of the
 * button and wraps "Find a trip" onto a second line. The badge riding the
 * icon's corner keeps the whole control inside 42px: 54px with the gap, and
 * 9.62px left over.
 *
 * 42px IS ALSO THE TOUCH TARGET, AT EVERY WIDTH. It used to shrink to 40 on
 * phones, which is the one place it should not; the phone band below records
 * why the two pixels were never needed. */
.pickleball-cart-link__link {
	position: relative;
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: var(--wp--custom--radius--pill, 999px);
	color: var(--pb-cart-ink);
	text-decoration: none;
	transition:
		transform var(--wp--custom--duration--press, 160ms) var(--wp--custom--ease--out, cubic-bezier(0.23, 1, 0.32, 1)),
		background-color var(--wp--custom--duration--fast, 200ms) ease;
}

.pickleball-cart-link__icon {
	display: block;
}

/* Hover is gated: on a touch screen it would latch on after a tap and leave
 * the cart looking permanently pressed. Same rule as motion.css. */
@media (hover: hover) and (pointer: fine) {
	.pickleball-cart-link__link:hover {
		background-color: var(--pb-cart-hover);
	}
}

.pickleball-cart-link__link:active {
	transform: scale(0.94);
}

/* The count.
 *
 * Accent, not primary. Primary is the "Find a trip" button's fill, and two
 * dark pills 16px apart read as a pair of buttons rather than as a control and
 * its state. Accent appears nowhere else in the bar, which is the whole job of
 * a counter: be the one thing that changed. */
.pickleball-cart-link__count {
	position: absolute;
	top: 2px;
	inset-inline-end: 0;
	min-width: 18px;
	box-sizing: border-box;
	padding: 0 5px;
	border-radius: var(--wp--custom--radius--pill, 999px);
	background-color: var(--pb-cart-badge);
	color: var(--pb-cart-badge-ink);
	font-family: var(--pb-cart-display);
	font-size: 12px;
	font-weight: 700;
	line-height: 18px;
	text-align: center;
	font-variant-numeric: tabular-nums;
}

/* --- The header row's width budget ---------------------------------------
 *
 * The row is a nowrap flex of three children - logo, navigation, and the
 * cart-plus-button cluster - with a 24px gap set as a block attribute in
 * parts/header.html, and the navigation lays its own items out with a second
 * 24px gap. Between the drawer breakpoint and roughly 1000px the sum of those
 * asks for more width than the row has, and the overflow does not land
 * anywhere harmless: flex shrinks the navigation, the navigation's container
 * wraps, and one menu item drops onto a second line that makes the whole bar
 * half as tall again.
 *
 * WHAT IS BEING SHARED OUT, MEASURED AT 900px - the first pixel at which
 * style.css stops drawing the drawer and the desktop navigation appears, and
 * therefore the tightest viewport on the site. Row width 852px (900 less the
 * 24px root padding either side). Laid out at max-content the three children
 * want 929.64px:
 *
 *     logo                                    117.00
 *     row gap                                  24.00
 *     navigation                              596.75   six items 472.75,
 *                                                      five 24px gaps 120.00
 *     row gap                                  24.00
 *     cart 42 + 16 gap + button 109.89        167.89
 *                                           --------
 *                                             929.64   against 852 available
 *
 * Seventy-seven and a half pixels over. No single economy covers that, which
 * is why there are three below and why the My-account separator moved up to
 * 1000px rather than merely losing its padding: taking that rule's 25px away
 * and changing nothing else leaves the row 52px short and the menu still on
 * two lines. That was measured, at 900, 920 and 940, before any of this was
 * written - header 105.63px, 105.78px and 105.94px, six nav items at
 * y = 16, 16, 16, 16, 16, 64.
 *
 * The three economies, smallest visible cost first:
 *
 *   row gap 24 -> 16        16px   Invisible wherever there is slack. The row
 *                                  is justify-content: space-between, so this
 *                                  gap is a floor the three clusters are
 *                                  nowhere near until the row is already full.
 *   nav gap 24 -> 16        40px   Five gaps, so the largest single lever
 *                                  here. 16px is the spacing token below 24,
 *                                  not an invented number.
 *   My-account separator    25px   4px margin + 20px padding + 1px rule. The
 *                                  section at the foot of this file argues it.
 *                                  ------
 *                                   81px  against 77.64 needed
 *
 * Measured after, across the band in 10px steps: one row of six nav items at
 * every width from 900 to 999, header height 80.38px at 900 rising to 80.52px
 * at 999, and "Find a trip" back on one line (47.38px tall, from 70.75px).
 * Slack at the worst width, 900px: 3.36px. It widens quickly - 12.72px at 910,
 * 22.08px at 920, 49.84px at 950 - because the row grows with the viewport
 * while the labels do not.
 *
 * 3.36px IS THIN, AND SAYING SO IS PART OF THE FIX: at 900px exactly, one more
 * character in one label, or a seventh item, puts the bar back on two lines.
 * The next lever if that happens is the button's side padding, which the phone
 * band below already trims for the same reason - 22 -> 18 buys another 8px.
 * After that the honest answer is that six labels of this length do not fit
 * beside a logo, a cart and a button at 900px and the menu should hold five.
 *
 * At 1000px and above the full treatment is back - 24px gaps, separator and
 * all - with 15.66px of slack at 1000px, so the band above the cut is not
 * borrowing against the one below it. */
@media (max-width: 999.98px) {
	.is-site-header .wp-block-group.alignwide {
		gap: var(--wp--preset--spacing--20, 16px);
	}
}

/* The navigation's own gap, in the tight band only.
 *
 * Both the <nav> and its <ul> are named because core puts the block-gap
 * declaration on a generated layout class whose name is a hash of the block's
 * attributes - `.wp-container-core-navigation-is-layout-5dff3d62` as this is
 * written - and that hash changes the moment anybody edits the navigation
 * block in the site editor. Naming the hash would be a rule that quietly stops
 * applying with nobody having touched this file. Two descendant selectors
 * carry (0,2,0) against core's (0,1,0), which is enough to win without
 * !important and without depending on which of the two elements the generated
 * class lands on. */
@media (min-width: 900px) and (max-width: 999.98px) {
	.is-site-header .wp-block-navigation,
	.is-site-header .wp-block-navigation__container {
		gap: var(--wp--preset--spacing--20, 16px);
	}
}

/* The same budget again, one phone size down.
 *
 * Below 480px the row is tighter still, and two economies buy the line back:
 * both gaps down to 12px, and the button's side padding from 22px to 14px.
 * Measured at 360px with those in place - the row wants 310.38px against 320px
 * available, 9.62px of slack, and the bar is one line at 79.47px.
 *
 * A THIRD ECONOMY USED TO LIVE HERE AND HAS BEEN TAKEN OUT. The cart's target
 * was squeezed to 40px square to buy 2px, in a file that argues two rules
 * above that 42px is what makes it comfortable to hit - so the screens where
 * touch is the only input got the smallest target on the site. The 2px was not
 * needed. With the target back at 42px the bar is still one line from 352px up
 * (measured in 2px steps: 79.44px at 352, 101.88px at 350), which costs two
 * pixels of range at a width no phone reports - 320, 360, 375, 390, 414 and
 * 430 are the widths that exist, and the nearest of them, 360, keeps 9.62px of
 * slack.
 *
 * Below 352px it wraps, and every remaining fix takes something away from a
 * customer who is mid-booking. A two-line button on a 320px screen is the
 * accepted cost, not an oversight. */
@media (max-width: 479.98px) {
	.is-site-header .wp-block-group.alignwide,
	.is-site-header .wp-block-group.alignwide > .wp-block-group {
		gap: 12px;
	}

	.is-site-header .wp-block-button__link {
		padding-inline: 14px;
	}
}

/* --- My account, in the navigation ---------------------------------------
 *
 * It is in the nav post rather than beside the cart, and the budget above is
 * why: the right-hand cluster has no room for a second control on a phone, and
 * of the two the cart has the better claim on it - it is transient, it carries
 * state, and it is the one thing a customer needs to see without looking for
 * it. Below 900px the nav is a full-screen drawer, which is where a phone user
 * expects to find an account link anyway.
 *
 * But it is not a section of the site the way "All trips" and "FAQ" are, so
 * where there is room for it the item is set off behind a hairline instead of
 * sitting as the sixth peer in the list.
 *
 * WHY 1000px AND NOT 900px, WHERE THE DESKTOP BAR STARTS. The rule costs 25px,
 * and between 900 and 999 the row has not got 25px to spend on punctuation. It
 * used to take them anyway, and the result was the failure the budget section
 * above now measures: the menu wrapped, My account was orphaned onto a second
 * line, and the hairline whose whole purpose was to avoid a stray mark became
 * a floating vertical rule hanging at the start of that line. A separator that
 * causes the break it is drawn across is worse than no separator, so below
 * 1000px there is none and My account sits as a peer - which is exactly what
 * it is in the drawer below 900px in any case.
 *
 * :has() rather than nth-child or an added class: the item is identified by
 * where it goes, so re-ordering the menu in the site editor cannot leave the
 * hairline standing in front of "FAQ". */
@media (min-width: 1000px) {
	.is-site-header .wp-block-navigation__container > .wp-block-navigation-item:has(> a[href$="/my-account/"]) {
		margin-inline-start: 4px;
		padding-inline-start: 20px;
		border-inline-start: 1px solid var(--wp--preset--color--line, rgba(20, 40, 38, 0.12));
	}
}

@media (prefers-reduced-motion: reduce) {
	.pickleball-cart-link__link:active {
		transform: none;
	}
}

/* --- The mobile navigation drawer -----------------------------------------
 *
 * Below 900px the navigation collapses into core's full-screen overlay. Core
 * dresses it for a document; this dresses it for a phone. Every rule below is
 * here because the measured default was wrong on a 390px screen, not because
 * it could be prettier.
 *
 * WHY THE DRAWER HAD NO PADDING AT ALL. Core pads the overlay with
 * `clamp(1rem, var(--wp--style--root--padding-left), 20rem)` per side. theme.json
 * set the root padding top and bottom to "0" — unitless. Unitless zero is a
 * legal <length> for `padding` itself, which is why nothing else ever broke,
 * but it is NOT legal inside clamp(): that one invalid function invalidates the
 * whole `padding` shorthand, taking the left and right sides down with it even
 * though their own variable was a perfectly good 20px. The menu text therefore
 * started at x=0, hard against the edge of the glass. theme.json now says "0px"
 * (same computed value, valid in clamp), and the padding below is set here
 * explicitly anyway: a drawer's inset is a design decision and should not be an
 * emergent property of a root variable three files away.
 *
 * The inset is deliberately wider than the page's own 20px gutter. Page text
 * runs to a measure and wants the full width; six menu rows do not, and the
 * extra breathing room is what makes it read as a panel rather than as the
 * page with its content removed.
 *
 * Sizes: rows are a 56px minimum because 23px tall links are below every tap
 * target guideline there is, and the row — not the word — is the target, so
 * the whole width is tappable. Type goes to ~22px because the block's 16px is
 * run through fluid typography and lands at 14.15px on a 390px screen, which
 * is smaller than the body copy behind it.
 * ------------------------------------------------------------------------- */

@media (max-width: 899.98px) {

	.is-site-header .wp-block-navigation__responsive-container.is-menu-open {
		/* env() is 0 everywhere that has no notch, so the calc() is a no-op on
		 * a desktop browser and real inset on an iPhone. The viewport meta
		 * needs viewport-fit=cover for these to report anything — see the note
		 * at the end of this section. */
		padding:
			calc(env(safe-area-inset-top, 0px) + 8px)
			calc(env(safe-area-inset-right, 0px) + clamp(24px, 7vw, 36px))
			calc(env(safe-area-inset-bottom, 0px) + 32px)
			calc(env(safe-area-inset-left, 0px) + clamp(24px, 7vw, 36px));

		/* The overlay is its own scroll container (core sets overflow:auto for
		 * long menus). `contain` keeps its bounce but stops a drag at the end
		 * of the list from pulling the page behind it or firing Android's
		 * pull-to-refresh. */
		overscroll-behavior: contain;
	}

	/* The rows.
	 *
	 * Specificity note: core's own `padding: 0` on the item content scores
	 * 0,4,0 and its block stylesheet prints before this file, so matching it
	 * is not enough — the extra `__responsive-container-content` class takes
	 * these to 0,5,0 and wins on weight rather than with !important. */
	.is-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container {
		gap: 0;
		width: 100%;

		/* The hairlines are as wide as the list, and on a 768px tablet a rule
		 * running 696px under the word "FAQ" reads as a table, not a menu. The
		 * cap only bites above ~570px; a phone list is narrower than this and
		 * stays edge to edge. */
		max-width: 520px;
	}

	.is-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-item {
		width: 100%;
	}

	/* Hairlines, not gaps. A 24px void between six floating words gives the eye
	 * nothing to run down; a ruled list does, and it also makes the full-width
	 * tap target visible instead of merely present. First row has none: it
	 * would read as a border under the close button. */
	.is-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-item + .wp-block-navigation-item {
		border-top: 1px solid var(--wp--preset--color--line, rgba(20, 40, 38, 0.12));
	}

	.is-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-item__content {
		display: flex;
		align-items: center;
		width: 100%;
		min-height: 56px;
		padding-block: 10px;
		font-size: clamp(20px, 5.2vw, 24px);
		line-height: 1.25;
		letter-spacing: -0.01em;

		/* A menu row is a control, not prose: no 300ms double-tap wait, no grey
		 * flash over the press state, and no text selection when a thumb rests
		 * on it. Scoped to the drawer rather than set globally — body copy and
		 * order numbers on this site must stay selectable. */
		touch-action: manipulation;
		-webkit-tap-highlight-color: transparent;
		user-select: none;
		-webkit-user-select: none;
	}

	/* Press feedback, since the tap highlight above was just removed. Native
	 * controls answer on finger-down; :active is the only event that does.
	 * The row tints rather than scales: a 56px row scaling 0.97 drags its
	 * neighbours' hairlines with it. */
	.is-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:active {
		background-color: var(--wp--preset--color--base-sunken, rgba(20, 40, 38, 0.06));
	}

	/* Where am I. The drawer is the only place on mobile that can answer this,
	 * and core marks the current page for screen readers only. Underline rather
	 * than a colour swap alone, so it survives a colour-blind reading, and it
	 * echoes the desktop nav's own hover underline. */
	.is-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content[aria-current="page"] {
		color: var(--wp--preset--color--primary, #1b3b37);
		text-decoration: underline;
		text-decoration-thickness: 2px;
		text-underline-offset: 6px;
		text-decoration-color: var(--wp--preset--color--accent, #c7e86a);
	}

	/* The close button. 24x24 in the corner is both under the 44px target and,
	 * on a notched phone, partly under the status bar. It keeps its own hit
	 * area while the glyph stays 24px, and the negative margin pulls the
	 * optical edge of the icon back out to the drawer's inset so it lines up
	 * with the rows below it rather than floating 10px inside them. */
	.is-site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 44px;
		height: 44px;
		margin-inline-end: -10px;
		touch-action: manipulation;
		-webkit-tap-highlight-color: transparent;
	}

	/* The toggle that opens it has the same problem on the bar itself. */
	.is-site-header .wp-block-navigation__responsive-container-open {
		display: flex;
		align-items: center;
		justify-content: center;
		min-width: 44px;
		min-height: 44px;
		touch-action: manipulation;
		-webkit-tap-highlight-color: transparent;
	}
}

/* The rows animate in with a stagger (assets/css/motion.css). Nothing here
 * touches transform or opacity, so that still owns the entrance.
 *
 * NEEDS A REAL PHONE: the safe-area insets above report 0 until the viewport
 * meta carries viewport-fit=cover, and neither the insets nor the tap-highlight
 * and touch-action fixes reproduce in desktop device emulation. */
