/* MadHeader — base front-end styles.
   All tunables are CSS custom properties emitted inline by Dynamic_CSS (.mh-root{...}).
   Defaults below are fallbacks only, so the header still looks sane if the var block is absent. */

.mh-root {
	--mh-breakpoint: 782px;
	--mh-btn-size: 30px;
	--mh-btn-thickness: 2px;
	--mh-btn-gap: 7px;
	--mh-btn-color: #111112;
	--mh-btn-color-active: #ffffff;
	--mh-btn-top: 14px;
	--mh-btn-side: 16px;
	/* Total width the floating button occupies measured from its own edge of the viewport:
	   its inset plus its box. Derived, never emitted by Dynamic_CSS — custom properties
	   substitute at use time, so this tracks whatever the inline block sets those two to.
	   Anything else pinned to the button's side offsets by this to clear it. */
	--mh-btn-footprint: calc(var(--mh-btn-side) + var(--mh-btn-size) + 12px);
	--mh-drawer-width: 320px;
	--mh-drawer-bg: #111112;
	--mh-drawer-padding: 32px;
	--mh-overlay-color: #000000;
	--mh-overlay-opacity: 0.5;
	--mh-item-size: 18px;
	--mh-item-color: #d7d7d7;
	--mh-item-color-hover: #ffffff;
	--mh-item-gap: 14px;
	--mh-drawer-duration: 0.45s;
	--mh-drawer-ease: cubic-bezier(.22, 1, .36, 1);
	--mh-btn-duration: 0.25s;
	--mh-btn-ease: ease;
	--mh-overlay-duration: 0.4s;
	--mh-item-stagger: 60ms;
	--mh-item-duration: 0.5s;
	--mh-item-distance: 16px;
	--mh-bar-height: 60px;
	--mh-bar-bg: #ffffff;
	--mh-bar-opacity: 1;
	--mh-bar-blur: 0px;
	--mh-bar-logo-h: 32px;
	--mh-elem-color: #111112;
	--mh-elem-size: 22px;

	font-family: var(--mh-font, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif);
}

/* ======================  ICONS  ====================== */
/* Each icon context below sets `fill: currentColor` so a SOLID glyph takes the surrounding
   text colour. An OUTLINE icon (Lucide and anything Lucide-shaped) declares fill="none" and
   draws itself with stroke="currentColor" — filling one turns it into a solid blob.
   Honour that declaration globally: this outranks every per-context `fill: currentColor`
   (two classes + element vs one), and matches only icons that explicitly asked not to be
   filled, so solid icons are untouched. Add outline SVGs anywhere in the header and they
   stay outlines without needing a rule of their own. */
.mh-root svg[fill="none"] { fill: none; }

/* ======================  HEADER BAR  ====================== */

/* Bar background strip — logo and elements sit inside as absolute children.
   Sits BELOW the drawer so the drawer slides over it. Button floats separately above all. */
.mh-bar {
	position: fixed;
	top: 0; left: 0; right: 0;
	z-index: 400; /* below drawer (500) and overlay (490) */
	height: var(--mh-bar-height);
	box-sizing: border-box;
	background: color-mix(in srgb, var(--mh-bar-bg) calc(var(--mh-bar-opacity) * 100%), transparent);
	-webkit-backdrop-filter: blur(var(--mh-bar-blur));
	backdrop-filter: blur(var(--mh-bar-blur));
	transition: transform .25s ease;
}
.mh-root--bar-shadow .mh-bar { box-shadow: 0 1px 10px rgba(0, 0, 0, .08); }

/* Logo wrapper — absolute inside bar, centred by default. */
.mh-bar-logo {
	position: absolute;
	top: 0; bottom: 0;
	display: flex; align-items: center;
	left: 50%; transform: translateX(-50%);
	pointer-events: auto;
}
.mh-bar-logo a { display: inline-flex; align-items: center; }
.mh-bar-logo img { height: var(--mh-bar-logo-h); width: auto; display: block; }

/* Logo alignment overrides */
.mh-root--logo-left   .mh-bar-logo { left: 16px; transform: none; right: auto; }
.mh-root--logo-right  .mh-bar-logo { left: auto; right: 16px; transform: none; }
.mh-root--logo-center .mh-bar-logo { left: 50%; transform: translateX(-50%); right: auto; }

/* Action elements wrapper — absolute inside bar. Side determined by elem.side setting. */
.mh-bar-elems {
	position: absolute;
	top: 0; bottom: 0;
	display: flex; align-items: center; gap: var(--mh-elem-gap, 4px);
}
/* Inset matches --mh-btn-side (the button's own "Distance from side" setting) — so the
   elements cluster sits at the same distance from the edge as the button does, instead
   of a hardcoded 8px that looked pushed to the edge regardless of that setting.
   Auto (default): opposite the button. */
.mh-root--btn-right.mh-root--elems-auto .mh-bar-elems { left: var(--mh-btn-side); right: auto; }
.mh-root--btn-left.mh-root--elems-auto  .mh-bar-elems { right: var(--mh-btn-side); left: auto; }
/* Explicit overrides */
.mh-root--elems-left  .mh-bar-elems { left: var(--mh-btn-side); right: auto; }
.mh-root--elems-right .mh-bar-elems { right: var(--mh-btn-side); left: auto; }

/* Elements explicitly placed on the SAME side as the button start past the button instead of
   underneath it. Without this, both sit at --mh-btn-side from the same edge and overlap: the
   button is position:fixed at a higher z-index, so the elements end up buried under it.
   The extra gap follows the configured icon spacing but never drops below 8px, so tightening
   the spacing between icons can't push the nearest one back into the button. */
