/*
Theme Name: GreenerRoute
Theme URI: https://greenerroute.com
Author: Bello Group Limited
Description: Custom lightweight block theme for GreenerRoute.com. Mobile-first, minimal-JS, built against the Phase 2 design system (see docs/design-system.md).
Version: 0.9.36
Requires at least: 6.4
Requires PHP: 8.0
Tested up to: 6.6
Requires Plugins: woocommerce
Text Domain: greenerroute
*/

:root {
	/* Widened from 240px: long category names (e.g. "All Board and Half
	   Board Envelopes") plus the submenu indent were overflowing the
	   rail's own width and forcing a horizontal scrollbar inside it. */
	--gr-sidebar-width: 300px;
}

/* Mobile-first product grid: 1 column on phone (<600px), 2 on tablet
   (600–959px), 4 on desktop (960px+). The product-collection block's own
   "columns" attribute is a single fixed value, so the responsive
   step-up is handled here instead. */
.wp-block-woocommerce-product-collection .wc-block-product-template {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--wp--preset--spacing--40);
}

@media (min-width: 600px) {
	.wp-block-woocommerce-product-collection .wc-block-product-template {
		grid-template-columns: repeat(2, 1fr);
		gap: var(--wp--preset--spacing--50);
	}
}

@media (min-width: 960px) {
	.wp-block-woocommerce-product-collection .wc-block-product-template {
		grid-template-columns: repeat(4, 1fr);
	}
}

/* Star rating, first thing under the image on every product card (shop
   grid + best sellers — both use the exact same card format now). A
   product with no reviews yet gets the empty-star/"Rate now" fallback
   below instead of WooCommerce's own default of rendering nothing. */
.gr-card-rating {
	margin-bottom: var(--wp--preset--spacing--10);
	font-size: 1.75rem; /* 2x the previous --font-size--small (0.875rem) */
}

.gr-rating-empty {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--10);
	height: 100%;
	line-height: 1;
	color: var(--wp--preset--color--muted);
	text-decoration: none;
}

.gr-rating-empty:hover {
	color: var(--wp--preset--color--accent);
}

.gr-rating-empty__stars {
	display: inline-flex;
	gap: 1px;
}

.gr-rating-empty__cta {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	text-decoration: underline;
}

/* Single card shadow token, single border-radius — no mixed styles. */
.wc-block-product-template .wc-block-product,
.product-summary {
	border-radius: 4px;
}

/* Breathing room between title, rating, and price on the product page —
   these were relying on core blocks' own default margins, which read as
   cramped this close together. */
.product-summary .wp-block-woocommerce-product-rating,
.product-summary .gr-rating-empty {
	margin-top: var(--wp--preset--spacing--30);
	margin-bottom: var(--wp--preset--spacing--10);
}

.product-summary .gr-product-price {
	margin-top: var(--wp--preset--spacing--30);
}

/* Explicit px match to .gr-card-title's computed size (20px) — swapping
   fontSize preset tokens ("xx-large" -> "x-large") on the post-title
   block didn't actually shrink it as expected (some other rule with
   higher specificity kept winning), so this sets the real pixel value
   directly instead of relying on a token name. */
.gr-product-title {
	font-size: 20px !important;
}

.gr-product-short-description {
	margin-top: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--muted);
}

/* Add to cart wrapper: WooCommerce (and the Stripe/PayPal plugins hooked
   into woocommerce_before_add_to_cart_form / woocommerce_after_add_to_cart_form)
   print several distinct pieces here — stock notice, the shipment-time ETA
   line, the <form class="cart"> itself, then the payment-method buttons —
   as flat siblings inside this one wrapper. A single-row flex (the previous
   rule) squeezed all of them onto one line, crushing the Add to Cart button.
   Stacking as a column instead gives each its own row, in source order:
   stock -> ETA -> add-to-cart form -> payment buttons. */
.gr-product-add-to-cart {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--wp--preset--spacing--20);
	margin: var(--wp--preset--spacing--40) 0;
}

.gr-product-add-to-cart .stock {
	margin: 0;
}

.gr-product-add-to-cart form.cart {
	/* !important on both: WooCommerce core sets this <form> to
	   display:grid AND flex-wrap:wrap — the wrap in particular silently
	   dropped the quantity box onto its own second line instead of beside
	   the button, since the two together are wider than this column. */
	display: flex !important;
	flex-wrap: nowrap !important;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
}

.gr-product-add-to-cart .single_add_to_cart_button {
	order: 1;
	flex: 1 1 auto;
	min-width: 0;
	/* !important: overrides WooCommerce's own button height. */
	height: 44px !important;
	padding: 0 var(--wp--preset--spacing--50);
	font-size: var(--wp--preset--font-size--medium);
}

.gr-product-add-to-cart .quantity {
	order: 2;
	flex: 0 0 auto;
	display: flex;
	align-items: stretch;
	height: 44px;
	box-sizing: border-box;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 4px;
	overflow: hidden;
}

/* Same WooCommerce behaviour as the card grid, same fix (see the matching
   .gr-card-cart-wrap rule): min stock == max stock (1 left) renders the
   qty field as type="hidden" instead of a stepper. Keep the box and show
   a static "1" rather than collapsing it, so the button stays the same
   width whether or not this product happens to have exactly 1 in stock. */
.gr-product-add-to-cart .quantity:has(input[type="hidden"]) {
	justify-content: center;
	align-items: center;
	width: 48px;
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
}

.gr-product-add-to-cart .quantity:has(input[type="hidden"])::after {
	content: "1";
}

.gr-product-add-to-cart .qty {
	width: 48px;
	height: 100%;
	box-sizing: border-box;
	border: 0;
	text-align: center;
	font-size: var(--wp--preset--font-size--medium);
	-moz-appearance: textfield;
}

.gr-product-add-to-cart .qty::-webkit-inner-spin-button,
.gr-product-add-to-cart .qty::-webkit-outer-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

.gr-product-add-to-cart .gr-qty-btn {
	width: 36px;
	height: 100%;
	box-sizing: border-box;
}

/* Shipment time — sits directly under Add to Cart, same muted small-text
   treatment as other secondary product-page info. */
.gr-shipment-time {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
	margin: 0 0 var(--wp--preset--spacing--40) 0;
}

.wc-block-product-template .wc-block-product {
	box-shadow: 0 1px 2px rgba(28, 32, 27, 0.06);
	padding: var(--wp--preset--spacing--30);
	/* !important: WooCommerce's own "columns-N" class (from the block's
	   displayLayout attribute) sets a percentage width sized for its flex
	   layout — that's what we're overriding to CSS Grid below, but the
	   card itself kept that percentage width, so it sat far short of its
	   actual grid cell instead of filling it. */
	width: 100% !important;
	box-sizing: border-box;
}

/* main's direct children (breadcrumb, query-title, product grid, etc.)
   otherwise get their own independent max-width + auto-margin centering
   from WP's "constrained" layout support, layered on TOP of main's own
   padding — the same double-indent bug hit on .site-nav-row earlier in
   this file. main's own padding is enough on its own. */
