/* Printeez Header block — styled to mirror the app's public header
 * (apps/print_simple_web: layouts/public_root.html.heex + css/header.scss).
 * Loads front-end AND editor (block `style` handle), so the editor previews
 * the real bar layout around the live slot previews.
 *
 * Anatomy (children of .ps-header, template order = DOM order):
 *   .ps-header-toggle     hidden checkbox — the pure-CSS mobile menu state,
 *                         the same mechanism the app header uses
 *   .ps-header-hamburger  its <label>, three bars animating to an X
 *   .ps-header-logo       core/site-logo
 *   .ps-header-nav        the custom menu block (off-canvas panel on mobile)
 *   .ps-header-search     the search block (display:contents): its fit box
 *                         with the inline field — measured by the app's
 *                         search runtime, which marks the header
 *                         .search-collapsed when the box is too narrow —
 *                         and, collapsed, its stacked behavior's full-width
 *                         last row or its overlay behavior's icon in the box
 *   .ps-header-selector   the warehouse selector block, when an author adds
 *                         one (not in the template since 2.18.0); starts the
 *                         right cluster via margin-left:auto
 *   .ps-header-slot--logged-out / --logged-in
 *                         the auth button groups (server-gated hidden;
 *                         header-view.js reveals one); the first visible one
 *                         starts the right cluster when there is no selector
 *
 * Breakpoint 819px matches the app's header collapse point. Colors are
 * plain values mirroring the app's rendered tokens (no skin-token system
 * exists WP-side): text #020912 (--color-fill), border #e5e5e5, bg #fff.
 */

.ps-header {
	position: sticky;
	top: 0;
	z-index: 999;
	display: flex;
	align-items: center;
	gap: 1rem;
	width: 100%;
	box-sizing: border-box;
	padding: 1rem 0.5rem;
	background: #ffffff;
	border-bottom: 1px solid #e5e5e5;
}

.ps-header *,
.ps-header *::before,
.ps-header *::after {
	box-sizing: border-box;
}

/* --- WP admin bar (logged-in admins) --------------------------------------
   WP pushes the page down with html{margin-top}, but a sticky bar must
   offset its own `top` too or it slides under the fixed admin bar on
   scroll. The height var ships with WP's front-end admin-bar styles
   (32px, 46px ≤782px); logged-out pages have neither the class nor the
   var, so this is a no-op for visitors. */
body.admin-bar .ps-header {
	top: var(--wp-admin--admin-bar--height, 32px);
}

@media (max-width: 600px) {
	/* Below 600px WP's admin bar is position:absolute and scrolls away
	   with the page, so the header sticks to the real viewport top. */
	body.admin-bar .ps-header {
		top: 0;
	}
}

@media (min-width: 820px) {
	.ps-header {
		padding: 1rem 1.5rem;
		gap: 3rem;
	}
}

/* --- Checkbox + hamburger (app: header-navigation-toggle/-trigger) ------ */

.ps-header .ps-header-toggle {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
}

.ps-header .ps-header-hamburger {
	display: none;
	flex-direction: column;
	justify-content: center;
	gap: 6px;
	padding: 0.5rem;
	cursor: pointer;
}

.ps-header .ps-header-hamburger span {
	display: inline-flex;
	width: 24px;
	height: 1.5px;
	background: #020912;
	transform-origin: center;
	transition: all 0.3s ease-in-out;
}

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

.ps-header .ps-header-logo {
	flex: 0 0 auto;
	margin: 0;
}

.ps-header .ps-header-logo img {
	width: 100%;
	max-width: 120px;
	height: auto;
	display: block;
}

/* --- Nav (desktop inline; mobile off-canvas below) ------------------------ */

.ps-header .ps-header-nav {
	min-width: 0;
}

/* Desktop: the nav is content-sized (app parity: `.header-main` is
   `w-auto`), so the bar's free space is the search fit box's — that box
   is what the search runtime measures, and the split must not depend on
   the state (a growing nav would halve the box and collapse the field
   early). The right cluster is pinned by the box's auto margin, or by the
   first auth slot's when there is no search block (see the right cluster). */
@media (min-width: 820px) {
	.ps-header .ps-header-nav {
		display: flex;
		justify-content: flex-start;
		flex: 0 1 auto;
		min-width: 0;
	}

	/* The menu block is width:100% by default; inside the nav it must
	   shrink-wrap or there is nothing to center. */
	.ps-header .ps-header-nav .wp-block-custom-printeez-custom-menu {
		width: auto;
	}
}

/* --- Search ---------------------------------------------------------------
   The block root is `display: contents`, so its parts are the bar's own
   flex items: the fit box (the inline field, and the overlay's trigger)
   and, for the stacked behavior, the stacked field. The box is what
   header_search_fit.js (in the app's search_embed.js) measures — flex-basis
   0, a fixed minimum, a maximum, its content hidden or shown by the state
   below — so its width is the free space the menu and the buttons leave and
   never depends on what it shows. It takes the right cluster's auto margin;
   whatever follows it gives its own up, so the field sits against the
   buttons. Mirrors `header > .global-search` in the app's header.scss.
   On a phone with the stacked behavior the box collapses to nothing (the
   phone rules below): it shows no field and no trigger there, and the
   collapse is unconditional, so its icon-wide minimum only pushed the
   buttons off the bar. */