.mh-root--btn-right.mh-root--elems-right .mh-bar-elems {
	right: calc(var(--mh-btn-footprint) + max(var(--mh-elem-gap, 4px), 8px));
	left: auto;
}
.mh-root--btn-left.mh-root--elems-left .mh-bar-elems {
	left: calc(var(--mh-btn-footprint) + max(var(--mh-elem-gap, 4px), 8px));
	right: auto;
}

/* Action elements (icons) */
.mh-elem {
	display: inline-flex; align-items: center; justify-content: center;
	position: relative;
	width: calc(var(--mh-elem-size) + 12px); height: calc(var(--mh-elem-size) + 12px);
	color: var(--mh-elem-color) !important;
	background: transparent !important; border: 0 !important; cursor: pointer; text-decoration: none !important;
}
.mh-elem svg { width: var(--mh-elem-size); height: var(--mh-elem-size); fill: currentColor; stroke: currentColor; }
.mh-elem__img { width: var(--mh-elem-size); height: var(--mh-elem-size); object-fit: contain; }
.mh-elem__fa { font-size: var(--mh-elem-size); line-height: 1; display: inline-flex; align-items: center; color: inherit !important; }
.mh-elem__badge {
	position: absolute; top: 2px; right: 0;
	min-width: 16px; height: 16px; padding: 0 4px;
	font-size: 10px; line-height: 16px; font-weight: 700; text-align: center;
	color: #fff; background: #ef4444; border-radius: 999px;
}
/* Widget-sourced elements keep their own native markup and sizing — the fixed icon box
   only applies to the icon/FA/image sources. Cart and Search-icon are bare glyphs
   (no chrome of their own), so their colour variables are re-pointed at MadHeader's own
   --mh-elem-color to follow the header bar's configured colour, keeping them visually
   consistent with each other and with the plain icon/FA/image element slots. Login is
   deliberately excluded: it's a full branded button (red pill + label), not a bare
   glyph, so its own colour variables are its real design, not a mismatch to fix. */
.mh-elem--widget {
	display: inline-flex; align-items: center; justify-content: center;
	width: auto; height: auto;
	background: transparent; border: 0;
	--grx-wcart-icon: var(--mh-elem-color);
	--grx-wsearch-icon-color: var(--mh-elem-color);
}
/* Push the page down so the fixed bar doesn't overlap content (body class set by JS). */
body.mh-has-bar { padding-top: var(--mh-bar-height, 60px); }