main.wp-block-group > * {
	max-width: none !important;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

/* main itself is a single full-bleed element (padding but no separate
   centering layer), while the utility/header/value-props bars each use
   an outer full-width wrapper + an auto-centered inner row. Above the
   1280px content-size breakpoint that meant main's content (e.g. the
   breadcrumb) sat 24px from main's own edge while the logo/nav sat
   ~24px from a centered edge further right — two different reference
   points. Centering main the same way makes both land at the same spot. */
main.wp-block-group {
	max-width: var(--wp--style--global--content-size, 1280px);
	margin-left: auto !important;
	margin-right: auto !important;
}

/* Footer content (copyright, links, cookie-manage) was flush-padded 24px
   from the viewport edge instead of aligned with the 1280px content
   column everything else uses — the footer block has no separate
   centering layer, just its own padding. Reusing the same max()-based
   padding formula as .site-nav-row: reproduces the padded-outer +
   centered-inner two-step math in one element, correct at every width
   (including the 1280–1328px band where a plain max-width+margin:auto
   would diverge from a padding-only approach), and still correct after
   the sidebar's own margin-left shifts the whole footer right in
   side-mode, since 100% here is footer's own (already-shifted) width. */
.site-footer {
	padding-left: max( var(--wp--preset--spacing--50), calc( ( 100% - var(--wp--style--global--content-size, 1280px) ) / 2 ) );
	padding-right: max( var(--wp--preset--spacing--50), calc( ( 100% - var(--wp--style--global--content-size, 1280px) ) / 2 ) );
}

/* Single product: gallery + summary side by side from tablet up. Scoped
   to .product-top-grid specifically (not the whole main), so the details
   tabs and "related products" section below stay full-width instead of
   being auto-placed into this same two-column grid — see the comment in
   single-product.html for why that broke when main itself was the grid. */
.product-top-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--wp--preset--spacing--60);
}

@media (min-width: 782px) {
	.product-top-grid {
		grid-template-columns: 1.1fr 0.9fr;
		align-items: start;
	}
}

/* ==========================================================================
   Utility bar (above header): account, cart, secondary links
   ========================================================================== */

.utility-bar {
	background: var(--wp--preset--color--tint);
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--50);
}

.utility-nav .wp-block-navigation__container > .wp-block-navigation-item > a {
	padding: var(--wp--preset--spacing--10) var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--muted);
}

.utility-account-link {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--10);
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	margin-right: var(--wp--preset--spacing--30);
}

.utility-cart .wc-block-mini-cart__button {
	height: 24px;
}

/* ==========================================================================
   Value-props bar (below header): trust/delivery highlights
   ========================================================================== */

.value-props-bar {
	background: var(--wp--preset--color--tint);
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--50);
	box-shadow: 0 4px 8px -4px rgba(28, 32, 27, 0.12);
	position: relative;
	z-index: 1;
}

.value-prop {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--ink);
}

.value-prop svg {
	flex-shrink: 0;
	color: var(--wp--preset--color--accent);
}

.value-prop span {
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
}

/* ==========================================================================
   Header: logo, mega-menu, layout toggle
   ========================================================================== */

.site-wordmark.wp-block-site-logo img {
	height: 84px;
	width: auto;
	max-width: none;
}

/* The header-bar's underline used to live directly on .site-header-bar,
   which is width-constrained (centered, max 1280px) — so the line stopped
   short of the real viewport edges. It now lives on this outer wrapper,
   which (like .utility-bar/.value-props-bar) is the actual full-width box;
   .site-header-bar is just the padded, centered row inside it. */
.site-header-bar-outer {
	border-bottom: 1px solid var(--wp--preset--color--border);
	/* Same fix as .site-header-bar below, one level up: this element is a
	   child of .site-header ("constrained"), so it was still being
	   auto-centered to max-width:1280 instead of being the genuinely
	   full-width box its own comment above assumes it already is — the
	   root cause of .site-header-bar's width being short by however much
	   this element itself was inset by, at any viewport wider than 1280px. */
	max-width: none !important;
	margin-left: 0 !important;
	margin-right: 0 !important;
	/* .utility-bar/.value-props-bar (both full-bleed, like this) carry
	   their own 24px padding, and their *inner* row (which only centers to
	   1280, no padding of its own) sits inside that already-padded area.
	   .site-header-bar below used to carry the padding itself AND center
	   to 1280 in the same step — which caps its *content* width at
	   1280-48=1232 instead of a true 1280, shifting the logo/toggle an
	   extra 24px inward on each side versus the other three bars. Moving
	   the padding out here (so .site-header-bar only centers, no padding
	   of its own) reproduces their exact two-step math instead. */
	padding-left: var(--wp--preset--spacing--50);
	padding-right: var(--wp--preset--spacing--50);
	box-sizing: border-box;
}

.site-header-bar {
	/* Centers within .site-header-bar-outer's already-padded interior —
	   see the comment there. No padding of its own now. */
	max-width: var(--wp--style--global--content-size, 1280px) !important;
	margin-left: auto !important;
	margin-right: auto !important;
	box-sizing: border-box;
}

/* Header controls (search, layout toggle) share one height so they align
   on the same row instead of the browser's mismatched default sizing.
   Padding/icon/font are rescaled to fit the 40px box too — just capping
   the height alone left the default (~56px-button) padding and a 25px
   icon fighting for space inside it. */
.site-header-bar .wp-block-search__inside-wrapper {
	height: 40px;
	box-sizing: border-box;
	display: flex;
	align-items: center;
	/* The input/button were filling the wrapper's entire interior right up
	   to its own border with zero inset, so text/icon visually touched the
	   box edge — this padding gives them breathing room inside it. */
	padding: 3px;
}

.site-header-bar .wp-block-search__input,
.site-header-bar .wp-block-search__button {
	height: 100%;
	box-sizing: border-box;
}

.site-header-bar .wp-block-search__input {
	font-size: var(--wp--preset--font-size--small);
	padding: 0 var(--wp--preset--spacing--30);
	/* The theme's global line-height (1.6) makes an inherited text line
	   taller than this 40px box and pushes the placeholder toward the
	   bottom edge — reset to normal so it centers instead. */
	line-height: normal;
}

.site-header-bar .wp-block-search__button {
	padding: var(--wp--preset--spacing--20);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: normal;
}

.site-header-bar .wp-block-search__button svg {
	/* !important: core's block-library CSS sets min-width/min-height:24px
	   on this icon, which floors any smaller width/height regardless of
	   !important on those alone — has to override the min- versions too. */
	width: 18px !important;
	height: 18px !important;
	min-width: 18px !important;
	min-height: 18px !important;
}

.nav-layout-toggle,
.nav-layout-toggle__btn {
	height: 40px;
	box-sizing: border-box;
}

.wc-block-mini-cart__button {
	height: 32px;
	box-sizing: border-box;
}

/* Cart count badge: default WC sizing (25px circle, 17.5px digits) reads
   oversized against the 30px basket icon, and sits mostly on top of it
   rather than in the corner — shrink it proportionate to the icon and
   nudge it further right so it reads as a corner badge, not an overlay. */
.wc-block-mini-cart__quantity-badge {
	position: relative;
}

.wc-block-mini-cart__badge {
	width: 16px !important;
	height: 16px !important;
	min-width: 16px !important;
	font-size: 10px !important;
	line-height: 16px !important;
	padding: 0 !important;
	top: -4px !important;
	right: -8px !important;
	display: flex;
	align-items: center;
	justify-content: center;
}

.wc-block-mini-cart__amount {
	font-size: var(--wp--preset--font-size--x-small);
	font-family: var(--wp--preset--font-family--primary);
	font-weight: 600;
}

.nav-layout-toggle__btn {
	display: inline-flex;
	align-items: center;
}

/* Full-bleed + max()-based padding instead of relying on WP's built-in
   "constrained" layout centering directly on this element. A plain
   max-width:1280+margin:auto (what removing max-width:none would leave
   active here) only matches .site-header-bar's padded-outer/centered-inner
   math when the viewport is wide enough for both to hit the same 1280px
   cap (>=1328px) — below that they diverge by up to 24px, since this row
   has no separate full-bleed "outer" wrapper the way the header bar does.
   The max() formula reproduces that two-step math in a single element at
   every width: 24px padding once the 1280 column no longer needs the
   difference to center, growing to keep centering once it does. Side-mode
   overrides all of this anyway (see html.nav-layout-side .site-nav-row
   below), so it's a no-op there either way. */
.site-nav-row {
	max-width: none !important;
	margin-left: 0 !important;
	margin-right: 0 !important;
	padding-left: max( var(--wp--preset--spacing--50), calc( ( 100% - var(--wp--style--global--content-size, 1280px) ) / 2 ) );
	padding-right: max( var(--wp--preset--spacing--50), calc( ( 100% - var(--wp--style--global--content-size, 1280px) ) / 2 ) );
}