.ps-header .ps-header-search {
	display: contents;
}

.ps-header .printeez-search__box {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	/* The search yields before the menu (as in the app): a real basis with
	   a heavy shrink factor makes this box absorb the bar's shortfall down
	   to its icon-wide minimum before the nav (flex-shrink 1) gives up a
	   pixel — so the field stacks or becomes its icon first, and the nav's
	   priority+ "More" (navigation-menu-view.js fitRow, which reads the
	   nav's clientWidth) folds only after that. With a basis of 0 the box
	   could never shrink and the nav yielded first. */
	flex: 1 100 28rem;
	min-width: 2.5rem;
	max-width: 28rem;
	margin-left: auto;
}

.ps-header .ps-header-search ~ .ps-header-selector,
.ps-header .ps-header-search ~ .ps-header-slot {
	margin-left: 0;
}

.ps-header .printeez-search__inline {
	width: 100%;
}

/* Collapsed — the inline field has no room (`search-collapsed`, set by the
   measurement) and always below 768px, the field's own phone line: the
   inline field goes; the stacked field becomes a full-width row under the
   bar, the overlay's trigger shows in the box, beside the buttons. The row
   is absolutely positioned at the header's bottom with the header's padding
   reserving its height (the field's h-12, h-10 from 768px, plus a 1rem gap
   from the bar, on top of the bar's own 1rem) — NOT a wrapped flex row: nothing in
   this state may change another item's width or line, or the measurement
   feeds on its own decision and the header shakes; `flex-wrap` would let
   the buttons wrap too whenever the bar is tight. While the phone menu is
   open the stacked field goes away: the panel starts at the header's
   bottom edge, so the field would stay visible above it with its results
   trapped underneath. The same rules twice, for the class and for the
   media query: plain CSS, no mixins. The hidden-by-default side of these
   lives in search.embed.css, so a block outside a header never shows them. */

.ps-header.search-collapsed .ps-header-search .printeez-search__inline {
	display: none;
}

.ps-header.search-collapsed .printeez-search--overlay .search-field-trigger {
	display: inline-flex;
}

.ps-header.search-collapsed .ps-header-search .printeez-search__stacked {
	display: block;
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0.5rem;
	padding: 0 0.5rem;
}

.ps-header.search-collapsed:has(.printeez-search__stacked) {
	padding-bottom: calc(1rem + 2.5rem + 1rem);
}

.ps-header.search-collapsed .ps-header-toggle:checked ~ .ps-header-search .printeez-search__stacked {
	display: none;
}

.ps-header.search-collapsed:has(.ps-header-toggle:checked) {
	padding-bottom: 1rem;
}

@media (min-width: 820px) {
	.ps-header.search-collapsed .ps-header-search .printeez-search__stacked {
		padding: 0 1.5rem;
	}
}

@media (max-width: 767px) {
	.ps-header .ps-header-search .printeez-search__inline {
		display: none;
	}

	.ps-header .printeez-search--overlay .search-field-trigger {
		display: inline-flex;
	}

	.ps-header .ps-header-search .printeez-search__stacked {
		display: block;
		position: absolute;
		left: 0;
		right: 0;
		bottom: 1rem;
		padding: 0 0.5rem;
	}

	/* Stacked behavior: the box is empty here (the inline field is gone,
	   the stacked field is its own row), so it gives up its icon-wide
	   minimum — a 2.5rem item plus the bar's gap was 3.5rem of a phone bar
	   spent on nothing, pushing the buttons past the edge. It stays in the
	   flow at zero width: its auto margin still pins the right cluster and
	   the fit observer still has a box (width 0 reads as collapsed, which
	   the rules here apply anyway). The overlay behavior keeps the minimum
	   for its trigger. */
	.ps-header:has(.printeez-search__stacked) .printeez-search__box {
		flex: 0 0 0;
		min-width: 0;
	}

	.ps-header:has(.printeez-search__stacked) {
		padding-bottom: calc(1rem + 3rem + 1rem);
	}

	.ps-header .ps-header-toggle:checked ~ .ps-header-search .printeez-search__stacked {
		display: none;
	}

	.ps-header:has(.ps-header-toggle:checked) {
		padding-bottom: 1rem;
	}
}

/* --- Right cluster: selector + auth buttons ------------------------------- */

/* Whatever starts the right cluster takes the auto margin: the selector when
   an author added one, else the auth slot (the hidden one is display:none,
   so only the revealed slot's margin counts). Belt-and-suspenders with the
   nav's flex-grow above on desktop; on phones, where the nav is off-canvas
   and the stacked search is on its own row, this is what pins the cluster
   to the right of the logo. A slot after a selector gets no margin, or the
   two auto margins would split the free space and float the selector mid-bar. */