/* ======================  IMAGE MENU (taptap-style grid)  ====================== */
.mh-imenu {
	display: grid;
	grid-template-columns: repeat(var(--mh-imenu-cols, 2), 1fr);
	gap: 10px;
	margin: var(--mh-menu-margin-top, 6px) 0 var(--mh-menu-margin-bottom, 6px);
}
.mh-imenu__tile {
	display: flex; flex-direction: column; align-items: center; gap: 8px;
	padding: 14px 8px;
	color: var(--mh-item-color, #d7d7d7) !important;
	text-decoration: none !important;
	border-radius: 10px;
	background: rgba(255, 255, 255, .06);
	transition: background .2s ease, color .2s ease;
}
.mh-imenu__tile:hover { background: rgba(255, 255, 255, .12); color: var(--mh-item-color-hover, #fff) !important; }
.mh-imenu__img {
	width: 100%; aspect-ratio: 16 / 10; border-radius: 8px;
	background-size: cover; background-position: center; background-color: #2a2d34;
}
.mh-imenu__img--blank { background: linear-gradient(135deg, #3a3d44, #23262c); }
.mh-imenu__icon { width: 40px; height: 40px; display: inline-flex; }
.mh-imenu__icon svg { width: 100%; height: 100%; fill: currentColor; }
.mh-imenu__label { font-size: 14px; font-weight: 600; text-align: center; }

/* A cell with children spans the full grid row so its text dropdown (same .sub-menu shape
   list mode uses) has room to open underneath the tile, instead of being cramped into one
   grid column. Plain (no-children) cells stay as normal grid items. */
.mh-imenu__cell--has-children { grid-column: 1 / -1; }
.mh-imenu__cell--has-children .mh-menu__row { align-items: stretch; }
.mh-imenu__cell--has-children .mh-imenu__tile { flex-direction: row; flex: 1 1 auto; justify-content: flex-start; }
.mh-imenu__cell--has-children .mh-imenu__img,
.mh-imenu__cell--has-children .mh-imenu__icon { flex: 0 0 auto; width: 40px; aspect-ratio: 1; }
.mh-imenu__cell .sub-menu { list-style: none; margin: 0; padding: 4px 0 0 16px; overflow: hidden; max-height: 0; transition: max-height var(--mh-drawer-duration) var(--mh-drawer-ease); }
.mh-imenu__cell .sub-menu li { margin: 0; }
/* Both the top-level cell AND any deeper <li> inside its dropdown can be "open" — same
   accordion rule at both levels, since submenus can nest arbitrarily deep. */
.mh-imenu__cell.mh-open > .sub-menu,
.mh-imenu__cell .sub-menu li.mh-open > .sub-menu { max-height: 1000px; }
.mh-imenu__cell.mh-open > .mh-menu__row .mh-submenu-toggle span,
.mh-imenu__cell .sub-menu li.mh-open > .mh-menu__row .mh-submenu-toggle span { transform: rotate(45deg); }

/* ---- Mobile-only: hidden by default, shown under the breakpoint ----
   .mh-root--always opts out (shows on all sizes). */
.mh-root { display: none; }
.mh-root--always { display: block; }
/* Body offset for the fixed bar (body.mh-has-bar, toggled by JS) is the exact-breakpoint
   source of truth, but JS only runs after DOMContentLoaded — between first paint and then,
   the fixed bar would overlap page content with no compensation ("content pulled up").
   These static-breakpoint fallbacks apply the SAME padding-top immediately via CSS, so the
   page is never unpadded even for that brief window; JS still refines to the exact
   --mh-breakpoint/--mh-breakpoint-tablet value once it runs. */
body:has(.mh-root--always.mh-root--has-bar) { padding-top: var(--mh-bar-height, 60px); }
@media (max-width: 782px) { /* static fallback; the real value is the var below */
	.mh-root--mobile_only { display: block; }
	body:has(.mh-root--mobile_only.mh-root--has-bar) { padding-top: var(--mh-bar-height, 60px); }
}
@media (max-width: 1024px) { /* static fallback for mobile+tablet; JS refines to --mh-breakpoint-tablet */
	.mh-root--mobile_tablet { display: block; }
	body:has(.mh-root--mobile_tablet.mh-root--has-bar) { padding-top: var(--mh-bar-height, 60px); }
}

/* ======================  BUTTON  ====================== */
/* Floating button — independently fixed, above everything. Every geometric property is
   !important so theme :hover rules (hello-elementor adds padding/border/transition to all
   buttons) cannot shift its position or size in any state. */
.mh-button,
.mh-button:hover,
.mh-button:focus,
.mh-button:active {
	position: fixed !important;
	top: var(--mh-btn-top) !important;
	z-index: 510 !important; /* button > drawer (500) > overlay (490) > bar (400) */
	display: inline-flex !important;
	align-items: center !important;
	justify-content: center !important;
	width: calc(var(--mh-btn-size) + 12px) !important;
	height: calc(var(--mh-btn-size) + 12px) !important;
	margin: 0 !important;
	padding: 0 !important;
	background: transparent !important;
	border: 0 !important;
	box-shadow: none !important;
	transform: none !important;
	translate: none !important;
	transition: none !important;
	outline: none !important;
	cursor: pointer !important;
	-webkit-tap-highlight-color: transparent;
	text-decoration: none !important;
	color: inherit !important;
	font-size: inherit !important;
	line-height: 1 !important;
	border-radius: 0 !important;
}
.mh-button:focus-visible { outline: 2px solid var(--mh-btn-color) !important; outline-offset: 2px !important; }
.mh-root--btn-right .mh-button,
.mh-root--btn-right .mh-button:hover,
.mh-root--btn-right .mh-button:focus,
.mh-root--btn-right .mh-button:active { right: var(--mh-btn-side) !important; left: auto !important; }
.mh-root--btn-left .mh-button,
.mh-root--btn-left .mh-button:hover,
.mh-root--btn-left .mh-button:focus,
.mh-root--btn-left .mh-button:active  { left: var(--mh-btn-side) !important;  right: auto !important; }

.mh-button__bars {
	position: relative;
	display: block;
	width: var(--mh-btn-size);
	height: calc(var(--mh-btn-thickness) * 3 + var(--mh-btn-gap) * 2);
}
.mh-button__bars span {
	position: absolute;
	left: 0;
	width: 100%;
	height: var(--mh-btn-thickness);
	background: var(--mh-btn-color);
	border-radius: 2px;
	transition: transform var(--mh-btn-duration) var(--mh-btn-ease),
		opacity var(--mh-btn-duration) var(--mh-btn-ease),
		background-color var(--mh-btn-duration) var(--mh-btn-ease);
}
.mh-button__bars span:nth-child(1) { top: 0; }
.mh-button__bars span:nth-child(2) { top: calc(var(--mh-btn-thickness) + var(--mh-btn-gap)); }
.mh-button__bars span:nth-child(3) { top: calc((var(--mh-btn-thickness) + var(--mh-btn-gap)) * 2); }

/* Thin style: lighter bars */
.mh-root--btn-style-thin .mh-button__bars span { height: 1px; }

/* Open state → morph to an X */
.mh-root.mh-active .mh-button__bars span { background: var(--mh-btn-color-active); }
.mh-root.mh-active .mh-button__bars span:nth-child(1) {
	top: calc(var(--mh-btn-thickness) + var(--mh-btn-gap));
	transform: rotate(45deg);
}
.mh-root.mh-active .mh-button__bars span:nth-child(2) { opacity: 0; }
.mh-root.mh-active .mh-button__bars span:nth-child(3) {
	top: calc(var(--mh-btn-thickness) + var(--mh-btn-gap));
	transform: rotate(-45deg);
}
/* Plus/cross style starts as a + (middle bar vertical-ish handled by rotate on open) */
.mh-root--btn-style-plus .mh-button__bars span:nth-child(2) { transform: rotate(90deg); transform-origin: center; }
.mh-root--btn-style-plus.mh-active .mh-button__bars span:nth-child(2) { transform: rotate(0deg); opacity: 1; }

/* --- Arrow: bars collapse into a back-arrow ( < ) on open --- */
.mh-root--btn-style-arrow.mh-active .mh-button__bars span:nth-child(1) {
	top: calc(var(--mh-btn-thickness) + var(--mh-btn-gap)); width: 55%; transform: rotate(-40deg) translateX(-1px);
}
.mh-root--btn-style-arrow.mh-active .mh-button__bars span:nth-child(2) { opacity: 1; transform: none; }
.mh-root--btn-style-arrow.mh-active .mh-button__bars span:nth-child(3) {
	top: calc(var(--mh-btn-thickness) + var(--mh-btn-gap)); width: 55%; transform: rotate(40deg) translateX(-1px);
}

/* --- Squeeze: top & bottom slide to centre then cross (origin-left feel) --- */
.mh-root--btn-style-squeeze .mh-button__bars span { transform-origin: left center; }
.mh-root--btn-style-squeeze.mh-active .mh-button__bars span:nth-child(1) { transform: rotate(45deg); top: 0; left: 4px; }
.mh-root--btn-style-squeeze.mh-active .mh-button__bars span:nth-child(3) { transform: rotate(-45deg); top: auto; bottom: 0; left: 4px; }

/* --- Spin: the whole icon rotates 180° while morphing to an X --- */
.mh-root--btn-style-spin .mh-button__bars { transition: transform var(--mh-btn-duration) var(--mh-btn-ease); }
.mh-root--btn-style-spin.mh-active .mh-button__bars { transform: rotate(180deg); }

/* ======================  OVERLAY  ====================== */
.mh-overlay {
	position: fixed;
	inset: 0;
	z-index: 490;
	background: var(--mh-overlay-color);
	opacity: 0;
	visibility: hidden;
	transition: opacity var(--mh-overlay-duration) ease, visibility 0s linear var(--mh-overlay-duration);
	cursor: pointer;
}
.mh-root.mh-active .mh-overlay {
	opacity: var(--mh-overlay-opacity);
	visibility: visible;
	transition: opacity var(--mh-overlay-duration) ease, visibility 0s;
}

/* ======================  DRAWER  ====================== */
/* Flex column: .mh-drawer no longer scrolls itself — .mh-drawer__inner (below) is the
   scrollable region, and .mh-drawer__sticky (when present) is a non-scrolling footer
   pinned to the bottom, so a "sticky" drawer widget can sit below an independently
   scrolling menu instead of scrolling away with it. */
.mh-drawer {
	position: fixed;
	z-index: 500;
	top: 0;
	bottom: 0;
	display: flex;
	flex-direction: column;
	width: var(--mh-drawer-width);
	max-width: 90vw;
	background: var(--mh-drawer-bg);
	box-sizing: border-box;
	overflow: hidden;
	transition: transform var(--mh-drawer-duration) var(--mh-drawer-ease),
		opacity var(--mh-drawer-duration) var(--mh-drawer-ease);
}
/* Slide positions (closed state) */
.mh-root--drawer-right .mh-drawer { right: 0; transform: translateX(100%); }
.mh-root--drawer-left .mh-drawer { left: 0; transform: translateX(-100%); }
/* Top / bottom sheets: sized to content but never taller than the viewport (scroll inside). */
.mh-root--drawer-top .mh-drawer { left: 0; right: 0; bottom: auto; width: 100%; max-width: none; max-height: 85vh; transform: translateY(-100%); }
.mh-root--drawer-bottom .mh-drawer { left: 0; right: 0; top: auto; width: 100%; max-width: none; max-height: 85vh; transform: translateY(100%); }
.mh-root--drawer-full .mh-drawer { inset: 0; width: 100%; max-width: none; opacity: 0; transform: none; visibility: hidden; }

/* Open state */
.mh-root.mh-active .mh-drawer { transform: translateX(0) translateY(0); }
.mh-root--drawer-full.mh-active .mh-drawer { opacity: 1; visibility: visible; }

/* Background image (::before) and tint (::after) as their own layers between the drawer's
   background COLOUR and its content. Keeping them separate is what lets a transparent PNG
   or a "contain" fit still show the colour behind it, and lets the tint be dialled up for a
   light photo without re-exporting the image. Both are inert when unconfigured: no image
   resolves to `none`, and the tint defaults to 0 opacity. */
.mh-drawer::before,
.mh-drawer::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
}
.mh-drawer::before {
	background-image: var(--mh-drawer-bg-image, none);
	background-size: var(--mh-drawer-bg-size, cover);
	background-position: var(--mh-drawer-bg-position, center center);
	background-repeat: var(--mh-drawer-bg-repeat, no-repeat);
	opacity: var(--mh-drawer-bg-opacity, 1);
}
.mh-drawer::after {
	background: var(--mh-drawer-scrim-color, #000);
	opacity: var(--mh-drawer-scrim-opacity, 0);
}
/* Content sits above both layers. Without this the image would paint over the menu, since
   the pseudo-elements come later in paint order than the drawer's non-positioned children. */
.mh-drawer__inner,
.mh-drawer__sticky {
	position: relative;
	z-index: 1;
}

/* Scrollable content region — everything except the sticky top/bottom slots.
   --mh-drawer-padding ("Content padding") is the real, single control for the menu's
   horizontal + vertical inset, matching its label. It won't necessarily line up under
   the (X) button unless Content padding is set to match the button's own side-distance —
   that's an admin choice, not something the CSS should silently force. */
.mh-drawer__inner {
	flex: 1 1 auto;
	min-height: 0; /* required for a flex child to actually shrink and scroll */
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	padding: var(--mh-drawer-padding);
	box-sizing: border-box;
	margin-top: 8px;
	padding-top: 28px; /* leaves room so content doesn't sit under the (X) button */
}
/* When a sticky-top widget is present, IT sits under the (X) button instead — the
   scrolling region no longer needs its own top clearance. */
.mh-drawer:has(.mh-drawer__sticky--top) .mh-drawer__inner { padding-top: var(--mh-drawer-padding); }

/* Sticky top/bottom slots — present only when a drawer widget's placement is "sticky".
   Never scroll with the menu; always pinned to the visual top/bottom edge of the drawer.
   Horizontal padding matches .mh-drawer__inner's (both driven by Content padding) so
   sticky content lines up with the menu above/below it. No divider line by default
   (kept borderless/minimal). */
.mh-drawer__sticky {
	flex: 0 0 auto;
	padding: var(--mh-drawer-padding);
	box-sizing: border-box;
}
.mh-drawer__sticky--top {
	padding-top: 28px; /* leaves room so content doesn't sit under the (X) button */
	padding-bottom: 0;
}
.mh-drawer__sticky--bottom {
	padding-top: 0;
}

/* Drawer widget (top/bottom slot) — the row holds one or two widgets side-by-side (e.g.
   Login next to Cart); placement/spacing variants live on the ROW, not the individual
   widget items, so both widgets in a slot always move together as one unit. "normal"
   needs no extra rule — it just sits in the menu's natural flow at the point
   drawer_widget() was called. */
.mh-drawer-widget-row {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 12px;
	margin: 0 0 16px;
}
.mh-drawer-widget-row--bottom { margin: 16px 0 0; }

.mh-drawer-widget-row--centred { justify-content: center; text-align: center; }

.mh-drawer-widget-row--spaced.mh-drawer-widget-row--top { margin-bottom: 32px; }
.mh-drawer-widget-row--spaced.mh-drawer-widget-row--bottom { margin-top: 32px; }

/* Sticky rows live outside the normal-flow margins above (they're inside
   .mh-drawer__sticky, which already has its own padding) — cancel the default margin
   so it doesn't double up with the sticky container's padding. */
.mh-drawer__sticky .mh-drawer-widget-row { margin: 0; }
.mh-drawer__sticky .mh-drawer-widget-row--centred { justify-content: center; }

/* Groxx Cart, specifically when placed as a drawer widget, gets a bordered "button" look
   so it visually pairs with Groxx Login's solid button in the same row — same height/
   radius/padding as Login's button box, but a soft thin border instead of a solid fill.
   Scoped to .mh-drawer-widget (MadHeader's own generic wrapper), so this doesn't touch
   how Cart looks as a header-bar element (.mh-elem--widget) or anywhere else it's used.
   Sets Cart's own themeable box-chrome variables (see .grx-wcart in groxx-core's
   widgets.css) rather than fighting its base rule with raw property overrides. */
.mh-drawer-widget .grx-wcart {
	--grx-wcart-justify: center;
	--grx-wcart-height: 44px;
	--grx-wcart-padding-x: 18px;
	--grx-wcart-radius: 4px;
	--grx-wcart-border: 1px solid rgba(255, 255, 255, .28);
	--grx-wcart-bg: transparent;
}
.mh-drawer-widget .grx-wcart:hover,
.mh-drawer-widget .grx-wcart:focus {
	--grx-wcart-border: 1px solid rgba(255, 255, 255, .5);
	--grx-wcart-bg: rgba(255, 255, 255, .06);
}
/* groxx-core hides Cart's "Cart" text below 782px ("icon + badge only on small screens")
   for its compact header-bar context — but MadHeader's drawer only ever renders at those
   same narrow widths, so that rule always fires here too, hiding the label even though
   the drawer has plenty of room for it. Restore it specifically for the drawer widget. */
.mh-drawer-widget .grx-wcart__label { display: inline !important; }

/* A lone widget in the row stretches to fill the full drawer width (e.g. Search's own
   internal width:100% needs a full-width flex item to actually fill, or it just shrinks
   to content and looks narrow). Two widgets side by side instead each hug their own
   natural content width (Login's pill button, Cart's compact icon+count), so they sit
   compactly next to each other rather than each stretching to half the row. */
.mh-drawer-widget-row--single > .mh-drawer-widget { flex: 1 1 auto; min-width: 0; }
.mh-drawer-widget-row--paired > .mh-drawer-widget { flex: 0 0 auto; }

/* ======================  MENU  ====================== */
.mh-menu {
	list-style: none;
	margin: var(--mh-menu-margin-top, 0) 0 var(--mh-menu-margin-bottom, 0);
	padding: 0;
}
.mh-menu li { margin: 0; }
/* Row wrapper: keeps the link and its submenu toggle on ONE flex row, side by side —
   a float couldn't reliably sit next to the link's own flex box and would drop onto
   its own line, which is what caused the toggle to appear detached/misaligned. Shared by
   the list menu AND the image-grid menu's text submenus (any depth), so both reuse the
   same link/toggle/accordion styling instead of duplicating it. */
.mh-menu__row { display: flex; align-items: center; }
.mh-menu a,
.mh-imenu__cell .sub-menu a {
	display: flex;
	align-items: center;
	flex: 1 1 auto;
	min-width: 0;
	gap: 10px;
	padding: var(--mh-item-gap) 0;
	font-size: var(--mh-item-size);
	color: var(--mh-item-color) !important;
	text-decoration: none !important;
	transition: color .2s ease;
}
.mh-menu a:hover,
.mh-menu a:focus,
.mh-imenu__cell .sub-menu a:hover,
.mh-imenu__cell .sub-menu a:focus { color: var(--mh-item-color-hover) !important; }
.mh-root--divider .mh-menu > li + li { border-top: 1px solid rgba(255, 255, 255, .08); }
.mh-menu .sub-menu { list-style: none; margin: 0; padding: 0 0 0 16px; overflow: hidden; max-height: 0; transition: max-height var(--mh-drawer-duration) var(--mh-drawer-ease); }
.mh-menu li.mh-open > .sub-menu { max-height: 1000px; }
.mh-menu__icon { display: inline-flex; width: 1.1em; height: 1.1em; }
.mh-menu__icon svg { width: 100%; height: 100%; fill: currentColor; }
.mh-menu-empty { color: var(--mh-item-color); opacity: .8; font-size: 14px; }

/* Submenu toggle — a bare chevron, no button box/border/background, styled like the
   Groxx Hero slider's nav arrows (.grx-hero__arrow): just a glyph that shifts opacity/colour
   on hover. No rotation/motion — closed shows a down chevron, open swaps to an up chevron,
   an instant state change (same idea as a plain +/- disclosure, just arrow-shaped).
   Lives in the same flex row as the link (see .mh-menu__row), never floated. */
.mh-submenu-toggle {
	display: flex; align-items: center; justify-content: center;
	flex: 0 0 auto;
	width: 24px; height: 24px;
	margin: 0; padding: 0;
	background: transparent !important; border: 0 !important; box-shadow: none !important;
	cursor: pointer;
	color: var(--mh-item-color);
	opacity: .7;
	transition: opacity .16s ease, color .16s ease;
}
.mh-submenu-toggle:hover,
.mh-submenu-toggle:focus-visible { opacity: 1; color: var(--mh-item-color-hover); }
.mh-submenu-toggle span {
	display: block; width: 9px; height: 9px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg); /* chevron pointing down, closed state */
}
/* Expanded: swap to a chevron pointing up — no animation, just the open/closed glyph. */
.mh-menu li.mh-open > .mh-menu__row > .mh-submenu-toggle span,
.mh-imenu__cell.mh-open > .mh-menu__row > .mh-submenu-toggle span,
.mh-imenu__cell .sub-menu li.mh-open > .mh-menu__row > .mh-submenu-toggle span { transform: rotate(-135deg); }

/* ======================  MULTI-LEVEL (DRILL-DOWN) MENU  ====================== */
/* Each level is a full-width panel stacked on the previous one. Only the panel you're
   currently on is visible; the ones above it stay mounted (so going back is instant and
   keeps scroll position) but hidden. Depth is unlimited — a level-3 panel is absolutely
   positioned against its level-2 parent, which resolves to exactly the same box, so the
   rules below apply identically however deep the menu goes.

   Why visibility and not display/opacity: `visibility` is inheritable, so hiding a panel's
   rows automatically hides everything nested inside them, and a deeper panel can opt back
   in with a single `visible` — no per-level bookkeeping. It also drops the panel out of the
   tab order, which opacity alone would not. */
.mh-drill {
	position: relative;
	overflow: hidden;
	transition: height var(--mh-drawer-duration) var(--mh-drawer-ease);
}
/* Level 0 stays in normal flow so the container has a natural height before JS measures. */
.mh-drill > .mh-menu { position: relative; }

/* Levels must resolve their top:0/left:0 against .mh-drill, never against the row that
   opened them. The item-reveal animation puts a transform on every root <li>, and ANY
   transform other than `none` makes an element a containing block for absolutely positioned
   descendants — so with it in place, drilling into the 5th item opened that level two-thirds
   of the way down the drawer, with anything past the container's measured height clipped.
   Drill-down therefore reveals with opacity only; the stagger delay still applies, and the
   accordion keeps the horizontal slide. */
.mh-root .mh-drill .mh-menu > li,
.mh-root.mh-active .mh-drill .mh-menu > li { transform: none; }

/* Applied for a single repaint while the drawer closes, so returning to the top level is
   instant instead of visibly sliding back through every open level on the way out. */
.mh-drill--instant,
.mh-drill--instant .sub-menu { transition: none !important; }

.mh-drill .sub-menu {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	max-height: none;  /* undo the accordion's collapsed height */
	overflow: visible; /* the accordion clips to animate height; here .mh-drill owns clipping */
	padding: 0;
	transform: translateX(100%);
	visibility: hidden;
	/* Hiding is delayed by the slide duration so a level leaving to the right stays on
	   screen for the whole animation instead of blinking out at the first frame. */
	transition: transform var(--mh-drawer-duration) var(--mh-drawer-ease),
		visibility 0s linear var(--mh-drawer-duration);
}
/* Open = this level is the current one or an ancestor of it. Ancestors must sit at x=0 too:
   a nested panel is a DOM descendant, so an ancestor left at translateX(100%) would carry
   the visible panel off-screen with it. */
.mh-drill .sub-menu.mh-panel--open {
	transform: translateX(0);
	visibility: visible;
	transition: transform var(--mh-drawer-duration) var(--mh-drawer-ease), visibility 0s;
}

/* Rows are hidden per-panel, then re-shown only for the current panel — that's what leaves
   ancestors mounted-but-invisible while their descendant panel shows through. The two
   directions need different timing, which is why "hidden" is split into two rules:
     - going back, the level sliding out must stay readable until it's gone  → delayed
     - going deeper, the level being covered must vanish at once, or it shows
       through the incoming panel for the length of the slide                 → immediate */
.mh-drill .mh-menu > li,
.mh-drill .sub-menu > li {
	visibility: hidden;
	transition: visibility 0s linear var(--mh-drawer-duration);
}
.mh-drill .mh-panel--current > li {
	visibility: visible;
	transition: visibility 0s;
}
.mh-drill .mh-panel--open:not(.mh-panel--current) > li {
	visibility: hidden;
	transition: visibility 0s;
}

/* Chevron points the way the panel will move (right) instead of down, and never rotates —
   in drill-down there is no in-place "expanded" state for it to indicate. */
.mh-drill .mh-submenu-toggle span { transform: rotate(-45deg); }
.mh-drill .mh-menu li.mh-open > .mh-menu__row > .mh-submenu-toggle span { transform: rotate(-45deg); }

/* Back row — a full-width button that reads "‹ Parent name", so it says where you're
   returning to rather than a bare "Back". */
.mh-menu__back { margin: 0 0 4px; }
.mh-back {
	display: flex;
	align-items: center;
	gap: 4px;
	width: 100%;
	margin: 0;
	padding: var(--mh-item-gap) 0;
	background: transparent !important;
	border: 0 !important;
	box-shadow: none !important;
	cursor: pointer;
	font-size: var(--mh-item-size);
	font-family: inherit;
	text-align: left;
	color: var(--mh-item-color);
	opacity: .75;
	transition: opacity .16s ease, color .16s ease;
}
.mh-back:hover,
.mh-back:focus-visible { opacity: 1; color: var(--mh-item-color-hover); }
/* The glyph is centred inside a box rather than being the box, for the same reason
   .mh-submenu-toggle is: a 9px square with 2px borders is an 11px border-box, and rotating it
   45deg grows its bounding box to ~15.6px. Drawn at its natural size it sat flush against the
   panel's left edge and .mh-drill's overflow clip shaved ~2.3px off the tip. The 24px box
   matches the right-hand toggles, so both chevrons share one hit-area size. */
.mh-back__arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
}
.mh-back__arrow::before {
	content: "";
	display: block;
	width: 9px;
	height: 9px;
	border-left: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg); /* chevron pointing left */
}

/* ======================  GROUP LABELS (mh-title menu items)  ====================== */
/* A menu item given the mh-title CSS class becomes a caption, not a destination: no link,
   no hover colour, no submenu toggle. The rule beside it is a flex spacer, so it always
   fills exactly the leftover width whatever the label says. */
.mh-title {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: calc(var(--mh-item-gap) + 6px) 0 var(--mh-item-gap);
}
.mh-title__inner {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	flex: 0 0 auto;
	font-size: var(--mh-title-size, 13px);
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--mh-title-color, #8a8a8f);
}
.mh-title__icon { display: inline-flex; width: 1.1em; height: 1.1em; }
.mh-title__icon svg { width: 100%; height: 100%; fill: currentColor; }
.mh-title__line { display: none; }
.mh-root--title-rule .mh-title__line {
	display: block;
	flex: 1 1 auto;
	height: 1px;
	background: currentColor;
	color: var(--mh-title-color, #8a8a8f);
	opacity: .35;
}
/* A group label is a row, not a link, so the divider-lines option shouldn't draw one above
   it — the label's own rule already separates the group. */
.mh-root--divider .mh-menu > li.mh-title { border-top: 0; }
/* In the image grid a label spans the full row instead of becoming a tile. */
.mh-imenu__cell--title { grid-column: 1 / -1; }

/* ======================  TOP LINKS  ====================== */
/* Up to three short links on the drawer's fixed top row. Sits in the same sticky slot as the
   inline logo, so it never scrolls with the menu. */
.mh-toplinks {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--mh-toplink-gap, 16px);
	min-height: calc(var(--mh-btn-size) + 12px); /* matches the close button's box height */
}
.mh-toplinks--align-left   { justify-content: flex-start; }
.mh-toplinks--align-centre { justify-content: center; }
.mh-toplinks--align-right  { justify-content: flex-end; }
/* Auto = the side opposite the close (X) button, so the two never collide. */
.mh-root--btn-right .mh-toplinks--align-auto { justify-content: flex-start; }
.mh-root--btn-left  .mh-toplinks--align-auto { justify-content: flex-end; }

.mh-toplink {
	font-size: var(--mh-toplink-size, 13px);
	line-height: 1.2;
	color: var(--mh-toplink-color, #fff) !important;
	text-decoration: none !important;
	opacity: .85;
	transition: opacity .16s ease, border-color .16s ease, background-color .16s ease;
}
.mh-toplink:hover,
.mh-toplink:focus-visible { opacity: 1; }

.mh-toplinks--button .mh-toplink {
	padding: 6px 14px;
	border: 1px solid currentColor;
	border-radius: 999px;
	opacity: .7;
}
.mh-toplinks--button .mh-toplink:hover,
.mh-toplinks--button .mh-toplink:focus-visible {
	opacity: 1;
	background: rgba(255, 255, 255, .08);
}

/* When top links and the inline logo share the sticky row, keep them on separate lines —
   both want the full width and would otherwise squeeze each other. */
.mh-toplinks + .mh-brand--inline_x { margin-top: 8px; }

/* ======================  ITEM REVEAL ANIMATION  ====================== */
.mh-root .mh-menu > li {
	opacity: 0;
	transform: translateX(var(--mh-item-distance));
	transition: opacity var(--mh-item-duration) var(--mh-drawer-ease),
		transform var(--mh-item-duration) var(--mh-drawer-ease);
}
.mh-root--drawer-left .mh-menu > li { transform: translateX(calc(var(--mh-item-distance) * -1)); }
.mh-root.mh-active .mh-menu > li { opacity: 1; transform: translateX(0); }
/* Stagger: each item delayed by index * stagger (custom props set per-item by JS). */
.mh-root.mh-active .mh-menu > li { transition-delay: calc(var(--mh-i, 0) * var(--mh-item-stagger)); }

/* ======================  BRANDING (logo + heading)  ====================== */
/* "above_menu" placement: sits in the menu's normal scrolling flow, with admin-configurable
   gaps above (from the drawer's top edge) and below (before the menu list starts) — replaces
   the old hardcoded 18px-bottom-only spacing. */
.mh-brand--above_menu { margin: var(--mh-brand-space-above, 0) 0 var(--mh-brand-space-below, 18px); }
/* "inline_x" placement: a fixed row next to the close button — never scrolls, slides open/
   closed with the drawer. Vertically centred on the same top offset as the (X) button. */
.mh-brand--inline_x {
	display: flex;
	align-items: center;
	min-height: calc(var(--mh-btn-size) + 12px); /* matches the button's own box height */
}
.mh-brand--inline_x.mh-brand--side-left  { justify-content: flex-start; }
.mh-brand--inline_x.mh-brand--side-right { justify-content: flex-end; }
/* Auto = opposite the close button's own side. */
.mh-root--btn-right .mh-brand--inline_x.mh-brand--side-auto { justify-content: flex-start; }
.mh-root--btn-left  .mh-brand--inline_x.mh-brand--side-auto { justify-content: flex-end; }

/* The close (X) button is position:fixed at a VIEWPORT edge (button.position), while the
   drawer is its own fixed-width panel sliding in from its OWN edge (drawer.position) — when
   those sides don't match, the X sits outside the drawer's box entirely and no amount of
   justify-content can visually align the logo next to it. Fall back to simply giving the
   sticky-top row enough top clearance to sit BELOW the X's full footprint (top offset +
   button box height) instead of trying to sit beside it. */
.mh-root--btn-right.mh-root--drawer-left .mh-drawer__sticky--top,
.mh-root--btn-left.mh-root--drawer-right .mh-drawer__sticky--top {
	padding-top: calc(var(--mh-btn-top) + var(--mh-btn-size) + 12px + 12px);
}

.mh-brand__logo {
	display: block;
	max-width: var(--mh-logo-max, 120px);
	max-height: var(--mh-drawer-logo-max-h, 40px);
	width: auto;
	height: auto;
	margin-bottom: 10px;
}
.mh-brand--inline_x .mh-brand__logo { margin-bottom: 0; }
.mh-brand__heading {
	font-size: var(--mh-heading-size, 22px);
	font-weight: 800;
	line-height: 1.15;
	color: var(--mh-heading-color, #fff);
}
.mh-brand__sub { font-size: 14px; opacity: .75; color: var(--mh-heading-color, #fff); margin-top: 2px; }

/* ======================  SEARCH  ====================== */
.mh-search { position: relative; margin: 0 0 16px; }
.mh-search__icon {
	position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
	width: 18px; height: 18px; color: var(--mh-item-color, #d7d7d7); opacity: .6; pointer-events: none;
}
.mh-search__icon svg { width: 100%; height: 100%; }
.mh-search:has(.mh-search__icon) .mh-search__input { padding-left: 38px; }
.mh-search__input {
	width: 100%;
	box-sizing: border-box;
	padding: 10px 14px;
	font-size: 15px;
	color: var(--mh-item-color, #d7d7d7);
	background: rgba(255, 255, 255, .08);
	border: 1px solid rgba(255, 255, 255, .15);
	border-radius: 8px;
}
.mh-search__input::placeholder { color: var(--mh-item-color, #d7d7d7); opacity: .6; }

/* ======================  WIDGETS  ====================== */
.mh-widgets { margin: 16px 0; }
.mh-widget { margin-bottom: 16px; color: var(--mh-item-color, #d7d7d7); }
.mh-widget__title { font-size: 13px; text-transform: uppercase; letter-spacing: .04em; opacity: .7; margin: 0 0 8px; color: var(--mh-item-color, #d7d7d7); }
.mh-widgets a { color: var(--mh-item-color-hover, #fff); }

/* ======================  SMART-SCROLL  ====================== */
.mh-root.mh-hide-button .mh-button,
.mh-root.mh-hide-button .mh-bar {
	opacity: 0;
	transform: translateY(-150%);
	pointer-events: none;
	transition: opacity .25s ease, transform .25s ease;
}

/* Lock body scroll while open (class added by JS). */
body.mh-scroll-lock { overflow: hidden; }

/* ======================  SMALL PHONES (≤360px)  ====================== */
@media (max-width: 360px) {
	/* Side drawers fill almost the whole screen so content isn't cramped. */
	.mh-root--drawer-left .mh-drawer,
	.mh-root--drawer-right .mh-drawer { width: 88vw; max-width: 88vw; }
	/* Trim the inner padding a touch on tiny screens. */
	.mh-drawer { padding: clamp(16px, calc(var(--mh-drawer-padding) - 8px), var(--mh-drawer-padding)); }
	/* Keep the heading from overflowing. */
	.mh-brand__heading { font-size: clamp(18px, var(--mh-heading-size), 26px); }
}

/* Long words / URLs in menu labels or widgets never force horizontal scroll. */
.mh-menu a,
.mh-widget,
.mh-brand__heading,
.mh-brand__sub { overflow-wrap: anywhere; word-break: break-word; }

/* Respect reduced-motion. */
@media (prefers-reduced-motion: reduce) {
	.mh-root *,
	.mh-root .mh-menu > li { transition-duration: 0.001s !important; }
}