.site-nav .wp-block-navigation__container > .wp-block-navigation-item > a,
.site-nav .wp-block-navigation__container > .wp-block-navigation-submenu > .wp-block-navigation-item__content {
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--20);
	font-weight: 600;
}

/* Mega-menu dropdown panel, Xerox-style: clean card, no arrows/carets clutter. */
.site-nav .wp-block-navigation__submenu-container {
	border-radius: 4px;
	border: 1px solid var(--wp--preset--color--border);
	box-shadow: 0 4px 16px rgba(28, 32, 27, 0.08);
	padding: var(--wp--preset--spacing--20) 0;
	min-width: 220px;
}

/* Menu item hover: greenerroute.com's existing button blue (#0170B9),
   per Fabien's request — distinct from the green accent used everywhere
   else, deliberately only on this hover state. */
.site-nav .wp-block-navigation-item > a:hover,
.site-nav .wp-block-navigation-submenu > .wp-block-navigation-item__content:hover,
.utility-nav .wp-block-navigation-item > a:hover {
	background-color: #0170b9;
	color: #fff;
}

/* Clearance: pushed to the far right of the nav row (flex auto-margin) and
   coloured red year-round so it reads as urgent/discount, distinct from the
   rest of the menu. Desktop dropdown flex layout only — the mobile overlay
   accordion stacks items vertically, where a right push would look broken,
   so it's scoped out there. */
.site-nav .wp-block-navigation__container > .clearance-nav-link {
	margin-left: auto;
}

/* Class repeated on the selector to out-specificity core's
   .wp-block-navigation .wp-block-navigation-item__content.wp-block-navigation-item__content
   { color: inherit } rule (three chained classes) — two classes plus a
   type selector loses to that on specificity alone, regardless of source order. */
.site-nav .clearance-nav-link > a.wp-block-navigation-item__content {
	color: #d32f2f;
}

.wp-block-navigation__responsive-container.is-menu-open .clearance-nav-link {
	margin-left: 0;
}

/* Mobile hamburger overlay: submenus expand as an inline accordion
   (pushing the rest of the menu down) instead of the desktop dropdown's
   absolutely-positioned flyout, which — inside the narrow overlay — was
   shifting content off to the right rather than opening cleanly. The
   desktop dropdown (outside the overlay) is untouched, since that
   flyout behaviour is fine in top-menu mode. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
	position: static !important;
	width: 100% !important;
	box-shadow: none !important;
	border: 0 !important;
	border-radius: 0 !important;
	padding-left: var(--wp--preset--spacing--40) !important;
	min-width: 0 !important;
}

/* Below tablet width, the side-menu toggle serves no purpose — the mobile
   hamburger already handles navigation there, and the fixed rail itself
   is disabled at this width (see the max-width:781px block below). */
@media (max-width: 781px) {
	.nav-layout-toggle {
		/* !important: the unconditional .nav-layout-toggle{display:...}
		   rule further down this file has equal specificity and comes
		   later in source order, so it wins the cascade tie otherwise. */
		display: none !important;
	}
}

.nav-layout-toggle {
	display: inline-flex;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 4px;
	overflow: hidden;
	margin-left: var(--wp--preset--spacing--30);
}

.nav-layout-toggle__btn {
	border: 0;
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--x-small);
	font-family: inherit;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	cursor: pointer;
}

.nav-layout-toggle__btn[aria-pressed="true"] {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--paper);
}

/* Side-menu layout: the same nav markup becomes a fixed left rail via CSS
   only, so no template restructuring is needed to support both modes.
   The rail also carries its own logo (hidden in top-mode, shown here) —
   sized/positioned using the same measured bar heights used elsewhere in
   this file (utility bar ≈44px, header-bar row ≈117px, value-props bar
   ≈56px) so two things line up with the shifted-right main content:
     - the logo's own bottom border lands at the same height as the
       header-bar-outer's underline (44 + 117 = 161px)
     - the links list starts 56px below that (161 + 56 = 217px), matching
       where the value-props bar ends and page content (e.g. a breadcrumb)
       begins in the main column. */
.side-nav-logo {
	display: none;
}

html.nav-layout-side .site-nav-row {
	position: fixed;
	top: 0;
	left: 0;
	width: var(--gr-sidebar-width);
	height: 100vh;
	display: flex;
	flex-direction: column;
	/* Without this, the empty spacer divs (and anything else without its
	   own explicit width) collapse to 0 width and float centered instead
	   of filling the rail — align-items defaults to center here via WP's
	   own block-support CSS otherwise. */
	align-items: stretch;
	/* Zeroed explicitly: theme.json's blockGap (24px) auto-applies as
	   margin-top between this block and its previous sibling in <header>,
	   which offsets the whole fixed rail down by that amount — throwing
	   off the height math this whole section relies on. */
	margin-top: 0;
	padding: 0;
	gap: 0;
	border-right: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--paper);
	z-index: 100;
}

/* The WP admin toolbar is ALSO position:fixed at top:0 with a higher
   z-index, so when logged in it was overlapping and hiding the first 32px
   of the sidebar (the top of the utility spacer + logo) rather than
   pushing the sidebar down below it. WordPress adds the .admin-bar class
   to <body> whenever it's showing, at a height of 32px above 782px wide
   and 46px below it (mirroring its own responsive breakpoint). */
html.nav-layout-side body.admin-bar .site-nav-row {
	top: 32px;
	height: calc(100vh - 32px);
}

@media (max-width: 782px) {
	html.nav-layout-side body.admin-bar .site-nav-row {
		top: 46px;
		height: calc(100vh - 46px);
	}
}

/* Original header-bar logo is replaced by the rail's own copy below. */
html.nav-layout-side .site-header-bar .site-wordmark {
	display: none;
}

/* Keeps the header-bar-outer's underline at a consistent height whether or
   not the logo (its tallest content) is present in it. Also switches from
   space-between to flex-end: with the logo hidden, only one child is left
   in the row, and space-between just left-aligns a single item instead of
   pushing it to the right — which is what made search/toggle drift away
   from the cart/value-props right edge in side-menu mode. */
html.nav-layout-side .site-header-bar {
	min-height: 117px;
	justify-content: flex-end;
}

.side-nav-spacer {
	display: none;
}

html.nav-layout-side .side-nav-spacer {
	display: block;
	flex-shrink: 0;
	background: var(--wp--preset--color--tint);
}

/* !important: .site-nav-row still carries WP's "constrained" layout
   class, whose generated CSS centers every direct child via
   `max-width` + `margin-left/right: auto !important` — which beats
   align-items:stretch and collapses these empty/content-sized elements
   to a 0-width column floating in the middle instead of filling the
   rail. Has to be fought with !important here too. */
html.nav-layout-side .site-nav-row > * {
	max-width: none !important;
	margin: 0 !important;
	width: 100% !important;
	box-sizing: border-box !important;
}

html.nav-layout-side .side-nav-spacer--utility {
	/* --gr-utility-height is set by nav-layout.js from the real utility
	   bar's measured height — see the comment there for why this moved
	   away from a hardcoded pixel guess (font rendering / sub-pixel
	   rounding could differ enough between browsers or widths to throw a
	   fixed value off by a couple of px). The 42.53125px fallback only
	   matters for the instant before that JS runs. */
	height: var(--gr-utility-height, 42.53125px);
}

html.nav-layout-side .side-nav-spacer--value-props {
	height: var(--gr-valueprops-height, 56px);
	box-shadow: 0 4px 8px -4px rgba(28, 32, 27, 0.12);
	position: relative;
	z-index: 1;
}

html.nav-layout-side .side-nav-logo {
	display: flex;
	align-items: center;
	justify-content: center;
	/* Matches the real header-bar's own height (see --gr-utility-height
	   comment above — same reasoning), so the logo sits at the same scale
	   it does in the header bar rather than floating oversized in a
	   mismatched box. */
	height: var(--gr-header-height, 117px);
	padding: 0 var(--wp--preset--spacing--40);
	border-bottom: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--paper);
	flex-shrink: 0;
	box-sizing: border-box;
}