.ps-header .ps-header-selector,
.ps-header .ps-header-slot {
	margin-left: auto;
}

.ps-header .ps-header-selector ~ .ps-header-slot {
	margin-left: 0;
}

.ps-header .ps-header-slot {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	flex: 0 0 auto;
}

.ps-header .ps-header-slot .wp-block-buttons {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	flex-wrap: nowrap;
}

.ps-header .ps-header-slot .wp-block-button__link {
	padding: 0.5rem 0.75rem;
	font-size: 0.875rem;
	white-space: nowrap;
}

@media (min-width: 1024px) {
	.ps-header .ps-header-slot .wp-block-button__link {
		padding: 0.5rem 1.25rem;
		font-size: 0.9rem;
	}
}

/* --- Drawer auth slots ----------------------------------------------------
   The off-canvas panel's own logged-in / logged-out pair, living INSIDE the
   nav group (the bar's ps-header-slot groups are siblings of the panel and
   stay in the bar, free for other buttons). Desktop never shows them: the
   bar already carries its auth cluster. */

.ps-header .ps-header-drawer-slot {
	display: none;
}

@media (max-width: 819px) {
	/* The reveal script clears the inline display:none on exactly one slot,
	   restoring this. Separated from the bar slots' rule so the two can
	   diverge without one inheriting the other's layout. */
	.ps-header .ps-header-drawer-slot {
		display: block;
		margin-top: 1.5rem;
		padding-top: 1.25rem;
		border-top: 1px solid #e5e5e5;
	}

	.ps-header .ps-header-drawer-slot .wp-block-buttons {
		display: flex;
		flex-direction: column;
		gap: 0.75rem;
	}

	/* Full-bleed drawer actions — the panel is a list, not a toolbar. */
	.ps-header .ps-header-drawer-slot .wp-block-button {
		width: 100%;
	}

	.ps-header .ps-header-drawer-slot .wp-block-button__link {
		display: block;
		width: 100%;
		padding: 0.75rem 1rem;
		text-align: center;
		white-space: nowrap;
	}
}

/* --- Mobile (≤819px, the app's collapse point) ----------------------------
   The checkbox precedes every slot as a direct sibling, so `:checked ~`
   reaches the nav and the hamburger exactly like the app's CSS does. */

@media (max-width: 819px) {
	.ps-header .ps-header-hamburger {
		display: inline-flex;
	}

	/* Anchored to the header itself (absolute in the sticky bar, top:100%),
	   not to the viewport — so the panel always starts exactly where the
	   bar ends, whatever pushes the bar around (WP admin bar, sticky vs.
	   in-flow). Height = viewport minus the bar (100% = the header's own
	   height) minus the admin bar when present. */
	.ps-header .ps-header-nav {
		position: absolute;
		top: 100%;
		/* Full viewport bleed regardless of how the theme wraps the header:
		   template parts commonly sit inside an alignfull has-global-padding
		   constrained group, so the header's own box — the panel's absolute
		   containing block — is inset from the viewport by the root padding
		   and left:0/right:0 can never reach the edges. Center-anchor, span
		   the viewport, pull half of it back. width:100vw is safe here: the
		   body scrollbar is gone while the panel is open (scroll lock below). */
		left: 50%;
		width: 100vw;
		max-width: none;
		margin: 0 0 0 -50vw;
		z-index: 999;
		height: calc(100vh - 100% - var(--wp-admin--admin-bar--height, 0px));
		overflow-y: auto;
		padding: 1rem;
		background: #ffffff;
		transform: translateX(-100%);
		opacity: 0;
		pointer-events: none;
		transition: all 0.3s ease-in-out;
	}

	.ps-header .ps-header-toggle:checked ~ .ps-header-nav {
		transform: translateX(0);
		opacity: 1;
		pointer-events: auto;
		z-index: 999999;
	}

	/* Hamburger → X. Adjacent bar centers sit 7.5px apart (1.5px bar +
	   6px gap), so each outer bar translates that far onto the middle bar
	   FIRST, then rotates (rightmost transform applies first). The reverse
	   order translated along the already-rotated axis, skewing the X
	   off-center. */
	.ps-header .ps-header-toggle:checked ~ .ps-header-hamburger span:nth-child(1) {
		transform: translateY(7.5px) rotate(45deg);
	}

	.ps-header .ps-header-toggle:checked ~ .ps-header-hamburger span:nth-child(2) {
		opacity: 0;
	}

	.ps-header .ps-header-toggle:checked ~ .ps-header-hamburger span:nth-child(3) {
		transform: translateY(-7.5px) rotate(-45deg);
	}
}

/* Scroll lock while the mobile menu is open (app: body overflow hidden). */
body:has(.ps-header .ps-header-toggle:checked) {
	overflow: hidden;
}