html.nav-layout-side .side-nav-logo img {
	height: auto;
	width: 150px;
	max-width: 100%;
}

/* Side-menu mode uses the independent .gr-cat-accordion widget instead of
   core/navigation's dropdown — hide one, show the other, per mode. */
.gr-cat-accordion-root {
	display: none;
}

html.nav-layout-side .site-nav {
	display: none;
}

html.nav-layout-side .gr-cat-accordion-root {
	display: block;
	flex: 1;
	overflow-y: auto;
	overflow-x: hidden;
	padding: var(--wp--preset--spacing--40);
	/* The utility/logo/value-props spacers above already total 217px
	   (44 + 117 + 56); this 24px is the same blockGap-driven margin that
	   lands above the breadcrumb in the main column, so links line up
	   with it exactly rather than falling short by that same amount. */
	margin-top: 24px;
}

.gr-cat-accordion,
.gr-cat-accordion__children {
	list-style: none;
	margin: 0;
	padding: 0;
}

.gr-cat-accordion__row {
	display: flex;
	align-items: stretch;
	background-color: transparent;
}

.gr-cat-accordion__link {
	flex: 1;
	display: flex;
	align-items: center;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	white-space: normal;
}

/* Green only on hover or when the item is the open/selected one — not as
   a permanent resting background. */
.gr-cat-accordion__row:hover,
.gr-cat-accordion__item.is-open > .gr-cat-accordion__row {
	background-color: var(--wp--preset--color--tint);
}

.gr-cat-accordion__count {
	margin-left: var(--wp--preset--spacing--10);
	font-weight: 400;
	color: var(--wp--preset--color--muted);
}

.gr-cat-accordion__toggle {
	width: 44px;
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	border: 0;
	border-left: 1px solid var(--wp--preset--color--paper);
	background: transparent;
	color: var(--wp--preset--color--ink);
	cursor: pointer;
}

.gr-cat-accordion__toggle:hover,
.gr-cat-accordion__item.is-open > .gr-cat-accordion__row .gr-cat-accordion__toggle {
	background-color: var(--wp--preset--color--tint);
}

.gr-cat-accordion__toggle svg {
	transition: transform 0.2s ease-in-out;
}

.gr-cat-accordion__item.is-open > .gr-cat-accordion__row .gr-cat-accordion__toggle svg {
	transform: rotate(180deg);
}

/* Collapsed by default (0 height, clipped) — expanded via the is-open
   class the click handler in category-accordion.js toggles. A max-height
   transition (rather than an instant display swap) gives the smooth
   slide open/closed. */
.gr-cat-accordion__children {
	max-height: 0;
	overflow: hidden;
	transition: max-height 0.3s ease;
	padding-left: var(--wp--preset--spacing--40);
}

.gr-cat-accordion__item.is-open > .gr-cat-accordion__children {
	max-height: 1000px;
}

.gr-cat-accordion__item:not(:last-child) .gr-cat-accordion__row {
	border-bottom: 1px solid var(--wp--preset--color--paper);
}

/* The bars themselves stay full-width (background spans behind the
   sidebar too, reading as one continuous strip) — only their inner content
   row shifts right, so it doesn't sit underneath the sidebar's own content.
   !important: same reason as elsewhere in this file — WP's per-block
   generated layout-support CSS (a unique wp-container-core-group-is-layout-*
   class) sets its own margin and wins the specificity tie otherwise. */
html.nav-layout-side .utility-bar-inner,
html.nav-layout-side .site-header-bar,
html.nav-layout-side .value-props-bar-inner {
	margin-left: var(--gr-sidebar-width) !important;
}

html.nav-layout-side main,
html.nav-layout-side footer.wp-block-template-part {
	/* footer.wp-block-template-part, not a bare "footer" selector: WP
	   wraps the footer template part in its own outer <footer> (the
	   template-part boundary), and our footer group block itself also
	   renders as a <footer> (tagName override in parts/footer.html) —
	   two nested <footer> elements. A bare "footer" selector matched
	   both and stacked the margin to 600px instead of 300px. main has
	   no such nesting (only one <main>), so it isn't affected.
	   !important: overriding WP's auto-generated per-block layout-support
	   margin, which is printed after this stylesheet and ties on
	   specificity — deliberate for this JS-toggled state, not a habit. */
	margin-left: var(--gr-sidebar-width) !important;
}

@media (max-width: 781px) {
	/* Side layout doesn't make sense below tablet width — the mobile
	   hamburger already covers this, so force top layout on small screens. */
	html.nav-layout-side .site-nav-row {
		position: static;
		width: auto;
		height: auto;
		border-right: 0;
	}

	html.nav-layout-side .utility-bar-inner,
	html.nav-layout-side .site-header-bar,
	html.nav-layout-side .value-props-bar-inner {
		margin-left: 0 !important;
	}

	html.nav-layout-side main,
	html.nav-layout-side footer.wp-block-template-part {
		margin-left: 0 !important;
	}
}

/* ==========================================================================
   Front-page hero — image on top with an overlaid CTA button (bottom-right
   corner), title + text below. Plain core blocks (group/image/buttons) with
   these wrapper classes only for positioning, so the whole thing stays
   editable/reformattable natively in the Site Editor — no custom block.
   ========================================================================== */

/* MetaSlider's own configured height (its Settings tab) only sets the size
   used when generating cropped image files — the rendered box still falls
   a little short of the hero column's actual stretched height. Forcing the
   whole slider stack to 100% of that column (rather than chasing an exact
   pixel match in MetaSlider's own settings) keeps it flush regardless of
   how tall the hero column ends up being. overflow:hidden on the column is
   a deliberate backstop: if anything inside still computes a hair taller
   than 100% (percentage-height chains through a 3rd-party plugin's own
   markup are fragile — one already overflowed by 50px+ mid-build), it gets
   clipped here instead of visibly pushing past the hero's height. */
body.home .wp-block-column[style*="33.33%"] {
	display: flex;
	overflow: hidden;
}

body.home .metaslider,
body.home .metaslider > div,
body.home .flexslider,
body.home .flexslider .flex-viewport,
body.home .flexslider .slides,
body.home .flexslider .slides > li {
	height: 100% !important;
	max-height: 100%;
	overflow: hidden;
}

body.home .flexslider .slides > li {
	box-sizing: border-box;
	padding: 0;
	background-color: #ffffff;
}

/* Sized via max-width/max-height + auto (not object-fit:cover/contain on a
   forced 100%x100% box) — the image finds its own largest size that still
   fits both dimensions and keeps its aspect ratio, which is what "resize
   the image itself, don't crop it" actually means. Simpler and more
   robust than fighting MetaSlider's own inline sizing style-for-style. */
body.home .flexslider .slides img {
	max-width: 100% !important;
	max-height: 100% !important;
	width: auto !important;
	height: auto !important;
	margin: 0 auto !important;
	display: block;
}

/* Caption shows only on hover/focus, not permanently. */
body.home .flexslider .caption-wrap {
	opacity: 0;
	transition: opacity 0.25s ease;
}

body.home .flexslider .slides > li:hover .caption-wrap,
body.home .flexslider .slides > li:focus-within .caption-wrap {
	opacity: 1;
}

body.home .flexslider {
	margin-bottom: 0;
	padding: 0;
	width: 100%;
}

.gr-hero__image-wrap {
	position: relative;
}

.gr-hero__image-wrap .gr-hero__image {
	margin: 0;
}

.gr-hero__image-wrap .gr-hero__image img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 4px;
}

.gr-hero__cta {
	position: absolute;
	right: var(--wp--preset--spacing--30);
	bottom: var(--wp--preset--spacing--30);
	margin: 0;
}

/* Hero CTA hover: greenerroute.com's existing button blue (#0170B9), same
   brand blue already used on nav-item hover — see that rule's comment
   further down — kept off the site-wide button hover (theme.json's
   accent-hover) and scoped to just this one CTA, per Fabien's request. */
.gr-hero__cta .wp-block-button__link:hover {
	background-color: #0170b9;
	color: #fff;
}

.gr-hero__content {
	padding-top: 5px;
}

/* ==========================================================================
   Shop-page category grid — greenerroute/shop-category-grid. Image tile,
   4 columns, title + product count in a translucent bar over the bottom of
   the image, matching the tile style already used on the live site's shop
   page. Category image = WooCommerce's own native category Thumbnail field.
   ========================================================================== */

.gr-shop-category-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--wp--preset--spacing--50);
	margin: var(--wp--preset--spacing--60) 0;
}

@media (min-width: 600px) {
	.gr-shop-category-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 960px) {
	.gr-shop-category-grid {
		grid-template-columns: repeat(4, 1fr);
	}
}

/* Amazon-mobile-style "sub-department tiles before the product list" —
   only rendered by PHP on category archives with children in the first
   place (see inc/shop-category-grid.php), and only shown on phone here,
   so tablet/desktop category pages are completely unaffected. */
@media (min-width: 600px) {
	.gr-shop-category-grid--subcats {
		display: none;
	}
}

.gr-shop-category-grid__item {
	display: block;
	text-decoration: none;
	color: inherit;
}

.gr-shop-category-grid__media {
	position: relative;
	display: block;
	aspect-ratio: 1 / 1;
	overflow: hidden;
	border-radius: 4px;
	background: var(--wp--preset--color--paper);
}

.gr-shop-category-grid__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	margin: 0;
	transition: transform 0.3s ease;
}

.gr-shop-category-grid__item:hover .gr-shop-category-grid__img {
	transform: scale(1.04);
}

.gr-shop-category-grid__placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	background: var(--wp--preset--color--tint);
	color: var(--wp--preset--color--border);
}

.gr-shop-category-grid__placeholder svg {
	width: 36%;
	height: 36%;
}

.gr-shop-category-grid__caption {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	display: block;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--10);
	background: rgba(255, 255, 255, 0.88);
	text-align: center;
}

.gr-shop-category-grid__title {
	display: block;
	font-weight: 700;
	font-size: 0.8125rem;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--wp--preset--color--ink);
}

.gr-shop-category-grid__count {
	display: block;
	font-size: 0.75rem;
	color: var(--wp--preset--color--muted);
	margin-top: 2px;
}

/* ==========================================================================
   Carousel — core/group block styles "Carousel (Fade)"/"Carousel (Slide)".
   Markup (track/dots/arrows) is injected by assets/js/carousel.js; a group
   with only one child is left alone (no controls, static content), per the
   "only if there's more than one item" requirement.
   ========================================================================== */

.gr-carousel {
	position: relative;
	overflow: hidden;
	height: 100%;
	min-height: 320px;
	border-radius: 4px;
}

@media (max-width: 781px) {
	/* wp:columns stacks below tablet width, so there's no stretched sibling
	   column to inherit a height from — fall back to a fixed height. */
	.gr-carousel {
		height: 320px;
	}
}

.gr-carousel__track {
	position: relative;
	height: 100%;
}

.gr-carousel[data-gr-carousel-mode="slide"] .gr-carousel__track {
	display: flex;
	height: 100%;
	transition: transform 0.5s ease;
}

.gr-carousel[data-gr-carousel-mode="slide"] .gr-carousel__slide {
	flex: 0 0 100%;
	width: 100%;
	height: 100%;
	box-sizing: border-box;
}

.gr-carousel[data-gr-carousel-mode="fade"] .gr-carousel__slide {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	box-sizing: border-box;
	opacity: 0;
	transition: opacity 0.6s ease;
	pointer-events: none;
}

.gr-carousel[data-gr-carousel-mode="fade"] .gr-carousel__slide.is-active {
	opacity: 1;
	pointer-events: auto;
}

.gr-carousel__slide {
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: var(--wp--preset--spacing--50);
}

.gr-carousel__dots {
	position: absolute;
	bottom: var(--wp--preset--spacing--30);
	left: 50%;
	transform: translateX(-50%);
	display: flex;
	gap: var(--wp--preset--spacing--10);
	z-index: 2;
}

.gr-carousel__dot {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.5);
	border: 0;
	padding: 0;
	cursor: pointer;
}

.gr-carousel__dot.is-active {
	background: var(--wp--preset--color--paper);
}

.gr-carousel__arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	background: rgba(0, 0, 0, 0.35);
	color: var(--wp--preset--color--paper);
	border: 0;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	cursor: pointer;
	font-size: 20px;
	line-height: 1;
	z-index: 2;
}

.gr-carousel__arrow--prev {
	left: var(--wp--preset--spacing--20);
}

.gr-carousel__arrow--next {
	right: var(--wp--preset--spacing--20);
}

/* ==========================================================================
   Mobile bottom tab bar (Amazon-style), mobile widths only
   ========================================================================== */

.gr-mobile-tabbar {
	display: none;
}

@media (max-width: 781px) {
	.gr-mobile-tabbar {
		display: flex;
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		z-index: 200;
		background: var(--wp--preset--color--paper);
		border-top: 1px solid var(--wp--preset--color--border);
		box-shadow: 0 -2px 8px rgba(28, 32, 27, 0.06);
	}

	/* Room for the fixed bar so it doesn't cover the last bit of content
	   or the footer on any page. */
	body {
		padding-bottom: 60px;
	}
}

.gr-mobile-tabbar__item {
	flex: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 2px;
	padding: var(--wp--preset--spacing--20) 0;
	border: 0;
	background: transparent;
	color: var(--wp--preset--color--muted);
	text-decoration: none;
	font-size: 10.5px;
	font-weight: 600;
	cursor: pointer;
}

.gr-mobile-tabbar__item:hover,
.gr-mobile-tabbar__item:active {
	color: var(--wp--preset--color--accent);
}

/* ==========================================================================
   Category hero — admin-editable image + benefits, top of category pages.
   Left column: image, with the benefit bullets in a 2-up grid underneath
   it. Right column: category title + native term description, truncated
   with a "Read more" toggle (assets/js/category-hero.js) — the expand/
   collapse pattern on priorydirect.co.uk's category pages, applied to our
   own image+benefits hero rather than their text-only header.
   ========================================================================== */

.gr-category-hero {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--wp--preset--spacing--50);
	/* stretch (grid's default — was "start"): lets the content column match
	   the media column's height instead of sizing to its own (usually
	   shorter) content, so it can actually fill the box below. */
	align-items: stretch;
	background: var(--wp--preset--color--tint);
	border-radius: 4px;
	padding: var(--wp--preset--spacing--50);
	margin: var(--wp--preset--spacing--40) 0 var(--wp--preset--spacing--60);
}

@media (min-width: 700px) {
	.gr-category-hero {
		grid-template-columns: 1fr 1fr;
	}
}

.gr-category-hero__media {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--40);
}

.gr-category-hero__image img {
	width: 100%;
	height: auto;
	border-radius: 4px;
	display: block;
}

.gr-category-hero__benefits {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
}

.gr-category-hero__benefits li {
	position: relative;
	padding-left: var(--wp--preset--spacing--60);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 600;
	color: var(--wp--preset--color--ink);
}

.gr-category-hero__benefits li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.15em;
	width: 24px;
	height: 24px;
	border-radius: 50%;
	background: var(--wp--preset--color--accent);
}

.gr-category-hero__benefits li::after {
	content: "";
	position: absolute;
	left: 7px;
	top: 0.45em;
	width: 10px;
	height: 5px;
	border-left: 2px solid var(--wp--preset--color--paper);
	border-bottom: 2px solid var(--wp--preset--color--paper);
	transform: rotate(-45deg);
}

.gr-category-hero__content {
	display: flex;
	flex-direction: column;
	/* Spreads title/description/button apart to use the full stretched
	   height from the grid row above, instead of clumping at the top with
	   dead space below — this is the "fill the height of the box" part. */
	justify-content: space-between;
}

.gr-category-hero__title {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-size: 18px;
}

/* Fallback title for non-category archive-product.html contexts (shop
   root, product tags, search) — the hero block owns ALL title output for
   this template now, replacing the old standalone query-title block, so
   this still needs the same spacing query-title used to provide. */
.gr-category-hero__title--standalone {
	margin: var(--wp--preset--spacing--40) 0 var(--wp--preset--spacing--60);
}

.gr-category-hero__description {
	color: var(--wp--preset--color--muted);
	font-size: 14px;
	line-height: 1.6em;
}

.gr-category-hero__description p {
	margin: 0 0 var(--wp--preset--spacing--20);
}

.gr-category-hero__description p:last-child {
	margin-bottom: 0;
}

.gr-category-hero__readmore {
	align-self: flex-start;
	margin-top: var(--wp--preset--spacing--20);
	background: none;
	border: 0;
	padding: 0;
	color: var(--wp--preset--color--accent);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--small);
	text-decoration: underline;
	cursor: pointer;
}

.gr-category-hero__readmore:hover {
	color: var(--wp--preset--color--accent-hover);
}

/* The "read more" reveal — a sibling of .gr-category-hero, not nested
   inside it, so it renders below the tinted box on the page's own white
   background rather than growing the green box taller. Only ever present
   in the DOM when there's genuinely remaining content (inc/category-hero.php). */
.gr-category-hero__more {
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--muted);
	font-size: 14px;
	line-height: 1.6em;
	margin: calc(-1 * var(--wp--preset--spacing--40)) 0 var(--wp--preset--spacing--60);
}

.gr-category-hero__more p {
	margin: 0 0 var(--wp--preset--spacing--20);
}

.gr-category-hero__more p:last-child {
	margin-bottom: 0;
}

/* Phone: compact hero — keep just the title (page context + the H1 this
   block is responsible for on non-category archives too), drop the
   image/benefits/description/read-more so the product grid isn't pushed
   below the fold by a large decorative block on a small screen. */
@media (max-width: 599px) {
	.gr-category-hero__media,
	.gr-category-hero__description,
	.gr-category-hero__readmore,
	.gr-category-hero__more {
		display: none;
	}

	.gr-category-hero {
		padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30);
	}

	.gr-category-hero__title {
		margin-bottom: 0;
		font-size: 16px;
	}
}

/* ==========================================================================
   Shop/category grid — uniform cards.
   The Amazon import brought wildly inconsistent image sizes, title
   lengths, and stock states, so every zone below gets a FIXED height
   (image, rating, title, price, cart) regardless of whether a given
   product has a review yet, a square photo, a short title, or stock —
   total card height is then identical by construction, not by luck.
   ========================================================================== */

.gr-card-image {
	background: var(--wp--preset--color--paper);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 4px;
}

/* Fixed height for the rating row — real stars and the empty-star/"Rate
   now" fallback are both sized to fit it, so it stays constant either
   way. */
/* 36px to match the Add to Cart button height further down the card, so
   the rating row and the cart row read as the same visual weight. */
.gr-card-rating-wrap {
	height: 36px;
	display: flex;
	align-items: center;
	margin-top: var(--wp--preset--spacing--30);
	overflow: hidden;
}

/* Amazon titles run long and vary wildly in length — clamped to 2 lines
   with a fixed height (rather than just overflow:hidden) so a one-word
   title and a full keyword-stuffed one take up the same space. */
.gr-card-title {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	text-overflow: ellipsis;
	height: 2.6em;
	line-height: 1.3em;
	margin-top: var(--wp--preset--spacing--30);
	margin-bottom: 0;
}

.gr-card-title a {
	color: inherit;
	text-decoration: none;
}

/* Amazon-style price emphasis: bold and a step larger than body text so it
   reads as the card's focal point, without loading a second font — the
   weight/size shift alone does the job, and the page stays on a single
   font-family for load speed. Taller zone + flex centering (not the old
   fixed 28px) because the bigger bold text needs more vertical room than
   body copy — a plain overflow:hidden at the old height clipped the tops
   of the digits. */
.gr-card-price {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	column-gap: var(--wp--preset--spacing--10);
	height: 48px;
	margin-top: var(--wp--preset--spacing--30);
	margin-bottom: 0;
	overflow: hidden;
}

.gr-card-price .woocommerce-Price-amount {
	font-size: var(--wp--preset--font-size--large);
	font-weight: 700;
	line-height: 1.2;
}

.gr-product-price {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	column-gap: var(--wp--preset--spacing--10);
}

.gr-product-price .woocommerce-Price-amount {
	font-weight: 700;
	line-height: 1.2;
}

.gr-unit-price {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--muted);
	line-height: 1.2;
}

/* Amazon-style price typography: the whole-number digits carry the bold
   large size, while the currency symbol and decimals sit smaller and
   raised — vertical-align:top aligns their top edge to the top of the
   (larger) line box, which is what makes the smaller text read as
   "raised" against the big digits without needing a manual offset.
   .woocommerce-Price-currencySymbol is WooCommerce's own markup; the
   decimal part isn't split by WooCommerce, so assets/js/price-format.js
   wraps it in .gr-price-decimal at runtime. */
.gr-card-price .woocommerce-Price-currencySymbol,
.gr-product-price .woocommerce-Price-currencySymbol,
.gr-card-price .gr-price-decimal,
.gr-product-price .gr-price-decimal {
	font-size: 0.5em;
	vertical-align: top;
}

/* Sale price emphasis, applied globally (not scoped to .gr-card-price/
   .gr-product-price) since prices also render via the plain WooCommerce
   product-price block on search results and other non-archive contexts.
   The new price (ins) takes the brand's existing button blue so it reads
   as the number that matters, while the original price (del) shrinks and
   mutes rather than competing with it at the same size/weight —
   text-decoration:line-through is the browser default for <del> already,
   kept explicit here since it's load-bearing UX, not incidental. */
del .woocommerce-Price-amount {
	/* max() rather than a flat em ratio — this price shows in contexts
	   with wildly different base sizes (large single-product price vs.
	   small search-result cards), and a flat 0.65em shrank the latter to
	   an illegible ~8px. The 11px floor keeps it readable everywhere while
	   still shrinking proportionally wherever the base size allows it. */
	font-size: max(0.65em, 11px);
	font-weight: 400;
	color: var(--wp--preset--color--muted);
	text-decoration: line-through;
}
ins .woocommerce-Price-amount {
	color: #0170b9;
	text-decoration: none;
}

/* woocommerce/add-to-cart-form renders EITHER a quantity+button row OR a
   single "Out of stock" paragraph for the same product, depending on
   stock — never both. That native behaviour already satisfies "out of
   stock gets its own line" and "qty + add to cart if available" as one
   block; this wrapper just gives both of those variants the same fixed
   height so stock state doesn't change the card's total height. */
.gr-card-cart-wrap {
	display: flex;
	align-items: center;
	height: 40px;
	margin-top: var(--wp--preset--spacing--20);
}

.gr-card-cart-wrap .wp-block-add-to-cart-form,
.gr-select-options-btn,
.gr-backorder-btn {
	width: 100%;
}

.gr-card-cart-wrap .wp-block-add-to-cart-form {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
}

/* The quantity+button pair actually lives inside a <form class="cart">
   wrapper, itself a direct (block-level) child of .wp-block-add-to-cart-
   form above — a `flex` on the button alone had no effect since its real
   flex parent is this <form>, not the outer wrapper two levels up. Making
   the form itself a flex container (and letting IT fill the row) is what
   lets the button's flex-grow actually reach full width once the
   quantity box next to it is hidden. */
.gr-card-cart-wrap .wp-block-add-to-cart-form form.cart {
	/* !important: WooCommerce core sets this <form> to display:grid with
	   its own column sizing, which otherwise wins over a plain override
	   here and stops the button's flex-grow (see comment above) from
	   having anywhere to grow into. */
	display: flex !important;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	flex: 1 1 auto;
	min-width: 0;
}

/* Every actionable element in this row — qty stepper, Add to cart,
   Select options, Register interest — gets the SAME explicit height and
   box-sizing, rather than each stretching to 100% of a differently-sized
   parent. Relying on height:100% chains broke here: WooCommerce's own
   button CSS and the native <input> box model don't all agree on
   box-sizing, so "100% of 40px" resolved to visibly different pixel
   heights depending on the button's own border/padding. */
.gr-card-cart-wrap .quantity {
	display: flex;
	align-items: stretch;
	flex: 0 0 auto;
	height: 36px;
	box-sizing: border-box;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 4px;
	overflow: hidden;
}

.gr-card-cart-wrap .qty {
	width: 40px;
	height: 100%;
	box-sizing: border-box;
	border: 0;
	text-align: center;
	font-size: var(--wp--preset--font-size--small);
	-moz-appearance: textfield;
}

.gr-card-cart-wrap .qty::-webkit-inner-spin-button,
.gr-card-cart-wrap .qty::-webkit-outer-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

.gr-qty-btn {
	width: 32px;
	height: 100%;
	box-sizing: border-box;
	border: 0;
	background: var(--wp--preset--color--tint);
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1;
	cursor: pointer;
}

.gr-qty-btn:hover {
	background: var(--wp--preset--color--border);
}

/* WooCommerce renders the quantity field as type="hidden" (no stepper)
   whenever min stock equals max stock — i.e. exactly 1 left, nothing to
   step between (true for ~48 real products in the catalogue right now,
   not a data error). Previously this collapsed the whole box (display:
   none), which fixed the empty-box artefact but made those cards'
   Add to Cart button jump to full width — inconsistent with every card
   that DOES have a real stepper. Keeping the box and showing a static
   "1" in the same slot instead keeps every card's layout/button width
   identical, without implying a quantity that isn't actually choosable. */
.gr-card-cart-wrap .quantity:has(input[type="hidden"]) {
	justify-content: center;
	align-items: center;
	width: 40px;
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
}

.gr-card-cart-wrap .quantity:has(input[type="hidden"])::after {
	content: "1";
}

.gr-card-cart-wrap .single_add_to_cart_button,
.gr-select-options-btn,
.gr-register-interest__toggle {
	/* !important: WooCommerce's own button CSS sets an explicit height
	   elsewhere, which otherwise wins over a plain height here. */
	height: 36px !important;
	box-sizing: border-box;
}

.gr-card-cart-wrap .single_add_to_cart_button {
	flex: 1 1 auto;
	width: auto;
	white-space: nowrap;
	font-size: var(--wp--preset--font-size--small);
	padding: 0 var(--wp--preset--spacing--40);
}

.gr-select-options-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--paper);
	border-radius: 4px;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	text-decoration: none;
}

.gr-select-options-btn:hover {
	background: var(--wp--preset--color--accent-hover);
	color: var(--wp--preset--color--paper);
}

/* WooCommerce also prints a "1 in stock"/"X left in stock" notice above
   the quantity+button for low-stock items — a second line of content the
   fixed-height row wasn't built for (only the out-of-stock case, a single
   line replacing the form entirely, was asked for). Hidden rather than
   given more room: a low-stock count isn't part of the requested layout,
   and the form itself still works identically without it. */
.gr-card-cart-wrap .stock.in-stock {
	display: none;
}

.gr-card-cart-wrap .stock.out-of-stock {
	display: flex;
	align-items: center;
	height: 36px;
	box-sizing: border-box;
	margin: 0;
	color: var(--wp--preset--color--error);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--small);
}

/* "Register interest" trigger button — opens the shared modal (markup
   rendered once in the footer, see .gr-interest-modal below) rather than
   an inline panel, so its own sizing is simple: just another button in
   the fixed-height cart row. */
.gr-register-interest__toggle {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 36px;
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--error);
	border: 1px solid var(--wp--preset--color--error);
	border-radius: 4px;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	cursor: pointer;
	box-sizing: border-box;
}

.gr-register-interest__toggle:hover {
	background: var(--wp--preset--color--tint);
}

/* "Back order" — same visual weight as Select options (both are "go to
   the product page" links), distinct blue so it doesn't read as a second
   "add to cart"-equivalent action. */
.gr-backorder-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 36px;
	box-sizing: border-box;
	background: #0170b9;
	color: var(--wp--preset--color--paper);
	border-radius: 4px;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	text-decoration: none;
}

.gr-backorder-btn:hover {
	background: #015a94;
	color: var(--wp--preset--color--paper);
}

/* Backorder ETA notice, single product page, above the description tabs.
   Border is the theme's own accent green (brand colour, per Fabien's
   request), not the generic neutral border token used elsewhere. */
.gr-backorder-eta {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--20);
	margin: var(--wp--preset--spacing--50) 0;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--tint);
	border: 1px solid var(--wp--preset--color--accent);
	border-radius: 8px;
	color: var(--wp--preset--color--ink);
}
.gr-backorder-eta svg { flex: 0 0 auto; margin-top: 2px; color: var(--wp--preset--color--accent); }
.gr-backorder-eta p { margin: 0; font-weight: 600; font-size: var(--wp--preset--font-size--small); }
.gr-backorder-eta__caveat {
	margin-top: var(--wp--preset--spacing--10) !important;
	font-weight: 400 !important;
	font-size: var(--wp--preset--font-size--x-small) !important;
	color: var(--wp--preset--color--muted);
}

/* Register-interest popup: fixed overlay + centered dialog, hidden via
   the [hidden] attribute rather than a class so no extra specificity
   fight is needed to show/hide it. */
.gr-interest-modal[hidden] { display: none; }
.gr-interest-modal {
	position: fixed;
	inset: 0;
	z-index: 1000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--wp--preset--spacing--40);
}
.gr-interest-modal__backdrop {
	position: absolute;
	inset: 0;
	background: rgba(28, 32, 27, 0.55);
}
.gr-interest-modal__dialog {
	position: relative;
	width: 100%;
	max-width: 420px;
	max-height: 90vh;
	overflow-y: auto;
	background: var(--wp--preset--color--paper);
	border-radius: 10px;
	padding: var(--wp--preset--spacing--50);
	box-shadow: 0 12px 40px rgba(28, 32, 27, 0.25);
}
.gr-interest-modal__close {
	position: absolute;
	top: var(--wp--preset--spacing--30);
	right: var(--wp--preset--spacing--30);
	width: 32px;
	height: 32px;
	border: 0;
	background: transparent;
	font-size: 24px;
	line-height: 1;
	cursor: pointer;
	color: var(--wp--preset--color--muted);
}
.gr-interest-modal__close:hover { color: var(--wp--preset--color--ink); }
.gr-interest-modal__product {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
	margin-bottom: var(--wp--preset--spacing--30);
	padding-right: var(--wp--preset--spacing--60);
}
.gr-interest-modal__product-image {
	width: 56px;
	height: 56px;
	object-fit: cover;
	border-radius: 6px;
	flex: 0 0 auto;
}
.gr-interest-modal__product-name {
	margin: 0;
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1.3;
}
.gr-interest-modal__intro {
	margin: 0 0 var(--wp--preset--spacing--40);
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
}
.gr-interest-modal__form {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--10);
}
.gr-interest-modal__form label {
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	margin-top: var(--wp--preset--spacing--20);
}
.gr-interest-modal__form input,
.gr-interest-modal__form textarea {
	box-sizing: border-box;
	width: 100%;
	padding: var(--wp--preset--spacing--20);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 6px;
	font-size: var(--wp--preset--font-size--small);
	font-family: inherit;
	resize: vertical;
}
.gr-interest-modal__submit {
	margin-top: var(--wp--preset--spacing--30);
	padding: var(--wp--preset--spacing--30);
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--paper);
	border: 0;
	border-radius: 6px;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	cursor: pointer;
}
.gr-interest-modal__submit:hover { background: var(--wp--preset--color--accent-hover); }
.gr-interest-modal__submit:disabled { opacity: 0.6; cursor: default; }
.gr-interest-modal__message {
	margin: var(--wp--preset--spacing--30) 0 0;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--accent);
}
body.gr-modal-open { overflow: hidden; }

.gr-view-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--10);
	height: 36px;
	margin-top: var(--wp--preset--spacing--20);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--accent);
	border: 1px solid var(--wp--preset--color--accent);
	border-radius: 4px;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	text-decoration: none;
	box-sizing: border-box;
}

.gr-view-btn:hover {
	background: var(--wp--preset--color--tint);
}

/* ==========================================================================
   Tiered pricing table (product page — only rendered when tiers exist)
   ========================================================================== */

.gr-tier-table {
	width: 100%;
	border-collapse: collapse;
	margin: var(--wp--preset--spacing--40) 0;
	font-size: var(--wp--preset--font-size--small);
}

.gr-tier-table th,
.gr-tier-table td {
	text-align: left;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.gr-tier-table th {
	background: var(--wp--preset--color--tint);
	font-weight: 600;
	color: var(--wp--preset--color--muted);
	text-transform: uppercase;
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0.03em;
}

.gr-tier-save {
	font-weight: 600;
	color: var(--wp--preset--color--accent);
}

.gr-tier-save--none {
	font-weight: 400;
	color: var(--wp--preset--color--muted);
}

/* Highlights the row matching the currently-entered quantity — see
   assets/js/tiered-pricing-highlight.js, which toggles this class as the
   qty stepper changes. */
.gr-tier-table tr[data-tier-qty] {
	transition: background-color 0.15s ease;
}

.gr-tier-row--active {
	background: var(--wp--preset--color--tint);
}

.gr-tier-row--active td:first-child {
	position: relative;
}

.gr-tier-row--active td:first-child::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0;
	bottom: 0;
	width: 3px;
	background: var(--wp--preset--color--accent);
}

/* Optional label next to the main price, e.g. "Bulk pricing available" —
   admin picks before/after via the General tab; only one of the two
   template instances ever renders non-empty (see tier-price-label
   render_callback), so no extra ordering logic is needed here. */
.gr-tier-price-label {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--accent);
}

/* ==========================================================================
   Cookie consent banner
   ========================================================================== */

.gr-cookie-banner {
	position: fixed;
	left: var(--wp--preset--spacing--40);
	right: var(--wp--preset--spacing--40);
	bottom: var(--wp--preset--spacing--40);
	max-width: 640px;
	margin: 0 auto;
	background: var(--wp--preset--color--paper);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 4px;
	box-shadow: 0 4px 16px rgba(28, 32, 27, 0.12);
	padding: var(--wp--preset--spacing--50);
	z-index: 1000;
}

.gr-cookie-banner__message p {
	margin: 0 0 var(--wp--preset--spacing--40);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

.gr-cookie-banner__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
}

.gr-cookie-banner__btn {
	border: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--paper);
	color: var(--wp--preset--color--ink);
	border-radius: 4px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	cursor: pointer;
}

.gr-cookie-banner__btn--primary {
	background: var(--wp--preset--color--accent);
	border-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--paper);
}

.gr-cookie-banner__custom {
	margin-top: var(--wp--preset--spacing--40);
	padding-top: var(--wp--preset--spacing--40);
	border-top: 1px solid var(--wp--preset--color--border);
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--30);
}

.gr-cookie-banner__custom label {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--small);
}

/* ==========================================================================
   Product eco badges — small icon + label row below the product title,
   one per ticked box on the product's Eco Badges admin tab.
   ========================================================================== */

.gr-product-badges {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--30);
	margin: var(--wp--preset--spacing--20) 0 var(--wp--preset--spacing--30);
	padding: 0;
}

/* Icon-only by default — the label is a hover/focus tooltip, not
   permanent text, so the row stays compact. position:relative + a
   tabindex on the <li> (see render_callback) is what makes the tooltip
   reachable by keyboard, not just mouse hover. */
.gr-product-badge {
	position: relative;
}

.gr-product-badge__icon {
	width: 40px;
	height: 40px;
	display: block;
	object-fit: contain;
}

.gr-product-badge__label {
	position: absolute;
	bottom: 100%;
	left: 50%;
	transform: translateX(-50%);
	margin-bottom: var(--wp--preset--spacing--10);
	padding: 4px 8px;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--paper);
	border-radius: 4px;
	font-size: var(--wp--preset--font-size--x-small);
	white-space: nowrap;
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.15s ease;
	pointer-events: none;
	z-index: 5;
}

.gr-product-badge:hover .gr-product-badge__label,
.gr-product-badge:focus .gr-product-badge__label {
	opacity: 1;
	visibility: visible;
}

/* Coming-soon holding page */
.gr-coming-soon-hero {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--paper);
	padding: var(--wp--preset--spacing--80) var(--wp--preset--spacing--50);
	border-radius: 12px;
	text-align: center;
	margin-bottom: var(--wp--preset--spacing--70);
}
.gr-coming-soon-hero__eyebrow {
	display: inline-block;
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	background: rgba(255,255,255,0.12);
	padding: 6px 14px;
	border-radius: 999px;
	margin-bottom: var(--wp--preset--spacing--40);
}
.gr-coming-soon-hero h1 {
	color: var(--wp--preset--color--paper);
	margin: 0 0 var(--wp--preset--spacing--40);
}
.gr-coming-soon-hero p {
	color: rgba(255,255,255,0.9);
	max-width: 640px;
	margin: 0 auto;
	font-size: var(--wp--preset--font-size--medium);
}

.gr-coming-soon-categories {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: var(--wp--preset--spacing--40);
	margin: var(--wp--preset--spacing--50) 0 var(--wp--preset--spacing--70);
}
.gr-coming-soon-categories__item {
	background: var(--wp--preset--color--tint);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 10px;
	padding: var(--wp--preset--spacing--40);
	text-align: center;
}
.gr-coming-soon-categories__item svg { color: var(--wp--preset--color--accent); margin-bottom: 8px; }
.gr-coming-soon-categories__item span { display: block; font-weight: 600; font-size: var(--wp--preset--font-size--small); }

.gr-coming-soon-signup {
	background: var(--wp--preset--color--tint);
	border-radius: 12px;
	padding: var(--wp--preset--spacing--60) var(--wp--preset--spacing--50);
	text-align: center;
	margin: var(--wp--preset--spacing--70) 0;
}
.gr-coming-soon-signup__form {
	display: flex;
	gap: 10px;
	justify-content: center;
	flex-wrap: wrap;
	margin-top: var(--wp--preset--spacing--40);
}
.gr-coming-soon-signup__form input[type="email"] {
	flex: 1 1 280px;
	max-width: 320px;
	padding: 12px 16px;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 6px;
	font-size: var(--wp--preset--font-size--medium);
}
.gr-coming-soon-signup__form button {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--paper);
	border: none;
	padding: 12px 24px;
	border-radius: 6px;
	font-weight: 600;
	cursor: pointer;
}
.gr-coming-soon-signup__form button:hover { background: var(--wp--preset--color--accent-hover); }
.gr-coming-soon-signup__hp { position: absolute; left: -9999px; }
.gr-coming-soon-signup__message {
	padding: 10px 16px;
	border-radius: 6px;
	margin-bottom: var(--wp--preset--spacing--40);
	font-weight: 600;
}
.gr-coming-soon-signup__message--success { background: #DCF3E4; color: var(--wp--preset--color--accent); }
.gr-coming-soon-signup__message--error { background: #FBE4E2; color: var(--wp--preset--color--error); }
