/* ==========================================================================
   Herbelo — storefront stylesheet
   Design language: apothecary/pharmacy rather than soft-wellness.
   Crisp hairlines and small radii instead of pillowy cards; one native
   system font throughout (weight/size carry hierarchy, not typeface) with
   mono reserved for data — prices, barcodes, quantities; neutrals biased
   toward the brand green sampled from the logo.
   Light-only by design — product photography assumes a white ground.
   ========================================================================== */

/* Noto Sans Arabic — self-hosted (not Google Fonts CDN), Arabic subset only.
   The Latin-subset files (400/600/700-latin.woff2) were removed: Latin
   characters within Arabic-direction text (brand names, prices, numbers)
   fall back to the next font in the --sans stack instead — visually
   indistinguishable from Noto's own Latin glyphs in practice, so keeping
   them was ~32KB of dead weight (3 files, ~10.7KB each) on every Arabic
   page load for no visible benefit.
   Replaces an earlier attempt at IBM Plex Sans Arabic + three
   alternates (Cairo/Tajawal/Almarai) — all four removed (files deleted,
   these @font-face rules replaced) in favor of settling on this one.
   Self-hosted rather than linked from fonts.googleapis.com so there's no
   third-party DNS/TLS round-trip on every first visit, and so it's cached
   by the exact same LiteSpeed/CDN path as every other theme asset.
   font-display: swap — text renders immediately in the fallback stack and
   re-flows once this loads, rather than staying invisible
   (font-display: block) until it does.

   STATIC per-weight instances (400/600/700 — the weights actually used
   site-wide per a grep of font-weight declarations; 500 dropped, unused
   enough to just fall back to 400), not Google's default variable font.
   Confirmed live: the variable file covers the full 100–900 range in one
   ~166KB download, paid on every page regardless of which weight(s) that
   page actually renders. Forcing static delivery (an old-Chrome User-Agent
   makes Google's API fall back to per-weight instances instead) means each
   file is ~50KB, and — since @font-face is only ever fetched per weight
   actually used on a given page, not the whole family — a typical page
   using 1–2 weights now transfers less than half of what the always-166KB
   variable file cost regardless. Flagged by a real PageSpeed Insights
   mobile run on the product page after the font was first added. */
@font-face {
	font-family: "Noto Sans Arabic";
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url("../fonts/noto-sans-arabic-400-arabic.woff2") format("woff2");
	unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
	font-family: "Noto Sans Arabic";
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url("../fonts/noto-sans-arabic-600-arabic.woff2") format("woff2");
	unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
	font-family: "Noto Sans Arabic";
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url("../fonts/noto-sans-arabic-700-arabic.woff2") format("woff2");
	unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}

:root {
	/* Ground + neutrals, biased green so they read as chosen, not inherited */
	--paper:      #ffffff;
	--mist:       #f1f4ef;
	--mist-deep:  #e4eae1;
	--hairline:   #d3dbd0;
	--stone:      #676e66;
	--ink:        #101a13;

	/* Brand green, hue-matched to the Herbelo logo mark (#A5B183, ~76° hue).
	   The logo's own sage tone is too light for AA text/button contrast
	   (~2.3:1 on white), so --leaf keeps its hue but is darkened/saturated
	   to clear 4.5:1; --leaf-logo is the raw sampled swatch for decorative use. */
	--leaf-logo:  #a5b183;
	--leaf:       #55642b; /* 6.47:1 vs white */
	--leaf-deep:  #3e4a1c;
	--leaf-wash:  #f0f3e7;

	/* Single warm signal: price, savings, low stock. Never decorative. */
	--amber:      #b25a08; /* WCAG AA vs white: 4.82:1 */
	--amber-deep: #a35204; /* for text on --amber-wash specifically: 4.96:1 — --amber itself only reaches 4.29:1 there */
	--amber-wash: #fbf0e4;

	--crit:       #a32219;
	--crit-wash:  #fdf1f0;

	/* One native system-font family throughout — San Francisco on Mac/iOS,
	   Segoe UI on Windows, Roboto on Android/Chrome OS. No web fonts, no
	   flash-of-unstyled-text, and it renders equally polished everywhere
	   rather than relying on a serif fallback chain that only really looks
	   right on one OS. Headings are set apart by weight/size, not typeface. */
	--sans:    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
	--display: var(--sans);
	--mono:    ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

	/* Type scale for UI chrome (labels, meta, list text) — everything below
	   body size now steps through these five values instead of dozens of
	   one-off sizes a hundredth of a rem apart. */
	--fs-2xs: .6875rem; /* 11px — tiny mono labels, chips */
	--fs-xs:  .75rem;   /* 12px — meta, captions */
	--fs-sm:  .8125rem; /* 13px — secondary text, list items */
	--fs-base: .875rem; /* 14px — default UI text */
	--fs-md:  .9375rem; /* 15px — emphasized small text */

	--shell: 1400px;
	--r:     3px;
	--r-lg:  4px;
	--shadow:    0 1px 3px rgba(16, 26, 19, .07);
	--shadow-lg: 0 12px 34px rgba(16, 26, 19, .16);
	--t:      140ms ease; /* hover/focus micro-interactions */
	--t-slow: 240ms ease; /* sliding panels: mini-cart, mobile nav, sticky bar */

	--z-header: 100;
	--z-overlay: 200;
	--z-drawer: 210;
	--z-toast: 300;
}

/* Arabic pages: a deliberately-chosen popular Arabic web font (Noto Sans
   Arabic, self-hosted — see the @font-face block up top) leading the
   stack, with the same native-system fonts as before kept as the fallback
   chain for the brief window before it loads (font-display: swap) or on
   the rare chance it fails to load at all — Noto Sans Arabic is also
   named explicitly in that fallback chain itself, since it's the one
   Linux/Android already ship as their own native Arabic default. Overriding
   the --sans custom property here (not a new variable) means every existing
   var(--sans)/var(--display) usage site-wide picks this up automatically,
   scoped to [dir="rtl"] so French is completely unaffected. Source order
   matters: this must come after :root{} above to win the specificity tie
   (:root and [dir="rtl"] both resolve to the same <html> element here). */
[dir="rtl"] {
	--sans: "Noto Sans Arabic", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Segoe UI Arabic", Tahoma, Arial, sans-serif;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
}
html, body {
	max-width: 100%;
	overflow-x: hidden;
}
body {
	margin: 0;
	background: var(--paper);
	color: var(--ink);
	font-family: var(--sans);
	font-size: 16px;
	line-height: 1.6;
	-webkit-font-smoothing: antialiased;
}
/* Belt-and-suspenders: forces the system-font stack on every element, even if
   a plugin (e.g. Elementor's global kit CSS) sets its own font-family
   somewhere with higher specificity. --sans above is the source of truth;
   this just guarantees it wins everywhere. .star-rating below carries its
   own !important — a class selector beats the universal one even under
   equal !important — so WooCommerce's "star" icon font still renders.
   var(--sans), not a hardcoded literal list — this rule's own !important
   would otherwise outrank the [dir="rtl"] --sans override above (a plain
   custom-property reassignment has no !important of its own to fight
   back with), silently keeping the Latin-only stack on Arabic pages
   despite that override existing. Confirmed live before this fix. */
* {
	font-family: var(--sans) !important;
}
body.mini-cart-open,
body.nav-open { overflow: hidden; }

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; margin: 0; padding: 0; }
table { width: 100%; border-collapse: collapse; }

h1, h2, h3, h4 {
	font-family: var(--display);
	font-weight: 600;
	line-height: 1.2;
	margin: 0 0 .5em;
}

/* Excludes radio/checkbox — applying text-field padding+border+background to
   those turns the native circle/square into a large filled rectangle (this
   is what was happening to the shipping method options, and to every other
   radio/checkbox on the site: payment methods, "ship to a different
   address", terms, coupon "have a discount code" toggles). Sized/colored
   properly just below instead.
   Also excludes .header-search-bar-input by name: each :not() here counts
   toward specificity the same as a class does, so adding the radio/checkbox
   exclusions raised this rule above .header-search-bar-input's own (single
   class) rule and started overriding its padding/border/background —
   excluding it explicitly means it's never a specificity contest at all. */
input:not([type="radio"]):not([type="checkbox"]):not(.header-search-bar-input), select, textarea {
	font-family: inherit;
	font-size: 1rem;
	padding: 11px 13px;
	/* --stone, not --hairline: --hairline (#d3dbd0) is barely visible against
	   the white/paper field background — fine for decorative card borders,
	   too faint for a field boundary someone actually needs to see. */
	border: 1px solid var(--stone);
	border-radius: var(--r);
	background: var(--paper);
	color: var(--ink);
}
input[type="radio"],
input[type="checkbox"] {
	width: 17px; height: 17px;
	flex-shrink: 0;
	accent-color: var(--leaf);
}
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
	outline: 2px solid var(--leaf);
	outline-offset: 2px;
}

.screen-reader-text {
	position: absolute;
	width: 1px; height: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
}
.skip-link {
	position: absolute;
	top: -100px; left: 0;
	background: var(--leaf);
	color: var(--paper);
	padding: 10px 16px;
	z-index: 10000;
}
.skip-link:focus { top: 0; }

/* Utility: mono figures wherever digits line up */
.num,
.woocommerce-Price-amount,
.price,
.amount {
	font-variant-numeric: tabular-nums;
}

/* Belt-and-suspenders alongside the <bdi> wrapper wc_price() already emits
   (see herbelo_allow_bdi_in_kses()): keeps "5 800 DA" from having its
   digit groups visually reordered by the page's bidi context, even for any
   price string that reaches the page through a path <bdi> doesn't cover. */
.woocommerce-Price-amount {
	unicode-bidi: isolate;
	direction: ltr;
	display: inline-block;
	padding-right: 5px;
}
/* The Arabic currency symbol "دج" broke the assumption above: <bdi> with no
   explicit dir auto-detects its OWN direction from its content's first
   "strong" character, skipping digits (direction-neutral) — so "5 800 دج"
   sees "د" first among strong characters and auto-detects RTL internally,
   silently overriding the direction: ltr set on the wrapping span above and
   reversing the whole amount to "دج 800 5". Forcing it on the <bdi> itself,
   not just its wrapper, is what actually reaches the auto-detection. */
.woocommerce-Price-amount bdi {
	unicode-bidi: isolate;
	direction: ltr;
}
/* Requested layout for Arabic: currency on the left, amount on the right
   ("دج 4 500", not "4 500 دج"). Tried direction: rtl on the bdi first —
   reverted, confirmed live it corrupts the NUMBER itself: wc_price()
   separates thousands with a plain space ("4 500"), spaces are bidi-
   neutral, and inside an RTL run that doesn't reliably keep "4" and "500"
   together — the bidi algorithm reordered them into "500 4" independently
   of the currency symbol. herbelo_wrap_price_number_span() (PHP) now
   wraps the number in its own span so this can reorder the two segments
   as flex items instead — a purely visual reposition that never re-runs
   bidi resolution on either span's own text, so the number's internal
   order is never at risk regardless of which side it's drawn on. */
.woocommerce-Price-amount bdi {
	display: inline-flex;
	align-items: baseline;
	/* The currency symbol's own text is " دج" — a leading space meant to
	   separate it from the number in normal (row) order. row-reverse below
	   flips which ITEM comes first without touching either item's own
	   text, so that space ends up on the outer edge of "دج" instead of
	   between it and the number, leaving them touching. An explicit gap
	   provides real separation that holds regardless of flex order. */
	gap: 3px;
}
.woocommerce-Price-amount .herbelo-price-number {
	unicode-bidi: isolate;
	direction: ltr;
}
[dir="rtl"] .woocommerce-Price-amount bdi {
	flex-direction: row-reverse;
}
/* Same 5px breathing room as the French version above, mirrored to the
   side the currency symbol actually sits on for Arabic ("دج" on the left,
   vs "DA" on the right for French) — not additive with it, so this has to
   reset padding-right back to 0 or Arabic would end up with both. */
[dir="rtl"] .woocommerce-Price-amount {
	padding-left: 5px;
	padding-right: 0;
}

/* ---------- Shared containers ---------- */
.header-inner,
.footer-inner,
.footer-newsletter-inner,
.site-main,
.post-grid,
.archive-header,
.band-inner {
	max-width: var(--shell);
	margin: 0 auto;
	padding: 0 24px;
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.button,
button,
input[type="submit"],
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit {
	display: inline-block;
	/* Buttons that are actual <a> tags (Voir le panier, Valider la commande…)
	   render inside .entry-content on cart/checkout/account (shortcodes on
	   plain Pages — see the Cart section below), and ".entry-content a"
	   underlines links for article body text. Nothing before this rule was
	   more specific for text-decoration specifically, so that underline was
	   winning on every button built from a link rather than a <button>. */
	text-decoration: none;
	background: var(--leaf);
	color: var(--paper);
	border: 1px solid var(--leaf);
	border-radius: var(--r);
	padding: 12px 20px;
	font-family: var(--sans);
	font-weight: 700;
	font-size: var(--fs-md);
	letter-spacing: .01em;
	cursor: pointer;
	text-align: center;
	transition: background var(--t), border-color var(--t), color var(--t);
}
.button:hover,
button:hover,
input[type="submit"]:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover {
	background: var(--leaf-deep);
	border-color: var(--leaf-deep);
	color: var(--paper);
}
.button:disabled,
.woocommerce a.button.disabled,
.woocommerce button.button:disabled,
.woocommerce button.button.disabled {
	background: transparent;
	border-color: var(--hairline);
	color: var(--stone);
	cursor: not-allowed;
}

/* Secondary: outline */
.button-outline,
.woocommerce a.button.button-outline,
.woocommerce-cart .wc-proceed-to-checkout a.checkout-button + a {
	background: transparent;
	color: var(--leaf);
	border-color: var(--leaf);
}
.button-outline:hover {
	background: var(--leaf);
	color: var(--paper);
}

/* Loop "add to cart": icon-only, not icon+label. The button's text ("Ajouter")
   is kept in the DOM at font-size:0 rather than removed — invisible on
   screen but still read by screen readers/assistive tech, which is the
   accessible way to do an icon-only control without losing its label.
   Three selector variants, not two: a real <button> (herbelo_loop_add_to_cart's
   own quick-add button, .loop-variation-add-to-cart) ties in specificity
   with .woocommerce button.button (both 2 classes + 1 element) and loses
   on source order — .product-card-actions .button alone doesn't carry
   enough weight to beat that for a <button> element the way it does for
   an <a>, where .product-card-actions a.button already matches
   .woocommerce a.button's own specificity and wins on position instead.
   Confirmed live: without the explicit button.button variant, this
   button rendered as a full-width text button ("Ajouter au panier"),
   breaking the card's height. */
.product-card-actions .button,
.product-card-actions a.button,
.product-card-actions button.button {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	padding: 0;
	font-size: 0;
	background: transparent;
	color: var(--leaf);
	border-color: var(--leaf);
	border-radius: 50%;
}
.product-card-actions .button:hover,
.product-card-actions a.button:hover,
.product-card-actions button.button:hover {
	background: var(--leaf);
	color: var(--paper);
}
/* Cart icon via mask-image (not background-image) specifically so it can use
   background-color: currentColor — the same icon then correctly switches
   from green to white on hover along with the button's text color, with no
   need for a second icon asset. */
.product-card-actions .button::before {
	content: "";
	width: 16px; height: 16px;
	flex-shrink: 0;
	background-color: currentColor;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M2 5h2l1.5 9.5a2 2 0 002 1.5h6a2 2 0 002-1.5L17 7H5.4' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='8' cy='18' r='1.3' fill='%23000'/%3E%3Ccircle cx='15' cy='18' r='1.3' fill='%23000'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M2 5h2l1.5 9.5a2 2 0 002 1.5h6a2 2 0 002-1.5L17 7H5.4' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='8' cy='18' r='1.3' fill='%23000'/%3E%3Ccircle cx='15' cy='18' r='1.3' fill='%23000'/%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
}
.product-card-actions .added_to_cart {
	display: none;
}

/* Single product page: WooCommerce's own add-to-cart.js (onAddedToCart)
   appends a "Voir le panier" <a class="added_to_cart wc-forward"> right
   after the button on every successful add — with nothing here to style or
   scope it, it rendered as a second, unstyled button-ish link crammed next
   to "Commander", visibly breaking the layout on each click. The mini-cart
   drawer already opens with its own "Voir le panier" action (see
   initMiniCart in main.js) and a toast confirms the add, so this appended
   link is redundant here regardless — hidden rather than styled. */
#add-to-cart-form .added_to_cart {
	display: none;
}

/* Out of stock: WooCommerce's own loop template drops the add_to_cart_button
   / ajax_add_to_cart classes for a non-purchasable product, leaving just
   "button product_type_simple" on what becomes a plain "Lire la suite" link
   to the product page — this selects exactly that button without touching
   the real add-to-cart one. Same cart icon there made an inert "go look at
   the page" link look like a working add action; a magnifying glass (view
   product) and a muted tone read correctly as "nothing to add here". */
.product-card-actions .button:not(.add_to_cart_button) {
	color: var(--stone);
	border-color: var(--stone);
}
.product-card-actions .button:not(.add_to_cart_button):hover {
	background: var(--stone);
	color: var(--paper);
}
.product-card-actions .button:not(.add_to_cart_button)::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='8.5' cy='8.5' r='6' stroke='%23000' stroke-width='1.7'/%3E%3Cpath d='M13 13l4.5 4.5' stroke='%23000' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='8.5' cy='8.5' r='6' stroke='%23000' stroke-width='1.7'/%3E%3Cpath d='M13 13l4.5 4.5' stroke='%23000' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* Already in cart: swapped live via JS (refreshShopCartIcons in main.js),
   never decided in this card's own markup — the shop grid is an otherwise
   cacheable, shared page, so anything cart-dependent baked into its HTML
   would risk showing one visitor's cart contents to another (the exact bug
   already fixed once for the stock notice). A solid fill + checkmark reads
   as "done" at the same a-glance icon-only size as the cart icon it
   replaces. */
.product-card-actions .add_to_cart_button.is-in-cart {
	background: var(--leaf);
	color: var(--paper);
	border-color: var(--leaf);
}
.product-card-actions .add_to_cart_button.is-in-cart::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 10.5l4.5 4.5L17 5' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 10.5l4.5 4.5L17 5' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* ==========================================================================
   WooCommerce notices — WC's own stylesheet is disabled, so these need
   styling here or they render as unstyled text.
   ========================================================================== */

.woocommerce-message,
.woocommerce-error,
.woocommerce-info,
.woocommerce-notice,
.woocommerce-noreviews {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	flex-wrap: wrap;
	background: var(--paper);
	border: 1px solid var(--hairline);
	border-inline-start: 4px solid var(--leaf);
	border-radius: var(--r-lg);
	box-shadow: var(--shadow);
	padding-block: 9px;
	padding-inline: 42px 34px;
	margin: 0 0 12px;
	font-size: var(--fs-base);
	line-height: 1.5;
	color: var(--ink);
	list-style: none;
}
/* Icon sits inside its own tinted circle badge rather than as a bare glyph —
   reads as a deliberate status indicator instead of a small stray mark, and
   gives the color-coding (green/red/grey) a clearer home than the thin
   left border alone. Absolutely positioned, not a flex item, so it stays
   put regardless of whether the content next to it is one line (a plain
   success message) or several stacked ones (an error list). */
.woocommerce-message::before,
.woocommerce-info::before,
.woocommerce-notice::before,
.woocommerce-noreviews::before,
.woocommerce-error::before {
	content: "";
	position: absolute;
	inset-inline-start: 9px;
	top: 9px;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background-color: var(--leaf-wash);
}
.woocommerce-message::after,
.woocommerce-info::after,
.woocommerce-notice::after,
.woocommerce-noreviews::after,
.woocommerce-error::after {
	content: "";
	position: absolute;
	inset-inline-start: 14px;
	top: 14px;
	width: 12px;
	height: 12px;
	background-color: var(--leaf);
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 10.5l4.5 4.5L17 5' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 10.5l4.5 4.5L17 5' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.woocommerce-error {
	border-inline-start-color: var(--crit);
}
.woocommerce-error::before { background-color: var(--crit-wash); }
.woocommerce-error::after {
	background-color: var(--crit);
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M10 2L18.5 17H1.5L10 2z' stroke='%23000' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='M10 8v3.5' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/%3E%3Ccircle cx='10' cy='14' r='1' fill='%23000'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M10 2L18.5 17H1.5L10 2z' stroke='%23000' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='M10 8v3.5' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/%3E%3Ccircle cx='10' cy='14' r='1' fill='%23000'/%3E%3C/svg%3E");
}
/* Info/notice ("Déjà client ?", "Cliquez ici pour vous connecter"…) is not a
   success confirmation — it was reusing the exact same green checkmark
   (and green accent border) as .woocommerce-message right above it on
   checkout, which reads as a second "done!" stacked under the real one.
   Neutral --stone throughout, plus its own icon shape, makes the two
   visually distinct at a glance instead of looking like a duplicate. */
.woocommerce-info,
.woocommerce-notice { border-inline-start-color: var(--stone); }
.woocommerce-info::before,
.woocommerce-notice::before { background-color: var(--mist-deep); }
.woocommerce-info::after,
.woocommerce-notice::after {
	background-color: var(--stone);
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='10' cy='10' r='8' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M10 9v5' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3Ccircle cx='10' cy='6.2' r='1.1' fill='%23000'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='10' cy='10' r='8' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M10 9v5' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3Ccircle cx='10' cy='6.2' r='1.1' fill='%23000'/%3E%3C/svg%3E");
}
/* Dismiss (×) — added client-side by initDismissibleNotices (main.js) since
   there's nothing server-side to tell not to show it again; this just lets
   a visitor clear it from the current view. Positioned in the same absolute
   top-right corner regardless of notice type or button presence. */
.woocommerce-notice-dismiss {
	position: absolute;
	top: 9px;
	inset-inline-end: 9px;
	width: 22px;
	height: 22px;
	display: flex;
	align-items: center;
	justify-content: center;
	border: 0;
	padding: 0;
	background: transparent;
	color: var(--stone);
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
	border-radius: 50%;
	transition: background var(--t), color var(--t);
}
.woocommerce-notice-dismiss:hover,
.woocommerce-notice-dismiss:focus-visible {
	background: var(--mist);
	color: var(--ink);
}
/* Error (and any other) notice rendered as a <ul> of several <li> — e.g. every
   required-field validation failure at once on checkout — used to squeeze
   into the same single-row flex layout as a plain one-line message, wrapping
   items awkwardly with no spacing between them. Stacking them vertically
   instead is what actually suits a list of distinct problems. */
ul.woocommerce-error,
ul.woocommerce-message,
ul.woocommerce-info,
ul.woocommerce-notice {
	flex-direction: column;
	align-items: flex-start;
}
ul.woocommerce-error li,
ul.woocommerce-message li,
ul.woocommerce-info li {
	margin: 0;
	width: 100%;
}
ul.woocommerce-error li + li,
ul.woocommerce-message li + li,
ul.woocommerce-info li + li {
	margin-top: 8px;
	padding-top: 8px;
	border-top: 1px solid rgba(0, 0, 0, .07);
}
/* The field name inside each error is a real <a href="#field_id"> (jumps to
   the invalid field) picking up the sitewide ".entry-content a" underline —
   fine for prose links, but this reads more like a label than a "click to
   read more", so it's underlined only on hover/focus instead, matching how
   the rest of this notice's plain text looks. */
.woocommerce-error li a {
	color: inherit;
	text-decoration: none;
}
.woocommerce-error li a:hover,
.woocommerce-error li a:focus-visible { text-decoration: underline; }
/* Underlined text link, not a button — a notice is already a small,
   low-weight strip; a full button chrome inside it competed with the
   notice's own accent color instead of reading as "one more detail here". */
.woocommerce-message .button,
.woocommerce-error .button,
.woocommerce-info .button,
.woocommerce-message a.button,
.woocommerce-error a.button,
.woocommerce-info a.button {
	margin-inline-start: auto;
	flex-shrink: 0;
	background: none;
	border: 0;
	padding: 0;
	font-weight: 600;
	font-size: var(--fs-base);
	color: var(--leaf);
	text-decoration: underline;
}
.woocommerce-error .button,
.woocommerce-error a.button { color: var(--crit); }
.woocommerce-message .button:hover,
.woocommerce-error .button:hover,
.woocommerce-info .button:hover,
.woocommerce-message a.button:hover,
.woocommerce-error a.button:hover,
.woocommerce-info a.button:hover {
	background: none;
	color: inherit;
	opacity: .75;
}

/* Empty cart: a centered icon + message + CTA, not the plain-text notice bar
   these two elements used to share with success/error messages sitewide
   (cart-empty.php renders them as siblings, .wc-empty-cart-message wrapping
   the message and .return-to-shop separate below it — centering both
   independently gets the same visual result as a shared flex parent would,
   without needing to touch that template). */
.wc-empty-cart-message {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	padding: 56px 24px;
	margin: 0 0 20px;
}
/* .cart-empty.woocommerce-info, not just .cart-empty: the actual element
   carries both classes at once (see cart/cart-empty.php), so the generic
   .woocommerce-info notice-box rule above (display:flex as a row, border,
   background, padding) was still winning on every property this doesn't
   explicitly re-declare — .woocommerce-info alone has the same one-class
   specificity as .cart-empty alone, so which one "won" came down to source
   order rather than being reliably overridden. The extra class here avoids
   depending on that. */
.cart-empty.woocommerce-info {
	display: block;
	background: none;
	border: 0;
	box-shadow: none;
	padding: 0;
	margin: 0;
	font-size: 1.1rem;
	font-weight: 600;
	color: var(--ink);
}
/* .woocommerce-info::after (further up this file) is the small checkmark
   meant to sit inside that ::before circle badge on a real notice —
   position:absolute; left:14px; top:14px, same trap as ::before above.
   .cart-empty doesn't use ::after for anything of its own, so this just
   removes it outright rather than needing to reset each property; content:
   none is what stops a pseudo-element from generating a box at all. */
.cart-empty::after {
	content: none;
}
.cart-empty::before {
	content: "";
	/* .woocommerce-info::before (further up this file) is the generic
	   notice-badge icon shared by every WC message type — a small dot fixed
	   at position:absolute; left:9px; top:9px. .cart-empty carries the
	   woocommerce-info class too (for its box styling, see the block
	   below), so its own ::before matches THAT rule as well. Equal
	   specificity (one class + one pseudo-element each) and source order
	   means this rule wins on every property it sets, but that rule's own
	   position/left/top were never in that list — position:absolute was
	   silently still in effect underneath the width/height/mask overrides
	   below, so this icon was rendering pinned 9px from a positioned
	   ancestor's corner rather than flowing in place. margin:auto centering
	   only has an effect on a normally-flowing block box, which is why nothing
	   this rule already had could have centered it. */
	position: static;
	inset-inline-start: auto;
	top: auto;
	display: block;
	width: 56px;
	height: 56px;
	margin: 0 auto 20px;
	background-color: var(--stone);
	opacity: .5;
	/* Same cart-icon path used in the header/mini-cart trigger, for visual
	   consistency rather than introducing a second icon shape — but with its
	   own recentered viewBox, not shared with those. The original viewBox
	   ('0 0 20 20') treats the icon as if it filled that square evenly, but
	   the drawn shape doesn't: measured empirically (rendered at 600x600,
	   actual black-pixel bounds), the artwork only occupies roughly
	   x:[1.27,17.73] y:[4.23,19.2] within it, leaving far more empty space
	   above/right than below/left — invisible at the ~20px this path is used
	   at elsewhere, but at this icon's 56px size mask-size:contain centers
	   that whole (lopsided) 20x20 square, not the artwork itself, so the
	   cart visibly sat low-and-left of center. This viewBox is that same
	   measured content box, squared up and re-centered on it, confirmed by
	   re-measuring the same way (left/right and top/bottom now within 2px
	   of each other at 600x600, i.e. sub-pixel at the real 56px size). */
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-0.02 2.2 19 19' fill='none'%3E%3Cpath d='M2 5h2l1.5 9.5a2 2 0 002 1.5h6a2 2 0 002-1.5L17 7H5.4' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='8' cy='18' r='1.2' fill='%23000'/%3E%3Ccircle cx='15' cy='18' r='1.2' fill='%23000'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-0.02 2.2 19 19' fill='none'%3E%3Cpath d='M2 5h2l1.5 9.5a2 2 0 002 1.5h6a2 2 0 002-1.5L17 7H5.4' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='8' cy='18' r='1.2' fill='%23000'/%3E%3Ccircle cx='15' cy='18' r='1.2' fill='%23000'/%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
}
.return-to-shop {
	text-align: center;
	margin: 0;
}
.woocommerce form .form-row.woocommerce-invalid input,
.woocommerce form .form-row.woocommerce-invalid select {
	border-color: var(--crit);
}

/* ==========================================================================
   Header
   ========================================================================== */

.announcement-bar {
	background: var(--leaf-deep);
	color: var(--paper);
	text-align: center;
	font-size: var(--fs-sm);
	letter-spacing: .01em;
	padding: 7px 16px;
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 1.6em;
}
.announcement-bar-text {
	opacity: 1;
	transition: opacity .5s ease;
}
.announcement-bar-text.is-fading {
	opacity: 0;
}

/* Desktop drops the header's own top bar entirely — no announcement
   messaging on desktop on any page. Mobile keeps it everywhere, unchanged. */
@media (min-width: 1025px) {
	.announcement-bar { display: none; }
}

/* Shop/category page's own copy of the top bar (see
   herbelo_category_announcement_bar, inc/woocommerce.php) — also hidden on
   desktop now, same as the header bar above. Left in the markup rather than
   removed since mobile never showed it either (mobile already has the real
   top bar), so it's simplest to just always hide it. */
.category-announcement-bar {
	display: none;
}

.site-header {
	border-bottom: 1px solid var(--hairline);
	background: var(--paper);
	position: sticky;
	top: 0;
	z-index: var(--z-header);
}
.header-inner {
	display: flex;
	align-items: center;
	gap: 26px;
	padding-top: 16px;
	padding-bottom: 16px;
}

.site-branding { display: flex; align-items: center; flex-shrink: 0; }
.site-branding img { width: 140px; height: auto; }
.site-title-link {
	font-family: var(--display);
	font-size: 1.42rem;
	font-weight: 700;
	letter-spacing: -.02em;
}

/* flex: 0 (not 1) so the nav takes its natural content width and doesn't
   compete with the search bar for growth — .header-search-bar is the
   element that should expand into the remaining space. */
.main-navigation { flex: 0 1 auto; display: flex; align-items: center; min-width: 0; }
.main-navigation > ul {
	display: flex;
	gap: 22px;
	flex-wrap: wrap;
}
.main-navigation ul ul { display: none; }
.main-navigation a {
	font-size: var(--fs-md);
	font-weight: 500;
	padding: 4px 0;
	border-bottom: 2px solid transparent;
	transition: color var(--t), border-color var(--t);
}
.main-navigation a:hover,
.main-navigation .current-menu-item > a {
	color: var(--leaf);
	border-bottom-color: var(--leaf);
}

/* Category bar — persistent row of links across the header's bottom edge,
   not a dropdown; scrolls horizontally instead of wrapping so it never
   grows the header's height. */
.category-bar {
	position: relative;
	border-top: 1px solid var(--hairline);
}
.category-bar-list {
	max-width: var(--shell);
	margin: 0 auto;
	padding: 0 24px;
	display: flex;
	justify-content: space-between;
	gap: 4px;
	white-space: nowrap;
	overflow-x: auto;
	scrollbar-width: none;
}
.category-bar-list::-webkit-scrollbar { display: none; }
.category-bar-list li { flex-shrink: 0; }
.category-bar-list li:last-child a { padding-inline-end: 0; }
.category-bar-list a {
	display: block;
	padding: 10px 12px;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--stone);
	border-bottom: 2px solid transparent;
	transition: color var(--t), border-color var(--t);
}
.category-bar-list a:hover {
	color: var(--leaf);
	border-bottom-color: var(--leaf);
}

.header-actions { display: flex; align-items: center; gap: 9px; margin-inline-start: auto; }
.herbelo-lang-switcher { display: flex; align-items: center; gap: 4px; font-size: var(--fs-xs); font-weight: 600; }
.herbelo-lang-link { color: var(--stone); text-decoration: none; padding: 2px 3px; }
.herbelo-lang-link:hover { color: var(--leaf); }
.header-icon-button {
	position: relative;
	width: 38px; height: 38px;
	display: inline-flex;
	align-items: center; justify-content: center;
	background: transparent;
	border: 0;
	border-radius: var(--r);
	color: var(--ink);
	padding: 0;
	cursor: pointer;
	transition: background-color var(--t), color var(--t);
}
.header-icon-button:hover {
	background: var(--mist);
	color: var(--leaf);
}
.cart-count {
	position: absolute;
	top: -6px;
	inset-inline-end: -6px;
	min-width: 21px;
	height: 21px;
	padding: 0 4px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: var(--amber);
	color: var(--paper);
	border-radius: 50%;
	font-family: var(--mono);
	font-size: var(--fs-2xs);
	font-weight: 600;
}

/* Inline search bar — sits between the nav and the account/cart icons on
   desktop. Below the nav breakpoint it drops to its own full-width row
   instead (see the 900px query), rather than being hidden behind a toggle. */
.header-search-bar {
	position: relative;
	display: flex;
	align-items: center;
	gap: 8px;
	flex: 1 1 auto;
	min-width: 160px;
	margin: 0 4px;
	padding: 0 12px;
	height: 40px;
	background: var(--mist);
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	transition: border-color var(--t), background var(--t);
}
.header-search-bar:focus-within {
	background: var(--paper);
	border-color: var(--leaf);
}
.header-search-bar-icon { color: var(--stone); flex-shrink: 0; }
.header-search-bar:focus-within .header-search-bar-icon { color: var(--leaf); }
.header-search-bar-input {
	flex: 1;
	min-width: 0;
	border: 0;
	background: transparent;
	padding: 0;
	font-size: var(--fs-base);
}
.header-search-bar-input:focus { outline: none; }
/* Native browser "clear" (x) button on type=search inputs */
.header-search-bar-input::-webkit-search-cancel-button { cursor: pointer; }

/* Results dropdown — shared by the desktop bar and the mobile panel. */
.header-search-results {
	position: absolute;
	top: calc(100% + 6px);
	inset-inline: 0;
	background: var(--paper);
	border: 1px solid var(--hairline);
	border-radius: var(--r-lg);
	box-shadow: var(--shadow-lg);
	max-height: 70vh;
	overflow-y: auto;
	z-index: var(--z-drawer);
}
.header-search-status {
	padding: 16px 14px;
	font-size: var(--fs-sm);
	color: var(--stone);
	text-align: center;
}
.header-search-results-list { display: flex; flex-direction: column; padding: 6px; }
.header-search-result {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 8px;
	border-radius: var(--r);
}
.header-search-result:hover,
.header-search-result.is-active {
	background: var(--mist);
}
.header-search-result img {
	width: 40px; height: 40px;
	object-fit: contain;
	background: var(--mist);
	border: 1px solid var(--hairline);
	border-radius: 2px;
	flex-shrink: 0;
}
.header-search-result-body {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}
.header-search-result-title {
	font-size: var(--fs-sm);
	font-weight: 600;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.header-search-result-price {
	font-family: var(--mono);
	font-size: var(--fs-xs);
	color: var(--leaf-deep);
}
.header-search-result.is-out-of-stock .header-search-result-price { color: var(--stone); }
.header-search-view-all {
	display: block;
	text-align: center;
	padding: 11px;
	border-top: 1px solid var(--hairline);
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--leaf);
}
.header-search-view-all:hover { background: var(--mist); }

.search-form { display: flex; }
.search-form .search-field {
	flex: 1;
	min-width: 0;
	border-radius: var(--r) 0 0 var(--r);
}
.search-form .search-submit { border-radius: 0 var(--r) var(--r) 0; }

/* Mobile nav trigger */
.menu-toggle {
	display: none;
	background: transparent;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	padding: 9px 8px;
	cursor: pointer;
}
.menu-toggle-bar {
	display: block;
	width: 18px; height: 1.5px;
	background: var(--ink);
	margin: 4px 0;
}

.nav-overlay {
	position: fixed;
	inset: 0;
	background: rgba(16, 26, 19, .45);
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--t);
	z-index: var(--z-overlay);
}
.nav-overlay.is-visible { opacity: 1; pointer-events: auto; }

/* ==========================================================================
   Mini-cart drawer
   ========================================================================== */

.mini-cart-drawer {
	position: fixed;
	top: 0; inset-inline-end: 0; bottom: 0;
	width: 100%;
	max-width: 396px;
	background: var(--paper);
	box-shadow: none;
	transform: translateX(100%);
	transition: transform var(--t-slow);
	z-index: var(--z-drawer);
	display: flex;
	flex-direction: column;
}
.mini-cart-drawer.is-open { transform: translateX(0); }
/* translateX has no logical/direction-aware equivalent — inset-inline-end:0
   above correctly anchors this to the left edge in RTL, but the *closed*
   transform still needs to push it further in that same direction (off the
   left edge) rather than the +100% (rightward) used for the LTR right-edge
   anchor above, or it would slide in from — and hide off — the wrong side. */
[dir="rtl"] .mini-cart-drawer { transform: translateX(-100%); }
[dir="rtl"] .mini-cart-drawer.is-open { transform: translateX(0); }

/* Header cart icon: the SVG is drawn facing right (handle on the left,
   basket opening toward the right) — mirror it on Arabic pages so it faces
   the reading direction, same idea as the flex-nav-prev/next rotation
   swaps above. */
[dir="rtl"] .mini-cart-toggle svg { transform: scaleX(-1); }

.mini-cart-drawer-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 17px 20px;
	border-bottom: 1px solid var(--hairline);
}
.mini-cart-drawer-header h2 {
	margin: 0;
	font-size: 1.05rem;
}
.mini-cart-item-count {
	font-size: var(--fs-sm);
	font-weight: 400;
	color: var(--stone);
}
.mini-cart-close {
	background: transparent;
	border: 0;
	color: var(--stone);
	font-size: 1.5rem;
	line-height: 1;
	padding: 2px 6px;
	cursor: pointer;
}
.mini-cart-close:hover { background: transparent; color: var(--ink); }

.mini-cart-contents {
	flex: 1;
	overflow-y: auto;
	padding: 18px 20px;
	display: flex;
	flex-direction: column;
}
.mini-cart-empty { color: var(--stone); text-align: center; margin-top: 36px; }
.mini-cart-shop-link { align-self: center; }

.mini-cart-items { display: flex; flex-direction: column; gap: 16px; }
.mini-cart-item {
	display: grid;
	grid-template-columns: 60px minmax(0, 1fr) auto;
	gap: 12px;
	align-items: start;
}
.mini-cart-item-image img {
	width: 60px; height: 60px;
	object-fit: cover;
	background: var(--mist);
	border: 1px solid var(--hairline);
	border-radius: var(--r);
}
.mini-cart-item-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mini-cart-item-title { font-size: var(--fs-base); font-weight: 600; }
/* A plain <select class="qty mini-cart-item-qty"> — no stepper, no wrapper
   div (nothing here to decorate: initQuantitySteppers only ever looks for
   input.qty, so a <select> is simply left alone). It still inherits the
   sitewide select border/padding/font-size (see the generic
   input/select/textarea rule near the top of this file), sized for a
   full-width checkout field — this scales it down to fit a compact item row
   instead. */
.mini-cart-item-qty {
	align-self: flex-start;
	width: auto;
	padding: 4px 22px 4px 8px;
	font-size: var(--fs-xs);
	color: var(--stone);
	border-color: var(--hairline);
}
.mini-cart-item-price { font-family: var(--mono); font-weight: 700; font-size: var(--fs-base); }
.mini-cart-item-remove { color: var(--stone); font-size: 1.1rem; line-height: 1; padding: 2px 4px; }
.mini-cart-item-remove:hover { color: var(--crit); }

.mini-cart-upsell {
	margin-top: 18px;
	padding-top: 16px;
	border-top: 1px solid var(--hairline);
}
.mini-cart-upsell-title {
	font-size: var(--fs-xs);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .06em;
	color: var(--stone);
	margin: 0 0 12px;
}
.mini-cart-upsell-list { display: flex; flex-direction: column; gap: 12px; }
.mini-cart-upsell-item {
	display: grid;
	grid-template-columns: 44px minmax(0, 1fr) auto;
	gap: 10px;
	align-items: center;
}
.mini-cart-upsell-image img {
	width: 44px; height: 44px;
	object-fit: cover;
	background: var(--mist);
	border: 1px solid var(--hairline);
	border-radius: var(--r);
}
.mini-cart-upsell-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mini-cart-upsell-name {
	font-size: var(--fs-sm);
	font-weight: 600;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.mini-cart-upsell-price { font-family: var(--mono); font-size: var(--fs-xs); color: var(--stone); }
/* Icon-only add-to-cart, same treatment as the shop-grid quick-add button
   (.product-card-actions .button) — a text button ("Ajouter au panier" /
   "أضف إلى السلة") was too wide for this compact row, encroaching on the
   product name/price next to it. */
.mini-cart-upsell-item .button,
.mini-cart-upsell-item a.button {
	position: relative;
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	padding: 0;
	font-size: 0;
	background: transparent;
	color: var(--leaf);
	border-color: var(--leaf);
	border-radius: 50%;
}
.mini-cart-upsell-item .button:hover,
.mini-cart-upsell-item a.button:hover {
	background: var(--leaf);
	color: var(--paper);
}
.mini-cart-upsell-item .button::before,
.mini-cart-upsell-item a.button::before {
	content: "";
	width: 15px; height: 15px;
	flex-shrink: 0;
	background-color: currentColor;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M2 5h2l1.5 9.5a2 2 0 002 1.5h6a2 2 0 002-1.5L17 7H5.4' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='8' cy='18' r='1.3' fill='%23000'/%3E%3Ccircle cx='15' cy='18' r='1.3' fill='%23000'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M2 5h2l1.5 9.5a2 2 0 002 1.5h6a2 2 0 002-1.5L17 7H5.4' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='8' cy='18' r='1.3' fill='%23000'/%3E%3Ccircle cx='15' cy='18' r='1.3' fill='%23000'/%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
}
/* Variable products render this as a link to the product page instead of an
   instant add ("Choix des options") — same swap the shop-grid button makes
   (.product-card-actions .button:not(.add_to_cart_button)), so the icon
   doesn't promise an instant add it can't do. */
.mini-cart-upsell-item .button:not(.add_to_cart_button),
.mini-cart-upsell-item a.button:not(.add_to_cart_button) {
	color: var(--stone);
	border-color: var(--stone);
}
.mini-cart-upsell-item .button:not(.add_to_cart_button):hover,
.mini-cart-upsell-item a.button:not(.add_to_cart_button):hover {
	background: var(--stone);
	color: var(--paper);
}
.mini-cart-upsell-item .button:not(.add_to_cart_button)::before,
.mini-cart-upsell-item a.button:not(.add_to_cart_button)::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='8.5' cy='8.5' r='6' stroke='%23000' stroke-width='1.7'/%3E%3Cpath d='M13 13l4.5 4.5' stroke='%23000' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='8.5' cy='8.5' r='6' stroke='%23000' stroke-width='1.7'/%3E%3Cpath d='M13 13l4.5 4.5' stroke='%23000' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E");
}

.mini-cart-footer {
	/* .mini-cart-footer is a child of .mini-cart-contents, which is both the
	   overflow-y:auto scroll container AND a flex column (see rule above) —
	   see template-parts/mini-cart.php. That combination is what lets one
	   rule handle both cases:
	   - Few items (nothing to scroll): margin-top:auto consumes the
	     leftover flex space above this element, pushing it all the way down
	     to the bottom of the drawer instead of leaving it stranded right
	     under the last item with empty space below.
	   - Many items (list overflows): auto margins collapse to 0 once there's
	     no free space left to distribute, so position:sticky + bottom:0
	     takes over instead, pinning this to the bottom of the visible
	     scrolled area rather than letting it scroll out of reach.
	   The opaque background stops item rows from showing through underneath
	   it while scrolling past in that second case. */
	position: sticky;
	bottom: 0;
	margin-top: auto;
	background: var(--paper);
	border-top: 1px solid var(--hairline);
	padding-top: 16px;
	display: flex;
	flex-direction: column;
	gap: 9px;
}
.mini-cart-subtotal {
	display: flex;
	justify-content: space-between;
	font-weight: 700;
	margin-bottom: 2px;
}
.mini-cart-subtotal .amount { font-family: var(--mono); }

/* ==========================================================================
   Breadcrumbs
   ========================================================================== */

.woocommerce-breadcrumb,
.breadcrumbs {
	display: none;
	max-width: var(--shell);
	margin: 16px auto 0;
	padding: 0 24px;
	font-size: var(--fs-sm);
	color: var(--stone);
}
/* Visible on the product page only — shows the category trail (now
   including the actual product category, see post_types-product-maintax
   in inc/woocommerce.php) directly above the product title. Left hidden
   everywhere else, matching this theme's existing design (shop/category
   archives don't show it either); scope this wider only if asked. */
.single-product .breadcrumbs { display: block; }
.shop-layout .woocommerce-breadcrumb {
	max-width: none;
	margin: 16px 0 14px;
	padding: 0;
}
.woocommerce-breadcrumb a:hover,
.breadcrumbs a:hover { color: var(--leaf); text-decoration: underline; }

/* ==========================================================================
   Shop layout — main + sidebar share this grid parent
   ========================================================================== */

.shop-layout {
	max-width: var(--shell);
	margin: 0 auto;
	padding: 0 24px;
	display: grid;
	grid-template-columns: 288px minmax(0, 1fr);
	gap: 36px;
	align-items: start;
}
.shop-layout--full { grid-template-columns: minmax(0, 1fr); }
/* Content first in the DOM, filters visually left. */
.shop-layout > .site-main {
	grid-column: 2;
	grid-row: 1;
	max-width: none;
	margin: 0;
	padding: 0;
	min-width: 0;
}
.shop-layout--full > .site-main { grid-column: 1; }
.shop-layout > #secondary { grid-column: 1; grid-row: 1; }

/* The grid itself now shows a skeleton (see initShopAjax in main.js) rather
   than a dimmed stale grid, so this only needs to block interaction —
   nothing to fade since the content underneath has already been replaced. */
.shop-layout.is-loading > .site-main { pointer-events: none; }

/* Shop page header — now a sibling before .shop-layout (see inc/woocommerce.php),
   so it needs its own copy of the shell width/padding to line up with the
   grid below instead of inheriting them from a parent. */
.woocommerce-products-header {
	max-width: var(--shell);
	margin: 20px auto 10px;
	padding: 0 24px;
}
.woocommerce-products-header__title,
.archive-title {
	font-size: 1.68rem;
	letter-spacing: -.015em;
	margin-bottom: 4px;
}
.woocommerce-products-header .page-description,
.archive-description { color: var(--stone); font-size: var(--fs-md); }
.woocommerce-products-header .page-description p:empty { display: none; }

/* Toolbar — count and sort are unwrapped siblings, so they're floated */
.woocommerce-result-count,
.woocommerce-ordering { margin: 0; }
.shop-layout .woocommerce-result-count {
	float: inline-start;
	font-size: var(--fs-sm);
	color: var(--stone);
	line-height: 40px;
	font-family: var(--mono);
}
.shop-layout .woocommerce-ordering { float: inline-end; }
.woocommerce-ordering select,
select.orderby {
	padding: 9px 12px;
	font-size: var(--fs-base);
	max-width: 100%;
}
.shop-layout ul.products,
.shop-layout .woocommerce-pagination { clear: both; }
.shop-layout ul.products { padding-top: 14px; }

/* ==========================================================================
   Product grid
   ========================================================================== */

ul.products {
	display: grid !important;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 20px;
	margin: 0 !important;
	padding: 0;
	list-style: none;
}
.shop-layout ul.products,
.related ul.products,
.upsells ul.products {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.product-card {
	display: flex;
	flex-direction: column;
	background: var(--paper);
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	overflow: hidden;
	transition: border-color var(--t);
}
.product-card:hover { border-color: var(--leaf); }

/* Portrait ratio, because the store's product photography is portrait
   (bottles/boxes, e.g. 1920x2560). Forcing 1:1 left tall products floating
   in a square with wide empty gutters. */
.product-card-image {
	position: relative;
	aspect-ratio: 1;
	background: var(--paper);
	border-bottom: 1px solid var(--hairline);
}
.product-card-image img {
	width: 100%; height: 100%;
	object-fit: contain;
	padding: 12px;
}
.product-card-image .onsale {
	position: absolute;
	top: 10px; left: 10px;
	font-family: var(--mono);
	font-size: var(--fs-2xs);
	font-weight: 700;
	letter-spacing: .07em;
	padding: 3px 6px;
	border-radius: 2px;
	background: var(--amber-wash);
	border: 1px solid var(--amber);
	color: var(--amber-deep);
}

.product-card-body { padding: 13px 14px 0; flex: 1; }
.product-card-brand {
	font-size: var(--fs-2xs);
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--stone);
	font-weight: 700;
	margin-bottom: 5px;
}
.product-card-title {
	font-family: var(--display);
	font-size: var(--fs-md);
	font-weight: 600;
	line-height: 1.32;
	margin: 0 0 8px;
	/* Clamped to 2 lines so uneven title lengths don't stagger the price/
	   add-to-cart row across a grid of otherwise same-height cards. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.product-card-meta {
	font-family: var(--mono);
	font-size: var(--fs-xs);
	color: var(--stone);
}
.product-card-rating {
	display: flex;
	align-items: center;
	gap: 4px;
	margin: 0 0 6px;
	font-family: var(--mono);
	font-size: var(--fs-xs);
}
.product-card-rating-star {
	width: 12px; height: 12px;
	flex-shrink: 0;
	background-color: var(--amber);
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 1l2.6 5.4 5.9.8-4.3 4.2 1 5.9L10 14.9l-5.2 2.4 1-5.9L1.5 7.2l5.9-.8L10 1z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 1l2.6 5.4 5.9.8-4.3 4.2 1 5.9L10 14.9l-5.2 2.4 1-5.9L1.5 7.2l5.9-.8L10 1z'/%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}
.product-card-rating-value { font-weight: 700; color: var(--ink); }
.product-card-rating-count { color: var(--stone); }
.product-card-foot {
	padding: 11px 14px 14px;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	margin-top: auto;
}
/* Variable-product quick-add (herbelo_loop_add_to_cart, inc/woocommerce.php)
   — always wraps to its own full-width line below the price, rather than
   competing for the same narrow row a simple product's single icon button
   fits in. */
.loop-variation-picker {
	display: flex;
	align-items: center;
	gap: 8px;
	flex: 1 1 100%;
}
.loop-variation-swatches {
	display: flex;
	flex-wrap: wrap;
	gap: 5px;
	flex: 1;
}
.loop-variation-swatch {
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	padding: 3px 8px;
	font-size: var(--fs-2xs);
	font-weight: 600;
	color: var(--ink);
	background: var(--paper);
	cursor: pointer;
}
.loop-variation-swatch:hover { border-color: var(--stone); }
.loop-variation-swatch.is-selected {
	border-color: var(--leaf);
	background: var(--leaf-wash);
	color: var(--leaf-deep);
}
.loop-variation-swatch.is-disabled {
	color: var(--stone);
	text-decoration: line-through;
	opacity: .55;
	cursor: not-allowed;
}
/* The button itself reuses .product-card-actions .button's circular
   icon-only treatment automatically (same markup shape: a .button inside
   .product-card-actions) — only the disabled state needs its own rule,
   gated on product-choice state here rather than product type. */
.loop-variation-add-to-cart:disabled {
	opacity: .4;
	cursor: not-allowed;
	pointer-events: none;
}
/* "Already in cart" — same green-fill + checkmark treatment as a simple
   product's own .add_to_cart_button.is-in-cart, applied to the picker's
   button regardless of its own disabled/not-yet-chosen state: the parent
   product being in the customer's cart is true independent of whatever
   the swatches are currently set to, so this deliberately wins over the
   :disabled rule above (same specificity, declared after it) rather than
   waiting for a swatch pick to show it. */
.loop-variation-picker.is-in-cart .loop-variation-add-to-cart {
	opacity: 1;
	pointer-events: auto;
	background: var(--leaf);
	color: var(--paper);
	border-color: var(--leaf);
}
.loop-variation-picker.is-in-cart .loop-variation-add-to-cart::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 10.5l4.5 4.5L17 5' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 10.5l4.5 4.5L17 5' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.product-card-price {
	font-family: var(--mono);
	font-weight: 700;
	font-size: var(--fs-md);
}
.product-card-price del {
	color: var(--stone);
	font-weight: 400;
	font-size: var(--fs-sm);
	margin-inline-end: 5px;
}
.product-card-price ins { text-decoration: none; }
.product-card-price .woocommerce-Price-currencySymbol {
	font-size: var(--fs-xs);
	color: var(--stone);
	font-weight: 600;
}
/* Same reasoning as the single-product price rule above: "دج" needs more
   size than "DA" did to stay legible in a product card. */
[dir="rtl"] .product-card-price .woocommerce-Price-currencySymbol {
	font-size: var(--fs-md);
}

/* ==========================================================================
   Shop grid skeleton — shown the instant a filter/pagination fetch starts,
   in place of ul.products, so the grid never collapses to nothing while
   waiting. Every box below reuses the real card's own padding/aspect-ratio
   values (not approximations) specifically so this doesn't itself become a
   CLS source once the real cards swap in — same box model, just gray fills
   instead of content.
   ========================================================================== */
.product-card-skeleton { pointer-events: none; }
.product-card-skeleton .product-card-image { background: var(--mist); }
.product-card-skeleton .product-card-body { padding-bottom: 13px; }
.skeleton-bar {
	background: linear-gradient(90deg, var(--mist) 25%, var(--hairline) 37%, var(--mist) 63%);
	background-size: 400% 100%;
	border-radius: 3px;
	animation: skeleton-shimmer 1.4s ease infinite;
}
@keyframes skeleton-shimmer {
	0% { background-position: 100% 50%; }
	100% { background-position: 0 50%; }
}
.skeleton-bar--brand { width: 44%; height: 10px; margin-bottom: 8px; }
.skeleton-bar--title { width: 100%; height: 13px; margin-bottom: 6px; }
.skeleton-bar--title-short { width: 70%; height: 13px; margin-bottom: 8px; }
.skeleton-bar--meta { width: 36%; height: 10px; }
.skeleton-bar--price { width: 56px; height: 17px; }
.skeleton-bar--button { width: 34px; height: 34px; border-radius: var(--r); }
@media (prefers-reduced-motion: reduce) {
	.skeleton-bar { animation: none; background: var(--mist); }
}

/* ==========================================================================
   Single product
   ========================================================================== */

.single-product .site-main { padding-top: 8px; padding-bottom: 60px; }

/* Only gallery + summary occupy the two columns; anything else spans full
   width, so stray siblings can't land in a half-width column and collide. */
.woocommerce div.product {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 420px) minmax(0, 240px);
	column-gap: 40px;
	row-gap: 8px;
	align-items: start;
	margin-top: 20px;
}
.woocommerce div.product > * {
	grid-column: 1 / -1;
	min-width: 0;
}
.woocommerce div.product > .woocommerce-product-gallery {
	grid-column: 1;
	grid-row: 1;
}
.woocommerce div.product > .summary,
.woocommerce div.product > .entry-summary {
	grid-column: 2;
	grid-row: 1;
}
.woocommerce div.product > .product-delivery-info {
	grid-column: 3;
	grid-row: 1;
}

/* --- Gallery: the image stands on its own, no framing panel --- */
.woocommerce div.product .woocommerce-product-gallery {
	position: sticky;
	top: 96px;
}
.woocommerce div.product .woocommerce-product-gallery__wrapper {
	position: relative;
	margin: 0;
	background: var(--paper);
	border-radius: 2px;
	overflow: hidden;
	/* Caps any momentary over-tall render of this element during flexslider's
	   multi-step init (measured live: every gallery image sits stacked in
	   plain flow until flexslider fully finishes configuring its slide-track,
	   briefly reaching 6000px+ tall on a 3-image product) to roughly one
	   image's worth of height, matching the eventual real, JS-driven size.
	   That balloon-then-collapse was this page's entire 0.127 CLS score,
	   landing on whatever sits below the gallery in the single-column mobile
	   layout. Deliberately a height cap rather than trying to match
	   flexslider's exact init sequence step-for-step (tried gating on
	   .flex-viewport's presence, then on its own inline width:600% — both
	   still raced one of its intermediate steps live) — max-height clips
	   every intermediate state the same way regardless of which step it's
	   from, without depending on that sequence at all.  */
	max-height: 100vw;
}
.woocommerce div.product .woocommerce-product-gallery__image { cursor: zoom-in; }
/* WooCommerce's own zoom trigger — a real, working, keyboard-accessible
   button that already opens the lightbox correctly (single-product.js binds
   its click handler directly to this element). It just injects a literal 🔍
   emoji as its content at runtime, so give it a real icon instead: keep the
   emoji in the DOM at font-size:0 (still readable by screen readers) and
   draw the icon with CSS the same way every other icon in this theme works. */
.woocommerce div.product .woocommerce-product-gallery__trigger {
	position: absolute;
	inset-inline-end: 12px; bottom: 12px;
	width: 34px; height: 34px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background-color: var(--paper);
	box-shadow: 0 1px 4px rgba(16, 26, 19, .18);
	z-index: 3;
	font-size: 0;
}
.woocommerce div.product .woocommerce-product-gallery__trigger::before {
	content: "";
	width: 17px; height: 17px;
	background-color: var(--ink);
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='8.5' cy='8.5' r='5.5' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M12.8 12.8 17 17' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/%3E%3Cpath d='M8.5 6.3v4.4M6.3 8.5h4.4' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='8.5' cy='8.5' r='5.5' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M12.8 12.8 17 17' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/%3E%3Cpath d='M8.5 6.3v4.4M6.3 8.5h4.4' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}
.woocommerce div.product .woocommerce-product-gallery__trigger:hover::before { background-color: var(--leaf); }
.woocommerce div.product .woocommerce-product-gallery img {
	width: 100%;
	aspect-ratio: 1;
	object-fit: contain;
	border-radius: 2px;
}
.woocommerce div.product .zoomImg,
.woocommerce div.product .zoomWindow,
.woocommerce div.product .zoomContainer {
	z-index: calc(var(--z-drawer) + 10) !important;
}
.woocommerce div.product .flex-viewport {
	border-radius: 2px;
	overflow: hidden;
	background: var(--paper);
}
.woocommerce div.product .woocommerce-product-gallery .onsale {
	position: absolute;
	top: 12px; left: 12px;
	z-index: 2;
	font-family: var(--mono);
	font-size: var(--fs-2xs);
	font-weight: 700;
	letter-spacing: .07em;
	background: var(--amber-wash);
	border: 1px solid var(--amber);
	color: var(--amber-deep);
	padding: 4px 8px;
	border-radius: 2px;
}

/* Gallery arrows */
.woocommerce div.product ul.flex-direction-nav { margin: 0; }
.woocommerce div.product .flex-direction-nav li { list-style: none; }
.woocommerce div.product .flex-direction-nav a {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	width: 36px; height: 36px;
	display: flex;
	align-items: center; justify-content: center;
	background: var(--paper);
	border: 1px solid var(--hairline);
	border-radius: 50%;
	font-size: 0;
	opacity: 0;
	transition: opacity var(--t);
	z-index: 2;
}
.woocommerce div.product .woocommerce-product-gallery:hover .flex-direction-nav a { opacity: 1; }
.woocommerce div.product .flex-direction-nav a::before {
	content: "";
	width: 7px; height: 7px;
	border: 1.6px solid var(--ink);
	border-width: 1.6px 1.6px 0 0;
}
.woocommerce div.product .flex-direction-nav .flex-nav-prev a { inset-inline-start: 10px; }
.woocommerce div.product .flex-direction-nav .flex-nav-prev a::before { transform: rotate(-135deg) translate(1px, -1px); }
.woocommerce div.product .flex-direction-nav .flex-nav-next a { inset-inline-end: 10px; }
.woocommerce div.product .flex-direction-nav .flex-nav-next a::before { transform: rotate(45deg) translate(-1px, -1px); }
/* flexslider itself auto-detects dir="rtl" on <html> and handles the actual
   slide mechanics without any config from here — this only needs the same
   chevron-swap the other sliders above do. */
[dir="rtl"] .woocommerce div.product .flex-direction-nav .flex-nav-prev a::before { transform: rotate(45deg) translate(1px, -1px); }
[dir="rtl"] .woocommerce div.product .flex-direction-nav .flex-nav-next a::before { transform: rotate(-135deg) translate(-1px, -1px); }

/* Thumbnails */
.woocommerce div.product .flex-control-thumbs {
	/* This is an <ol>, not a <ul> — the sitewide list reset near the top of
	   this file only zeroes list-style/margin/padding on ul, so these
	   thumbnails were getting the browser's default decimal numbering
	   ("1. 2. 3.") stacked right on top of each image. */
	list-style: none;
	display: flex;
	gap: 8px;
	margin-top: 14px;
	padding: 0;
	flex-wrap: wrap;
}
.woocommerce div.product .flex-control-thumbs li { width: 62px; }
.woocommerce div.product .flex-control-thumbs img {
	background: var(--paper);
	border: 1px solid var(--hairline);
	border-radius: 2px;
	aspect-ratio: 1;
	object-fit: contain;
	padding: 3px;
	cursor: pointer;
	opacity: .8;
	transition: opacity var(--t), border-color var(--t);
}
.woocommerce div.product .flex-control-thumbs img:hover { opacity: 1; }
.woocommerce div.product .flex-control-thumbs img.flex-active {
	border-color: var(--leaf);
	box-shadow: inset 0 0 0 1px var(--leaf);
	opacity: 1;
}

/* PhotoSwipe lightbox — exempt from the global img max-width reset */
.pswp { z-index: 9999; }
.pswp img { max-width: none; max-height: none; }

/* Real SVG icons for the lightbox controls, replacing WooCommerce's bundled
   PhotoSwipe sprite (a low-res PNG that something in the stack — LiteSpeed's
   optimizer, going by the injected rule — was forcing over the SVG version
   anyway). !important is needed to beat that forced background-image. */
.pswp__button {
	background-image: none !important;
	opacity: 1 !important;
}
.pswp__button--share,
.pswp__button--fs { display: none !important; }
.pswp__button--zoom,
.pswp__button--close {
	position: relative;
	width: 44px; height: 44px;
	border-radius: 50%;
	background-color: rgba(16, 26, 19, .45) !important;
	transition: background-color var(--t);
}
.pswp__button--zoom:hover,
.pswp__button--close:hover { background-color: rgba(16, 26, 19, .7) !important; }
.pswp__button--zoom::before,
.pswp__button--close::before {
	content: "";
	position: absolute;
	top: 50%; left: 50%;
	transform: translate(-50%, -50%);
	width: 20px; height: 20px;
	background-color: var(--paper);
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
}
.pswp__button--zoom::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='8.5' cy='8.5' r='5.5' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M12.8 12.8 17 17' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/%3E%3Cpath d='M8.5 6.3v4.4M6.3 8.5h4.4' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='8.5' cy='8.5' r='5.5' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M12.8 12.8 17 17' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/%3E%3Cpath d='M8.5 6.3v4.4M6.3 8.5h4.4' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
}
.pswp--zoomed-in .pswp__button--zoom::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='8.5' cy='8.5' r='5.5' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M12.8 12.8 17 17' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/%3E%3Cpath d='M6.3 8.5h4.4' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='8.5' cy='8.5' r='5.5' stroke='%23000' stroke-width='1.6'/%3E%3Cpath d='M12.8 12.8 17 17' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/%3E%3Cpath d='M6.3 8.5h4.4' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
}
.pswp__button--close::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M4.5 4.5l11 11M15.5 4.5l-11 11' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M4.5 4.5l11 11M15.5 4.5l-11 11' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
}
.pswp__button--arrow--left,
.pswp__button--arrow--right { background: none !important; }
.pswp__button--arrow--left::before,
.pswp__button--arrow--right::before {
	content: "";
	position: absolute;
	top: 50%; left: 50%;
	width: 42px; height: 42px;
	margin: -21px 0 0 -21px;
	border-radius: 50%;
	background-color: rgba(16, 26, 19, .45) !important;
	background-image: none !important;
}
.pswp__button--arrow--left::after,
.pswp__button--arrow--right::after {
	content: "";
	position: absolute;
	top: 50%; left: 50%;
	width: 10px; height: 10px;
	border: 1.8px solid var(--paper);
	border-width: 1.8px 1.8px 0 0;
}
.pswp__button--arrow--left::after { transform: translate(-30%, -50%) rotate(-135deg); }
.pswp__button--arrow--right::after { transform: translate(-70%, -50%) rotate(45deg); }

/* --- Buy box --- */
.woocommerce div.product .summary.entry-summary { max-width: none; }

/* Legacy code emits a couple of empty wrappers into the summary; they'd
   otherwise leave dead vertical gaps between blocks. */
.woocommerce div.product .summary > div:empty,
.woocommerce div.product .summary > p:empty { display: none; }

.woocommerce div.product .summary .product_title {
	font-size: clamp(1.15rem, 2vw, 1.5rem);
	letter-spacing: -.015em;
	margin-bottom: 10px;
}

/* Brand + barcode line (output by herbelo-store-logic) — plain metadata,
   no box: it's a footnote to the title, not a callout.
   No font-family here: the UPC number already gets var(--mono) from its own
   inline style (herbelo-store-logic wraps just the digits in
   <span style="font-family:monospace">), which is where it belongs — a
   barcode reads better in a monospace face. This rule used to force that
   onto the WHOLE line with !important, monospace-ing "بواسطة" and the
   brand name too, which (confirmed live) looks visibly wrong for Arabic
   text — monospace typefaces have weak/inconsistent Arabic glyph support
   compared to the site's normal --sans stack. */
.woocommerce div.product .brand-ean {
	font-size: var(--fs-xs) !important;
	color: var(--stone) !important;
	margin: 4px 0 16px !important;
	padding: 0;
	background: none;
	border: 0;
}
.woocommerce div.product .brand-ean a {
	color: var(--ink) !important;
	font-weight: 600;
	text-decoration: none !important;
}
.woocommerce div.product .brand-ean a:hover { color: var(--leaf) !important; }

/* Rating — same badge as the shop-grid card (.product-card-rating and its
   children, styled near the product-card rules above), just given more
   breathing room here since the product page isn't a cramped card. */
.woocommerce div.product .product-single-rating {
	margin-bottom: 14px !important;
	font-size: var(--fs-base);
}
.woocommerce div.product .product-single-rating .product-card-rating-count:hover {
	color: var(--leaf);
}

/* Price + stock availability, same row (herbelo_single_product_price_and_stock()) */
.product-price-stock-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	column-gap: 16px;
	row-gap: 4px;
	margin: 0 0 16px;
}
.product-price-stock-row p.price { margin: 0; }
/* Price pinned at the row's start edge, badge at its end edge — with
   exactly 2 real flex children (the p:empty rule below removes the two
   stray empty <p>s that used to sit between them and confuse this),
   justify-content: space-between on the container alone pushes both all
   the way to their edges. Deliberately not using a per-item auto margin
   for this: margin-inline-start/-end map to physical sides off the
   element's own direction, NOT off flex-direction, so a rule tuned for
   French's plain "row" broke under Arabic's without a second, separately-
   tuned RTL override — confirmed live, twice. justify-content has no such
   direction pitfall, and no [dir="rtl"] flex-direction: row-reverse is
   used either: plain "row" already puts price at the RTL inline start
   (the right edge) and the badge at the end (left) — the mirror image of
   French's price-left/badge-right, which is what "reverse on RTL" means
   here — with the exact same one rule doing both directions correctly. */
.woocommerce div.product .product-price-stock-row .stock,
.woocommerce div.product .product-price-stock-row .custom_availability {
	margin: 0;
}
/* Legacy's custom_availability_text() filter puts a <div> where
   single-product/stock.php wraps its return value in a <p> — a <div>
   can't legally sit inside a <p>, so the browser closes the <p> early,
   leaving that <p> empty. The div's own source string still has its
   original closing </p> after it, now orphaned (no open <p> left to
   close) — per the HTML5 parsing spec, a stray </p> end tag doesn't just
   get dropped, it synthesizes a brand new empty <p> (with no class,
   confirmed live via computed styles) right then and there. Net result:
   TWO empty <p> elements end up as extra flex children alongside the
   real price/badge — targeting p:empty generically (not just p.stock)
   catches both, since the second one has nothing else to select on. */
.woocommerce div.product .product-price-stock-row p:empty {
	display: none;
}
/* Price */
.woocommerce div.product p.price,
.woocommerce div.product .woocommerce-variation-price .price {
	font-family: var(--mono);
	font-size: 1.75rem;
	font-weight: 700;
	letter-spacing: -.02em;
	color: var(--ink);
	margin: 0 0 16px;
	display: flex;
	align-items: baseline;
	gap: 10px;
	flex-wrap: wrap;
}
.woocommerce div.product p.price del {
	color: var(--stone);
	font-size: var(--fs-md);
	font-weight: 400;
}
.woocommerce div.product p.price ins { text-decoration: none; }
.woocommerce div.product p.price .woocommerce-Price-currencySymbol,
.woocommerce div.product .woocommerce-variation-price .price .woocommerce-Price-currencySymbol {
	font-size: var(--fs-base);
	font-weight: 600;
	color: var(--stone);
}
/* "DA" reads fine this small — two plain capital letters. "دج" doesn't:
   Arabic's thinner, more detailed letterforms need more size to stay
   legible, so at the same size next to a large price number it looked cut
   off/illegible rather than just "subtle" the way "DA" does. */
[dir="rtl"] .woocommerce div.product p.price .woocommerce-Price-currencySymbol,
[dir="rtl"] .woocommerce div.product .woocommerce-variation-price .price .woocommerce-Price-currencySymbol {
	font-size: 1.05rem;
}
/* Picking a variation swaps the price range (p.price, above) for this
   single-price element instead — confirmed live: it fell back to
   completely unstyled plain text (no size/weight/font rules ever targeted
   it, since it's a <span class="price"> nested in .woocommerce-variation-
   price, not the bare p.price WooCommerce uses everywhere else), a visibly
   jarring size drop right after selecting a swatch. */
.woocommerce div.product .woocommerce-variation-price { margin-bottom: 4px; }

.product-authenticity-badge {
	display: flex;
	align-items: center;
	gap: 6px;
	margin: 0 0 14px;
	font-size: var(--fs-md);
	font-weight: 700;
	color: var(--leaf-deep);
}
.product-authenticity-badge-icon {
	width: 13px; height: 13px;
	flex-shrink: 0;
	background-color: currentColor;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M10 2 3.5 4.5v5c0 4.4 2.8 7.7 6.5 9 3.7-1.3 6.5-4.6 6.5-9v-5L10 2Z' stroke='%23000' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='m7 10 2 2 4-4' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M10 2 3.5 4.5v5c0 4.4 2.8 7.7 6.5 9 3.7-1.3 6.5-4.6 6.5-9v-5L10 2Z' stroke='%23000' stroke-width='1.6' stroke-linejoin='round'/%3E%3Cpath d='m7 10 2 2 4-4' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}

/* Short description bullets — top/bottom rule only, so this key-benefits
   list reads as its own section set apart from the price above and the
   buy box below, without boxing it in on the sides. */
.woocommerce div.product .woocommerce-product-details__short-description {
	margin-bottom: 18px;
	padding: 14px 0;
	border-top: 1px solid var(--hairline);
	border-bottom: 1px solid var(--hairline);
	font-size: var(--fs-md);
}
.woocommerce div.product .woocommerce-product-details__short-description ul {
	display: grid;
	gap: 7px;
}
.woocommerce div.product .woocommerce-product-details__short-description li {
	position: relative;
	padding-inline-start: 20px;
	list-style: none;
}
.woocommerce div.product .woocommerce-product-details__short-description li::before {
	content: "";
	position: absolute;
	inset-inline-start: 2px; top: .54em;
	width: 8px; height: 4px;
	border: 1.8px solid var(--leaf);
	border-width: 0 0 1.8px 1.8px;
	transform: rotate(-45deg);
}
/* 2 products' Arabic short-description bullets were imported with a literal
   inline style="text-align: left;" baked onto every <li> (confirmed via a
   DB search — see the site's product RTL fixes for the matching table
   issue). Unlike the table's presentational align="" attribute, this is
   real CSS on the element itself, so only !important can outrank it.
   Scoped to [dir="rtl"] — French pages never had this problem. */
[dir="rtl"] .woocommerce div.product .woocommerce-product-details__short-description li {
	text-align: right !important;
}

/* Availability line */
.woocommerce div.product .stock,
.woocommerce div.product .custom_availability {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: var(--fs-base);
	font-weight: 600;
	margin: 0 0 14px;
}
.woocommerce div.product p.stock { margin-bottom: 14px; }

/* Add-to-cart form — grid rather than flex-grow so the button's width is a
   deterministic "everything left over", not something that has to win a
   flex-basis/min-content tug-of-war against the quantity control (which
   differs in markup between a plain number input and a variation's select). */
#add-to-cart-form { margin-bottom: 18px; }
/* :not(.variations_form) — a variable product's form.cart holds the
   attribute table + .single_variation_wrap as its direct children, not
   quantity/button directly, so this grid must not apply there (it was
   scrambling the attribute picker into the same 2-column grid). */
.woocommerce div.product form.cart:not(.variations_form) {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	align-items: stretch;
	gap: 10px;
	margin: 0;
}
/* Variable products nest quantity + button inside this wrapper instead of
   putting them directly in form.cart, so the grid rule above never reaches
   them there — same treatment, applied one level deeper. */
.woocommerce div.product .woocommerce-variation-add-to-cart {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	align-items: stretch;
	gap: 10px;
	margin-top: 4px;
}
.quantity {
	display: flex;
	align-items: stretch;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	overflow: hidden;
	width: fit-content;
}
.quantity .qty,
.quantity select {
	width: 54px;
	border: 0;
	text-align: center;
	text-align-last: center;
	border-radius: 0;
	background: var(--paper);
	font-family: var(--mono);
	padding: 10px 4px;
}
.quantity-stepper-button {
	width: 38px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--mist);
	border: 0;
	color: var(--ink);
	padding: 0;
	cursor: pointer;
	border-radius: 0;
}
.quantity-stepper-button:hover { background: var(--mist-deep); }
.woocommerce div.product form.cart .button {
	width: 100%;
	font-size: 1rem;
	padding: 14px 22px;
}
.woocommerce div.product form.cart .button.loading { opacity: .6; pointer-events: none; }
/* "Already in cart" (assets/js/main.js, initAlreadyInCartCheck) — a
   lighter, secondary-looking fill rather than the same solid green as
   the primary "Commander" state, so it reads as a status being reported
   back rather than still being the main call to action. Still fully
   clickable — this is informational, not a block on adding another one. */
.woocommerce div.product form.cart .button.is-in-cart {
	background: var(--leaf-wash);
	color: var(--leaf-deep);
	border-color: var(--leaf);
}
.woocommerce div.product form.cart .button.is-in-cart::before {
	content: "";
	display: inline-block;
	width: 15px; height: 15px;
	margin-inline-end: 7px;
	vertical-align: -2px;
	background-color: currentColor;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 10.5l4.5 4.5L17 5' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 10.5l4.5 4.5L17 5' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}

/* ==========================================================================
   Thank-you (order-received) page — custom template, see
   woocommerce/checkout/thankyou.php for why (default was a bare bullet list
   + plain HTML table with no visual distinction from a browser default page,
   two identical billing/shipping address blocks since this checkout never
   collects a separate shipping address, and no COD reassurance or next step).
   ========================================================================== */

.thankyou-hero {
	text-align: center;
	padding: 32px 20px 24px;
}
.thankyou-hero-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 56px;
	margin-bottom: 16px;
	border-radius: 50%;
	background: var(--leaf-wash);
}
.thankyou-hero-icon::before {
	content: "";
	width: 28px;
	height: 28px;
	background-color: var(--leaf);
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 10.5l4.5 4.5L17 5' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 10.5l4.5 4.5L17 5' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.thankyou-hero-icon--failed { background: var(--crit-wash); }
.thankyou-hero-icon--failed::before {
	background-color: var(--crit);
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M6 6l8 8M14 6l-8 8' stroke='%23000' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M6 6l8 8M14 6l-8 8' stroke='%23000' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
}
.thankyou-hero-title {
	margin: 0 0 8px;
	font-size: 1.75rem;
}
.thankyou-hero-subtitle {
	margin: 0;
	color: var(--stone);
	font-size: var(--fs-base);
}

.thankyou-cod-note {
	max-width: 640px;
	margin: 0 auto 32px;
	padding: 14px 18px;
	background: var(--mist);
	border-inline-start: 3px solid var(--leaf);
	border-radius: var(--r-lg);
	font-size: var(--fs-base);
	color: var(--ink);
	text-align: center;
}

.thankyou-grid {
	display: grid;
	grid-template-columns: 1.6fr 1fr;
	gap: 28px;
	align-items: start;
	max-width: 900px;
	margin: 0 auto;
}
.thankyou-order-details h2 {
	font-size: 1.1rem;
	margin: 0 0 16px;
}
.thankyou-items {
	width: 100%;
	border-collapse: collapse;
	margin-bottom: 16px;
}
.thankyou-items tr + tr td { border-top: 1px solid var(--hairline); }
.thankyou-items td { padding: 12px 8px; vertical-align: middle; }
.thankyou-item-image { width: 52px; }
.thankyou-item-image img {
	width: 48px;
	height: 48px;
	object-fit: cover;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	display: block;
}
.thankyou-item-name { font-size: var(--fs-base); }
.thankyou-item-qty { color: var(--stone); font-size: var(--fs-sm); }
.thankyou-item-total {
	text-align: end;
	font-family: var(--mono);
	font-weight: 700;
	white-space: nowrap;
}

.thankyou-totals {
	border-top: 2px solid var(--hairline);
	padding-top: 12px;
}
.thankyou-totals-row {
	display: flex;
	justify-content: space-between;
	padding: 4px 8px;
	color: var(--stone);
	font-size: var(--fs-sm);
}
.thankyou-totals-row .amount,
.thankyou-totals-row > span:last-child { font-family: var(--mono); }
.thankyou-totals-row--total {
	margin-top: 4px;
	padding-top: 10px;
	border-top: 1px solid var(--hairline);
	color: var(--ink);
	font-weight: 700;
	font-size: 1.05rem;
}

.thankyou-sidebar { display: flex; flex-direction: column; gap: 16px; }
.thankyou-info-card {
	background: var(--mist);
	border-radius: var(--r-lg);
	padding: 16px 18px;
}
.thankyou-info-card h3 {
	margin: 0 0 8px;
	font-size: var(--fs-sm);
	text-transform: uppercase;
	letter-spacing: .02em;
	color: var(--stone);
}
.thankyou-info-card p {
	margin: 0;
	font-size: var(--fs-base);
	color: var(--ink);
	line-height: 1.6;
}

.thankyou-upsell {
	margin-top: 32px;
	padding-top: 28px;
	border-top: 1px solid var(--hairline);
	text-align: center;
}
.thankyou-upsell h2 { margin: 0 0 6px; }
.thankyou-upsell-note { margin: 0 0 20px; color: var(--stone); font-size: var(--fs-sm); }
.thankyou-upsell-list {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 16px;
	max-width: 560px;
	margin: 0 auto;
	text-align: start;
}
.thankyou-upsell-item {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 12px;
	background: var(--mist);
	border-radius: var(--r-lg);
	padding: 12px 14px;
}
.thankyou-upsell-image img {
	width: 52px; height: 52px;
	object-fit: cover;
	background: var(--paper);
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	flex-shrink: 0;
}
.thankyou-upsell-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.thankyou-upsell-name {
	font-size: var(--fs-sm);
	font-weight: 600;
	line-height: 1.3;
	/* Product names here run long ("NOW Foods, 5-HTP avec glycine, taurine
	   et inositol, 60 capsules végétariennes") — single-line ellipsis was
	   cutting them down to a few words. Two lines is enough room to read
	   the actual product, same clamp the shop-grid cards use for the same
	   problem. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.thankyou-upsell-price { font-family: var(--mono); font-size: var(--fs-xs); color: var(--stone); }
/* Every WC shortcode (including checkout, which the order-received page
   reuses) wraps its own output in a <div class="woocommerce">
   (WC_Shortcodes::shortcode_wrapper) — so .woocommerce a.button
   (specificity 0,0,2,1) was beating a plain .thankyou-upsell-add override
   (0,0,1,0), leaving this button at its full default size (128px wide,
   confirmed live) and squeezing the name column down to a couple of
   characters per line. .woocommerce .thankyou-upsell-item a.button
   (0,0,3,1) beats it outright rather than resting on source order. */
.woocommerce .thankyou-upsell-item a.button {
	/* flex-basis:100% inside the wrapping row above forces this onto its
	   own full-width line below the image+name+price row — the card is
	   only ~270px wide in the 2-column desktop grid, not enough for image
	   + name + button side by side without squeezing the name to a couple
	   of characters per line (confirmed live). */
	flex: 1 0 100%;
	padding: 8px 12px;
	font-size: var(--fs-xs);
	text-align: center;
}

@media (max-width: 480px) {
	.thankyou-upsell-list { grid-template-columns: 1fr; }
}

.thankyou-actions {
	text-align: center;
	margin: 32px auto 0;
}
.thankyou-actions .button { display: inline-flex; }
.thankyou-actions .button-outline { margin-inline-start: 10px; }

@media (max-width: 700px) {
	.thankyou-grid { grid-template-columns: 1fr; }
}

/* "Notify me when back in stock" — hand-rolled in herbelo_display_pressure_badge
   (herbelo-store-logic) instead of the instock-email-alert plugin's own
   [instock] shortcode (see that function's comment for why), submitting to
   the same plugin's existing save/email logic. Styled here from scratch —
   the plugin's own CSS is a generic full-width form with its own colors,
   nothing like the rest of this page. */
.notify-in-stock {
	margin: 14px 0 4px;
	padding: 14px;
	background: var(--mist);
	border-radius: var(--r-lg);
}
.notify-in-stock-text {
	margin: 0 0 10px;
	font-size: var(--fs-base);
	font-weight: 600;
	color: var(--ink);
}
.notify-in-stock-form {
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
}
.notify-in-stock-form input[type="email"] {
	flex: 1;
	min-width: 180px;
	padding: 10px 12px;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	font-size: var(--fs-base);
	background: var(--paper);
	color: var(--ink);
}
.notify-in-stock-form input[type="email"]:focus {
	outline: none;
	border-color: var(--leaf);
}
.notify-in-stock-form .button {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 10px 20px;
}
.notify-in-stock-form .button::before {
	content: "";
	width: 15px; height: 15px;
	flex-shrink: 0;
	background-color: currentColor;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5 8a5 5 0 0 1 10 0c0 3 1 4.5 1.5 5H3.5C4 12.5 5 11 5 8z' stroke='%23000' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M8 16a2 2 0 0 0 4 0' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5 8a5 5 0 0 1 10 0c0 3 1 4.5 1.5 5H3.5C4 12.5 5 11 5 8z' stroke='%23000' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M8 16a2 2 0 0 0 4 0' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
}
/* Success/error feedback the plugin prints below the form after a subscribe
   attempt (instock_email_alert_save_sent / _error) — its own default is a
   full-width green/red bordered box that doesn't match anything else here. */
.instock_message {
	margin: 10px 0 0;
	padding: 10px 14px;
	border: 0;
	border-inline-start: 3px solid var(--leaf);
	border-radius: var(--r);
	background: var(--leaf-wash);
	font-size: var(--fs-base);
	color: var(--ink);
	max-width: none;
}
.instock_message.error {
	border-inline-start-color: var(--crit);
	background: var(--crit-wash);
}

/* Delivery / payment / returns — printed as .woocommerce-message by the
   legacy plugin (bbloomer_display_pressure_badge), right under the buy
   button inside .summary. Hidden here, not removed — the notify-form and
   trust-badge list that same function prints stay exactly where they are;
   only these 3 messages move, re-rendered fresh as their own full-width
   band below the image+summary row (herbelo_delivery_info_band,
   inc/woocommerce.php) rather than crammed into the same narrow column. */
.woocommerce div.product .summary .woocommerce-message {
	display: none;
	position: relative;
	background: none;
	border: 0;
	border-top: 1px solid var(--hairline);
	border-radius: 0;
	margin: 0;
	padding-block: 12px;
	padding-inline: 30px 0;
	font-size: var(--fs-base);
	color: var(--stone);
}
.woocommerce div.product .summary .woocommerce-message:first-of-type {
	margin-top: 4px;
}
.woocommerce div.product .summary .woocommerce-message:last-of-type {
	border-bottom: 1px solid var(--hairline);
	margin-bottom: 18px;
}
.woocommerce div.product .summary .woocommerce-message strong {
	display: block;
	color: var(--ink);
	font-family: var(--sans);
	font-size: var(--fs-base);
	font-weight: 700;
	margin-bottom: 2px;
}
.woocommerce div.product .summary .woocommerce-message br { display: none; }
/* The redesigned notice badge (a tinted circle + checkmark, via ::before and
   ::after on .woocommerce-message globally) leaked onto these three blocks
   too, overlapping their own truck/cash/return ::before icon below — this
   specifically removes just that leaked checkmark layer, leaving the
   original per-message icon as the only one. */
.woocommerce div.product .summary .woocommerce-message::after { content: none; }

/* One icon per message, in their fixed output order (Livraison, Paiement,
   Retour — hardcoded in that sequence by herbelo-store-logic). Drawn as
   inline SVG data URIs so no icon font or image request is needed; stroke
   color/weight matches the header's icon buttons. */
.woocommerce div.product .summary .woocommerce-message::before {
	content: "";
	position: absolute;
	inset-inline-start: 0; top: 14px;
	width: 20px; height: 20px;
	background-color: transparent;
	border-radius: 0;
	background-repeat: no-repeat;
	background-position: center;
	background-size: 18px;
}
/* :nth-of-type counts by raw tag name among ALL sibling <div>s, not by
   class — since other divs precede these three in the summary (add-to-cart
   wrapper, trust list, ...), nth-of-type(1/2/3) never matched any of them.
   Adjacent-sibling combinators target by position *relative to same-class
   siblings* instead, which is what's actually needed here: default to the
   1st icon, then override on any message preceded by one/two others. */
.woocommerce div.product .summary .woocommerce-message::before {
	/* delivery truck — default, applies to the first message */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2355642b' stroke-width='1.7'%3E%3Cpath d='M2.5 7h11v10h-11z' stroke-linejoin='round'/%3E%3Cpath d='M13.5 10.5h5l3 3v3.5h-8z' stroke-linejoin='round'/%3E%3Ccircle cx='6.5' cy='18.5' r='1.8'/%3E%3Ccircle cx='17' cy='18.5' r='1.8'/%3E%3C/svg%3E");
}
.woocommerce div.product .summary .woocommerce-message + .woocommerce-message::before {
	/* cash on delivery — any message with one .woocommerce-message before it */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2355642b' stroke-width='1.7'%3E%3Crect x='2.5' y='6' width='19' height='12' rx='2'/%3E%3Cpath d='M2.5 10h19'/%3E%3C/svg%3E");
}
.woocommerce div.product .summary .woocommerce-message + .woocommerce-message + .woocommerce-message::before {
	/* returns — the message with two .woocommerce-message in a row before it */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2355642b' stroke-width='1.7'%3E%3Cpath d='M3.5 12a8.5 8.5 0 1 0 2.6-6.1' stroke-linecap='round'/%3E%3Cpath d='M3 4v5h5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* Delivery/payment/returns info (herbelo_delivery_info_band,
   inc/woocommerce.php) — icon + title + text per item (shipping/payment/
   returns). Above 1024px, .woocommerce div.product is a 3-column grid
   (image | buy box | this) so it sits as a 3rd column in the SAME row as
   the gallery and summary — stacked vertically there since it's a narrow
   sidebar (see the min-width: 1025px override below). Below 1024px
   div.product collapses to a single column and this becomes a full-width
   band instead, laid out 3-across down to 640px and stacked below that. */
.product-delivery-info {
	display: flex;
	flex-wrap: nowrap;
	gap: 14px;
	max-width: var(--shell);
	margin: 28px auto 0;
	padding: 22px 20px;
	border-top: 1px solid var(--hairline);
	border-bottom: 1px solid var(--hairline);
}
@media (min-width: 1025px) {
	.product-delivery-info {
		flex-direction: column;
		gap: 20px;
		max-width: none;
		margin: 0;
		padding: 4px 0 0;
		border-top: 0;
		border-bottom: 0;
	}
}
.product-delivery-info-item {
	flex: 1 1 0;
	min-width: 0;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 6px;
}
.product-delivery-info-head {
	display: flex;
	align-items: center;
	gap: 8px;
}
.product-delivery-info-icon {
	width: 26px; height: 26px;
	flex-shrink: 0;
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
}
.product-delivery-info-icon--shipping {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2355642b' stroke-width='1.7'%3E%3Cpath d='M2.5 7h11v10h-11z' stroke-linejoin='round'/%3E%3Cpath d='M13.5 10.5h5l3 3v3.5h-8z' stroke-linejoin='round'/%3E%3Ccircle cx='6.5' cy='18.5' r='1.8'/%3E%3Ccircle cx='17' cy='18.5' r='1.8'/%3E%3C/svg%3E");
}
.product-delivery-info-icon--payment {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2355642b' stroke-width='1.7'%3E%3Crect x='2.5' y='6' width='19' height='12' rx='2'/%3E%3Cpath d='M2.5 10h19'/%3E%3C/svg%3E");
}
.product-delivery-info-icon--returns {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2355642b' stroke-width='1.7'%3E%3Cpath d='M3.5 12a8.5 8.5 0 1 0 2.6-6.1' stroke-linecap='round'/%3E%3Cpath d='M3 4v5h5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.product-delivery-info-item strong {
	font-size: .6875rem;
	color: var(--ink);
	font-weight: 700;
}
.product-delivery-info-item span:last-child {
	font-size: var(--fs-xs);
	color: var(--stone);
	line-height: 1.5;
}
@media (max-width: 640px) {
	.product-delivery-info { flex-direction: column; gap: 16px; padding: 18px 14px; }
	.product-delivery-info-icon { width: 20px; height: 20px; }
	.product-delivery-info-item strong { font-size: .625rem; }
	.product-delivery-info-item span:last-child { font-size: var(--fs-2xs); line-height: 1.4; }
}

/* Satisfaction/shipping/tracking list — the legacy plugin sets an inline
   `display: inline-table` on this div. inline-table shrink-wraps to its
   content width (like inline-block), which is what actually put it out of
   layout: it rendered narrower than the full-width blocks above and below
   it. Forcing width explicitly rather than trusting the display override
   alone, since inline styles win ties and this needs to be bulletproof. */
.woocommerce div.product .product-widget {
	display: block !important;
	width: 100% !important;
	max-width: 100% !important;
	box-sizing: border-box !important;
	margin: 0 0 16px;
}
.woocommerce div.product .product-widget ul {
	display: grid;
	gap: 6px;
	width: 100%;
}
.woocommerce div.product .product-widget li {
	position: relative;
	padding-inline-start: 20px;
	font-size: var(--fs-base);
	color: var(--stone);
	list-style: none;
}
.woocommerce div.product .product-widget li::before {
	content: "";
	position: absolute;
	inset-inline-start: 2px; top: .54em;
	width: 8px; height: 4px;
	border: 1.8px solid var(--leaf);
	border-width: 0 0 1.8px 1.8px;
	transform: rotate(-45deg);
}

/* Product meta */
.woocommerce div.product .product_meta {
	margin-top: 18px;
	padding-top: 14px;
	border-top: 1px solid var(--hairline);
	font-family: var(--mono);
	font-size: var(--fs-xs);
	color: var(--stone);
}
.woocommerce div.product .product_meta a { color: var(--leaf); }

/* Description + reviews, side by side below the fold */
.product-description-reviews-row {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: 52px;
	align-items: start;
	margin-top: 44px;
}
.woocommerce-product-description {
	font-size: var(--fs-md);
}
.woocommerce-product-description h2,
.woocommerce-product-description h3 { font-size: 1.16rem; margin-top: 26px; }
.woocommerce-product-description img { border-radius: var(--r); }
/* Supplement-facts tables (~100 products have one baked into the
   description): the quantity ("50 µg (2000 UI)") and %DV ("250 %") columns
   are only 15% width each, so on narrow screens/RTL that whole phrase wraps
   across several tiny lines — and since the bidi algorithm re-resolves
   direction independently PER LINE, a parenthetical broken mid-phrase comes
   out with its parentheses visually scrambled/duplicated-looking. Confirmed
   live on the Arabic vitamin D3 page: "(2000 وحدة دولية)" wrapped across
   3 lines with both parens landing on the wrong lines. These two columns
   are always short (a measurement, a percentage) — never wrapping them
   keeps each one a single bidi run, which is what actually fixes the
   scrambling; the auto table layout then borrows the width they need from
   the (much longer, meant-to-wrap) name column in the excluded first cell.
   :not([colspan]) skips the header/section rows above, which use
   colspan="3" (a single, often-longer cell) rather than this 3-column
   per-nutrient layout. */
.woocommerce-product-description table td:nth-last-child(-n+2):not([colspan]) {
	white-space: nowrap;
}
/* 12 products' supplement-facts tables were imported with a legacy
   align="left" attribute on every <tr> (a presentational HTML hint, not
   CSS) — confirmed live via a DB search and a computed-style check
   (textAlign: -webkit-left on every cell) on the Ashwagandha product page.
   Physical "left" doesn't flip for direction the way logical start/end
   would, so on /ar/ every cell's Arabic text sits flush against the wrong
   edge instead of the right, where Arabic reads from. Scoped to
   [dir="rtl"] only — the same attribute is correct as-is for the French
   pages these tables were originally written for. */
[dir="rtl"] .woocommerce-product-description table td {
	text-align: right;
}
.woocommerce-product-reviews {
	padding-inline-start: 44px;
	border-inline-start: 1px solid var(--hairline);
}

@media (max-width: 900px) {
	.product-description-reviews-row { grid-template-columns: minmax(0, 1fr); gap: 36px; }
	.woocommerce-product-reviews {
		padding-inline-start: 0;
		padding-top: 32px;
		border-inline-start: 0;
		border-top: 1px solid var(--hairline);
	}
}

.woocommerce-tabs { margin-top: 40px; }
.woocommerce-tabs ul.tabs {
	display: flex;
	gap: 6px;
	border-bottom: 1px solid var(--hairline);
	margin-bottom: 22px;
	flex-wrap: wrap;
}
.woocommerce-tabs ul.tabs li {
	padding: 11px 16px;
	font-weight: 600;
	font-size: var(--fs-md);
	color: var(--stone);
	border-bottom: 2px solid transparent;
	cursor: pointer;
	list-style: none;
}
.woocommerce-tabs ul.tabs li.active,
.woocommerce-tabs ul.tabs li:hover {
	color: var(--leaf);
	border-bottom-color: var(--leaf);
}
.woocommerce-tabs .woocommerce-Tabs-panel { max-width: 78ch; }

.related.products,
.upsells.products { margin-top: 48px; }
.related.products > h2,
.upsells.products > h2 {
	font-size: 1.3rem;
	border-bottom: 1px solid var(--hairline);
	padding-bottom: 12px;
	margin-bottom: 22px;
}

/* Recently viewed — filled client-side (main.js: initRecentlyViewed) from
   localStorage, hidden by default until JS confirms there's something to
   show. Horizontal scroll-snap row, same interaction pattern as the
   bestseller/related sliders elsewhere on the site. */
.recently-viewed-products { margin-top: 48px; }
.recently-viewed-title {
	font-size: 1.3rem;
	border-bottom: 1px solid var(--hairline);
	padding-bottom: 12px;
	margin: 0 0 22px;
}
.recently-viewed-list {
	display: flex;
	gap: 16px;
	margin: 0;
	padding: 4px 4px 8px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-padding-inline-start: 4px;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
}
.recently-viewed-list::-webkit-scrollbar { display: none; }
.recently-viewed-card {
	flex: 0 0 140px;
	scroll-snap-align: start;
	display: flex;
	flex-direction: column;
	text-decoration: none;
	color: inherit;
}
.recently-viewed-card-image {
	width: 100%;
	aspect-ratio: 1;
	object-fit: contain;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	background: var(--paper);
	margin-bottom: 8px;
}
.recently-viewed-card-title {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	font-size: var(--fs-sm);
	color: var(--ink);
	margin-bottom: 4px;
}
.recently-viewed-card-price {
	font-size: var(--fs-sm);
	font-weight: 700;
	color: var(--leaf-deep);
}

/* Sticky add-to-cart */
.sticky-add-to-cart {
	position: fixed;
	inset-inline: 0; bottom: 0;
	background: rgba(255, 255, 255, .94);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	border-top: 1px solid var(--hairline);
	box-shadow: 0 -3px 18px rgba(16, 26, 19, .09);
	padding: 10px 16px;
	transform: translateY(100%);
	transition: transform var(--t-slow);
	z-index: var(--z-header);
}
.sticky-add-to-cart.is-visible { transform: translateY(0); }
.sticky-add-to-cart-inner {
	display: flex;
	align-items: center;
	gap: 14px;
	max-width: var(--shell);
	margin: 0 auto;
}
.sticky-add-to-cart-image {
	width: 42px; height: 42px;
	object-fit: contain;
	background: var(--mist);
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	flex-shrink: 0;
}
.sticky-add-to-cart-details { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.sticky-add-to-cart-title {
	font-weight: 600;
	font-size: var(--fs-base);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.sticky-add-to-cart-price {
	font-family: var(--mono);
	font-weight: 700;
	font-size: var(--fs-base);
	white-space: nowrap;
}
.sticky-add-to-cart-button { flex-shrink: 0; }

/* ==========================================================================
   Star ratings — WooCommerce's bundled icon font, re-declared because WC's
   own stylesheet is disabled.
   ========================================================================== */

@font-face {
	font-family: star;
	src: url("/wp-content/plugins/woocommerce/assets/fonts/star.woff") format("woff"),
		url("/wp-content/plugins/woocommerce/assets/fonts/star.ttf") format("truetype");
	font-weight: 400;
	font-style: normal;
	font-display: block;
}
.star-rating {
	overflow: hidden;
	position: relative;
	height: 1em;
	line-height: 1;
	width: 5.4em;
	font-family: star !important;
	font-weight: 400;
	flex-shrink: 0;
	/* .star-rating span below anchors itself with the LOGICAL
	   inset-inline-start (correctly flips to right:0 under RTL), but its
	   own ::before — the actual gold star glyphs — draws from the
	   PHYSICAL left:0, which never flips. Under RTL those two disagree:
	   the clip box anchors right while the glyphs still try to start from
	   the left, so they land misaligned against the grey background stars
	   — confirmed live via a screenshot (one mangled/doubled-looking star
	   at the edge). Stars are iconography, not language content, so they
	   don't need to visually reverse for RTL at all — forcing this whole
	   widget to always compute as LTR internally (direction is inherited,
	   so this cascades to ::before/span/span::before below too) makes
	   inset-inline-start resolve to left:0 everywhere, matching the
	   physical left:0 already hardcoded on span::before. Same fix pattern
	   used for the price/currency bidi bug earlier this session. */
	direction: ltr;
}
.star-rating::before {
	content: "\53\53\53\53\53";
	float: left;
	top: 0; inset-inline-start: 0;
	position: absolute;
	color: var(--hairline);
}
.star-rating span {
	overflow: hidden;
	float: left;
	top: 0; inset-inline-start: 0;
	position: absolute;
	padding-top: 1.5em;
	/* The universal font-family rule near the top of this file matches this
	   span directly (it's a real element, not inherited from .star-rating),
	   which otherwise overrides the icon font this element needs to draw
	   the filled/colored stars via ::before below. */
	font-family: star !important;
}
.star-rating span::before {
	content: "\53\53\53\53\53";
	top: 0; left: 0;
	position: absolute;
	color: var(--amber);
}

/* Variation dropdown (e.g. "Quantité dans l'emballage") — its option text
   (product attribute terms, e.g. "50 pièces") isn't run through the site's
   translation layer, so it's still French/Latin content even on /ar/ pages.
   With no bidi isolation, the RTL page direction reorders that text's word
   order in the rendered <select> box — confirmed live: "50 pièces" was
   displaying as "pièces 50". Same fix pattern as .woocommerce-Price-amount
   and .star-rating above: force the box to compute LTR internally so its
   own content reads correctly, independent of the page's overall direction;
   text-align stays right so the box doesn't look like a stray LTR island
   floating against the RTL layout around it. */
[dir="rtl"] .variations select {
	direction: ltr;
	text-align: right;
}

/* Variation attribute swatches (assets/js/main.js, initVariationSwatches)
   — replaces the raw <select> above with clickable pill buttons. The
   <select> stays in the DOM as the source of truth WooCommerce's own
   variation script reads/writes; only hidden here, not removed. */
.woocommerce div.product table.variations,
.woocommerce div.product table.variations tbody,
.woocommerce div.product table.variations tr {
	display: block;
}
.woocommerce div.product table.variations tr + tr { margin-top: 16px; }
.woocommerce div.product table.variations th.label {
	display: block;
	text-align: start;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--stone);
	padding: 0 0 8px;
}
.woocommerce div.product table.variations td.value {
	display: flex;
	align-items: center;
	gap: 14px;
	flex-wrap: wrap;
	padding: 0;
}
.variations select.variation-swatches-source {
	/* Visually hidden, not display:none — WooCommerce still reads/writes
	   .val() either way, but keeping it in normal flow (rather than
	   removed from layout) avoids any risk of a "display:none form field"
	   edge case in its own validation. */
	position: absolute;
	width: 1px; height: 1px;
	padding: 0; margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}
.variation-swatches {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}
.variation-swatch {
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	padding: 8px 16px;
	background: var(--paper);
	font-size: var(--fs-base);
	font-weight: 600;
	color: var(--ink);
	cursor: pointer;
	transition: border-color var(--t), background var(--t), color var(--t);
}
.variation-swatch:hover { border-color: var(--stone); }
.variation-swatch.is-selected {
	border-color: var(--leaf);
	background: var(--leaf-wash);
	color: var(--leaf-deep);
}
.variation-swatch.is-disabled {
	color: var(--stone);
	text-decoration: line-through;
	cursor: not-allowed;
	opacity: .55;
}
/* Same reasoning as [dir="rtl"] .variations select above: the swatch
   label text is untranslated French/Latin content ("60 pièce(s)"), so it
   needs to compute LTR internally even on an RTL page or its own word
   order scrambles. */
[dir="rtl"] .variation-swatch { direction: ltr; }
/* Same reasoning, same fix — the shop-grid quick-add swatches. */
[dir="rtl"] .loop-variation-swatch { direction: ltr; }

.woocommerce div.product .reset_variations {
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--stone);
	text-decoration: underline;
	text-underline-offset: 2px;
}
.woocommerce div.product .reset_variations:hover { color: var(--ink); }

/* ==========================================================================
   Pagination
   ========================================================================== */

.woocommerce-pagination,
.navigation.pagination { margin: 40px 0 8px; }
.woocommerce-pagination ul.page-numbers,
.navigation.pagination .nav-links {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 7px;
	border: 0;
	margin: 0;
	padding: 0;
}
.woocommerce-pagination ul.page-numbers li { border: 0; margin: 0; overflow: visible; }
.page-numbers {
	display: inline-flex;
	align-items: center; justify-content: center;
	min-width: 38px; height: 38px;
	padding: 0 11px;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	background: var(--paper);
	font-family: var(--mono);
	font-size: var(--fs-base);
	font-weight: 600;
	transition: border-color var(--t), color var(--t), background var(--t);
}
a.page-numbers:hover { border-color: var(--leaf); color: var(--leaf); }
.page-numbers.current {
	background: var(--leaf);
	border-color: var(--leaf);
	color: var(--paper);
}
.page-numbers.dots { border-color: transparent; background: transparent; min-width: 22px; padding: 0 3px; }

/* ==========================================================================
   Reviews
   ========================================================================== */

.woocommerce-Reviews-title,
#reviews h2 { font-size: 1.24rem; margin-bottom: 18px; }
#reviews ol.commentlist,
.woocommerce-product-reviews ol.commentlist {
	list-style: none;
	margin: 0 0 28px;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 14px;
}
#reviews ol.commentlist li { margin: 0; }
/* No grid here — the reviews column now shares a row with the description
   (see .product-description-reviews-row), so it's roughly half the width it
   used to have; a 44px avatar column made every review feel cramped. Padding
   alone gives the text room to breathe instead. */
#reviews .comment_container {
	background: var(--paper);
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	padding: 17px;
}
#reviews .comment_container img.avatar { display: none; }
#reviews .comment-text { min-width: 0; }
#reviews .woocommerce-review__author { font-weight: 700; margin-inline-end: 8px; }
#reviews .woocommerce-review__published-date {
	font-family: var(--mono);
	font-size: var(--fs-xs);
	color: var(--stone);
}
#reviews .woocommerce-review__verified {
	font-size: var(--fs-xs);
	font-weight: 700;
	letter-spacing: .04em;
	color: var(--leaf-deep);
}
#reviews .comment-text .star-rating { margin-bottom: 7px; }
#reviews .description p:last-child { margin-bottom: 0; }

#review_form_wrapper { border-top: 1px solid var(--hairline); padding-top: 24px; }
#review_form .comment-form { max-width: 640px; }
#review_form .comment-form label {
	display: block;
	font-weight: 600;
	font-size: var(--fs-base);
	margin-bottom: 6px;
}
#review_form .comment-form input[type="text"],
#review_form .comment-form input[type="email"],
#review_form .comment-form textarea { width: 100%; }
#review_form .comment-form-rating .stars { margin-bottom: 12px; }

/* ==========================================================================
   Cart
   ========================================================================== */

.woocommerce-cart .site-main,
.woocommerce-checkout .site-main,
.woocommerce-account .site-main { padding-top: 28px; padding-bottom: 60px; }

/* Cart/Checkout/Account are shortcodes on regular Pages, so they render
   through page.php's narrow .entry-content — widen those here. */
.woocommerce-cart .entry-content,
.woocommerce-checkout .entry-content,
.woocommerce-account .entry-content,
.woocommerce-cart .entry-header,
.woocommerce-checkout .entry-header,
.woocommerce-account .entry-header { max-width: var(--shell); }

.woocommerce table.shop_table {
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	border-spacing: 0;
	overflow: hidden;
}
.woocommerce table.shop_table th {
	background: var(--mist);
	text-align: start;
	padding: 12px 15px;
	font-size: var(--fs-xs);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .1em;
	color: var(--stone);
	border-bottom: 1px solid var(--hairline);
}
.woocommerce table.shop_table td {
	padding: 15px;
	border-top: 1px solid var(--hairline);
	vertical-align: middle;
	font-size: var(--fs-md);
}
.woocommerce table.shop_table td.product-thumbnail img {
	width: 64px;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	background: var(--mist);
}
/* text-decoration:none: this is a link (class="remove"), not a .button, so
   it wasn't covered by the .button fix above — same ".entry-content a"
   underline problem, just on the × remove-item icon instead. */
.woocommerce table.shop_table td.product-remove a { color: var(--stone); font-size: 1.15rem; text-decoration: none; }
.woocommerce table.shop_table td.product-remove a:hover { color: var(--crit); }
.woocommerce table.shop_table .amount { font-family: var(--mono); }

/* Free-shipping progress bar (herbelo_free_shipping_progress_bar) — sits
   above the cart items table. */
.free-shipping-progress {
	margin: 0 0 18px;
	padding: 14px 16px;
	background: var(--mist);
	border-radius: var(--r-lg);
}
.free-shipping-progress-text {
	margin: 0 0 10px;
	font-size: var(--fs-base);
	color: var(--ink);
}
.free-shipping-progress-text strong,
.free-shipping-progress-text .woocommerce-Price-amount {
	color: var(--leaf-deep);
	font-weight: 700;
}
.free-shipping-progress-text--done {
	margin-bottom: 0;
	color: var(--leaf-deep);
	font-weight: 700;
}
.free-shipping-progress-bar {
	height: 8px;
	border-radius: 999px;
	background: var(--mist-deep);
	overflow: hidden;
}
.free-shipping-progress-fill {
	height: 100%;
	border-radius: 999px;
	background: var(--leaf);
	transition: width var(--t);
}

/* Cart items — modern card rows instead of a classic data table. Same
   underlying <table>/<tr>/<td> markup (WooCommerce needs the exact
   cart[key][qty] field names to process quantity updates and removals),
   just re-laid-out with CSS grid so none of that functionality changes. */
.woocommerce-cart table.cart {
	border: 0;
	border-radius: 0;
	overflow: visible;
}
.woocommerce-cart table.cart thead {
	position: absolute;
	width: 1px; height: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
}
.woocommerce-cart table.cart tbody { display: block; }
.woocommerce-cart table.cart tr.cart_item {
	display: grid;
	grid-template-columns: 84px minmax(0, 1fr) auto;
	grid-template-areas:
		"thumb name   remove"
		"thumb price  remove"
		"thumb qty    subtotal";
	column-gap: 18px;
	row-gap: 6px;
	align-items: center;
	padding: 16px;
	border: 1px solid var(--hairline);
	border-radius: var(--r-lg);
	margin-bottom: 12px;
	background: var(--paper);
}
.woocommerce-cart table.cart tr.cart_item td {
	padding: 0;
	border-top: 0;
	font-size: var(--fs-md);
}
.woocommerce-cart table.cart td.product-thumbnail { grid-area: thumb; }
.woocommerce-cart table.cart td.product-thumbnail img {
	width: 84px; height: 84px;
	object-fit: contain;
	padding: 6px;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	background: var(--paper);
}
.woocommerce-cart table.cart td.product-name { grid-area: name; font-weight: 600; }
.woocommerce-cart table.cart td.product-name a { color: var(--ink); }
.woocommerce-cart table.cart td.product-name a:hover { color: var(--leaf); }
.woocommerce-cart table.cart td.product-price {
	grid-area: price;
	color: var(--stone);
	font-size: var(--fs-sm);
}
.woocommerce-cart table.cart td.product-quantity { grid-area: qty; }
.woocommerce-cart table.cart td.product-subtotal {
	grid-area: subtotal;
	font-weight: 700;
	justify-self: end;
	align-self: end;
}
.woocommerce-cart table.cart td.product-remove {
	grid-area: remove;
	justify-self: end;
	align-self: start;
}
.woocommerce-cart table.cart td.product-remove a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px; height: 28px;
	border-radius: 50%;
	background: var(--mist);
	font-size: 1.1rem;
	line-height: 1;
}
.woocommerce-cart table.cart td.product-remove a:hover { background: var(--crit-wash); }
.woocommerce-cart table.cart tr:not(.cart_item) td.actions {
	border: 0;
	padding: 16px 0 0;
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	align-items: center;
	justify-content: space-between;
}
/* Coupon input + "Apply" button, side by side — WooCommerce's cart.php
   template (unlike the theme's own hand-rolled checkout coupon form) ships
   with no inline layout at all, so this was falling back to the sitewide
   input.input-text{width:100%} rule (meant for full-width form fields like
   billing/shipping) and stacking input, apply button, and the separate
   "update cart" button as three full-width blocks. */
.woocommerce-cart .coupon {
	display: flex;
	gap: 8px;
	flex: 1 1 auto;
	max-width: 380px;
	min-width: 220px;
}
.woocommerce-cart .coupon input.input-text {
	width: auto;
	flex: 1;
	min-width: 0;
	padding: 10px 12px;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	font-size: var(--fs-base);
}
.woocommerce-cart .coupon input.input-text:focus {
	outline: none;
	border-color: var(--leaf);
}
.woocommerce-cart .coupon .button { flex-shrink: 0; }
/* "Mettre à jour le panier" — the coupon's own submit already reads as the
   primary action on this row; matches the outline treatment used for
   secondary actions elsewhere (e.g. the mini-cart's "view cart" link). */
.woocommerce-cart table.cart tr:not(.cart_item) td.actions [name="update_cart"] {
	flex-shrink: 0;
	background: none;
	color: var(--leaf);
	border: 1px solid var(--leaf);
}
.woocommerce-cart table.cart tr:not(.cart_item) td.actions [name="update_cart"]:hover {
	background: var(--leaf);
	color: var(--paper);
}

.woocommerce-cart-form { margin-bottom: 24px; }
.woocommerce-cart .cart-collaterals { max-width: 400px; margin-inline-start: auto; }
.woocommerce-cart .cart_totals {
	background: var(--mist);
	border: 2px solid var(--hairline);
	border-radius: var(--r-lg);
	box-shadow: var(--shadow);
	padding: 20px;
}
.woocommerce-cart .cart_totals h2 { margin-top: 0; font-size: 1.05rem; }
/* table-layout:fixed, not auto (the default): with auto layout, a table
   grows to fit whatever cell needs the most room — here, the shipping row's
   label+price — rather than respecting the width it's actually been given,
   so it kept pushing itself wider than its .cart_totals card no matter how
   much that row's own content was made to shrink/wrap. Fixed layout makes
   the *table's* width the hard constraint instead: the first row sets each
   column's share (see the explicit th width below), and every other row's
   content is forced to fit inside that, wrapping if it must, rather than
   expanding the table to avoid wrapping. */
.woocommerce-cart .cart_totals table { margin-bottom: 14px; table-layout: fixed; width: 100%; }
.woocommerce-cart .cart_totals table th { width: 92px; }
.woocommerce-cart .cart_totals table th,
.woocommerce-cart .cart_totals table td {
	padding: 10px 0;
	border-top: 1px solid var(--hairline);
	font-size: var(--fs-md);
	text-align: end;
}
.woocommerce-cart .cart_totals table th,
.woocommerce-cart .cart_totals table td[colspan] { text-align: start; }
.woocommerce-cart .cart_totals tr.order-total th {
	font-size: 1.2rem;
	font-weight: 700;
}
.woocommerce-cart .cart_totals .order-total .amount {
	font-family: var(--mono);
	font-weight: 700;
	font-size: 1.5rem;
}
.woocommerce-cart .cart_totals tr.woocommerce-shipping-totals th { vertical-align: top; }
.woocommerce-cart .woocommerce-shipping-destination {
	margin: 10px 0 0;
	font-size: var(--fs-sm);
	color: var(--stone);
}
.woocommerce-cart .shipping-calculator-button {
	display: inline-block;
	margin-top: 6px;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--leaf);
}
.woocommerce-cart .shipping-calculator-form { margin-top: 14px; }
.woocommerce-cart .wc-proceed-to-checkout a { width: 100%; display: block; }
.cross-sells { margin-top: 48px; }
.cross-sells > h2 {
	font-size: 1.2rem;
	border-bottom: 1px solid var(--hairline);
	padding-bottom: 12px;
	margin-bottom: 20px;
}

/* ==========================================================================
   Checkout
   ========================================================================== */

.woocommerce-checkout form.checkout {
	display: grid;
	grid-template-columns: 1.35fr minmax(0, 1fr);
	column-gap: 44px;
	row-gap: 16px;
	align-items: start;
}
.woocommerce-checkout #customer_details { display: contents; }
/* Everything defaults left; only the summary moves right. */
.woocommerce-checkout form.checkout > *,
.woocommerce-checkout #customer_details > * {
	grid-column: 1;
	min-width: 0;
}
/* .col-1 (billing fields) and .col-2 (shipping toggle + order notes) were
   both left to auto-place their grid row, landing in row 1 and row 2
   respectively — same rows the sticky order-summary column occupies (row 1
   only, see #order_review below). Since a CSS grid row's height is set by
   the TALLEST item sharing it, and the summary box is taller than .col-1's
   billing fields alone, row 1 stretched to match the summary's height,
   leaving a large dead gap between .col-1 (ending partway through that
   inflated row) and .col-2 starting at row 2. Made explicit here so the
   fix below (spanning the summary across both rows) has a fixed target,
   rather than relying on auto-placement order. */
.woocommerce-checkout .col-1 { grid-row: 1; }
.woocommerce-checkout .col-2 { grid-row: 2; }
.woocommerce-checkout .col-1,
.woocommerce-checkout .col-2 { width: auto; float: none; }
/* Wrapper of hidden inputs — would otherwise take an empty grid row */
.woocommerce-checkout form.checkout > wc-order-attribution-inputs { display: none; }
.woocommerce-checkout #order_review_heading {
	grid-column: 2;
	grid-row: 1;
	align-self: start;
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0 0 2px;
	font-size: 1.12rem;
}
.woocommerce-checkout #order_review_heading::before {
	content: "";
	width: 18px; height: 18px;
	flex-shrink: 0;
	background-color: var(--leaf);
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M2 5h2l1.5 9.5a2 2 0 002 1.5h6a2 2 0 002-1.5L17 7H5.4' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='8' cy='18' r='1.2' fill='%23000'/%3E%3Ccircle cx='15' cy='18' r='1.2' fill='%23000'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M2 5h2l1.5 9.5a2 2 0 002 1.5h6a2 2 0 002-1.5L17 7H5.4' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='8' cy='18' r='1.2' fill='%23000'/%3E%3Ccircle cx='15' cy='18' r='1.2' fill='%23000'/%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}
.woocommerce-checkout #order_review {
	grid-column: 2;
	/* Was "2 / -1". With no grid-template-rows ever declared on the
	   container, the explicit grid has zero row tracks, so a negative line
	   like -1 resolves against THAT (empty) explicit grid, not against the
	   rows auto-created for content — it collapsed to line 1, put this and
	   #order_review_heading (also grid-row: 1) in the same cell, and this
	   div (later in DOM, so painted on top, with an opaque background)
	   covered the heading completely.
	   Fix was grid-row: 1 — same row as .col-1 and the heading, so this box
	   starts level with "Informations de livraison" instead of dropping to
	   a second row miles below it, plus a margin-top sized to clear the
	   heading it shares a cell with, so the two don't overlap.
	   That alone, though, left this (tall — cart items, totals, payment
	   method) box as the ONLY thing determining row 1's height, since a
	   grid row's height matches its tallest occupant: row 1 stretched to
	   fit this box, leaving a large empty gap below .col-1 (billing
	   fields, shorter than this box) before .col-2 (shipping toggle +
	   order notes, row 2) — confirmed live: ~108px of dead space between
	   the email field and the order notes textarea. Spanning rows 1-3
	   (i.e. rows 1 and 2, the only two rows this layout has) distributes
	   this box's height demand across .col-1 + .col-2's COMBINED height
	   instead of concentrating it in row 1 alone — same starting position
	   (this is still the first thing in its grid area, so sticky/margin
	   math is unchanged), just no longer forcing row 1 alone to match it. */
	grid-row: 1 / 3;
	margin-top: 40px;
	align-self: start;
	background: var(--mist);
	border: 2px solid var(--hairline);
	border-radius: var(--r-lg);
	box-shadow: var(--shadow);
	padding: 15px;
	position: sticky;
	top: 96px;
}
.woocommerce-checkout h3 {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: 1.12rem;
	margin-bottom: 18px;
}
.woocommerce-checkout #customer_details h3::before {
	content: "";
	width: 26px; height: 26px;
	flex-shrink: 0;
	border-radius: 50%;
	background: var(--leaf-wash);
	color: var(--leaf-deep);
}
.woocommerce-checkout #customer_details .col-1 h3::before { content: "1"; display: grid; place-items: center; font-family: var(--mono); font-size: var(--fs-xs); font-weight: 700; }
.woocommerce-checkout #customer_details .col-2 h3::before { content: "2"; display: grid; place-items: center; font-family: var(--mono); font-size: var(--fs-xs); font-weight: 700; }
/* Country field: this store only ships within Algeria and the country
   <select> only ever has that one option (selected by default), so hiding
   it changes nothing about what gets submitted — DZ still goes through.
   Street address: herbelo-store-logic (see set_default_address_values() /
   quadlayers_remove_checkout_fields() in core-woocommerce.php) already
   auto-fills #billing_address_1 with "." on page load specifically so this
   field can be skipped without failing the "required" check, rather than
   unsetting it outright — hiding it here relies on that same JS default.
   Ship-to-different-address: no reason to collect a separate shipping
   address on a wilaya/COD checkout where shipping is priced by wilaya, not
   by street — hiding it just leaves shipping = billing address, unchanged
   from what happens today whenever a shopper leaves that checkbox alone.
   !important on the first two: WooCommerce's own checkout.js sets an
   inline style="display: block" on address-field-class fields as part of
   its country-change field visibility logic, and an inline style beats any
   external stylesheet rule (regardless of selector specificity) unless
   that rule is !important — confirmed live, plain display:none here was
   silently losing to it. */
.woocommerce-checkout #billing_country_field,
.woocommerce-checkout #billing_address_1_field { display: none !important; }
.woocommerce-checkout #ship-to-different-address { display: none; }
.woocommerce-checkout .form-row { margin-bottom: 12px; }
.woocommerce-checkout .form-row label {
	display: block;
	font-size: var(--fs-sm);
	font-weight: 600;
	margin-bottom: 6px;
}
/* Scoped to form.checkout, not just the .woocommerce-checkout body class —
   that class sits on <body>, so a bare ".woocommerce-checkout input" matches
   *any* input anywhere on the page, including the unrelated header search
   box (which sits higher in specificity than .header-search-bar-input's own
   single-class rule, so it was winning and overriding it). form.checkout is
   the actual checkout form element and can't exist outside it. */
.woocommerce-checkout form.checkout input:not([type="radio"]):not([type="checkbox"]),
.woocommerce-checkout form.checkout select,
.woocommerce-checkout form.checkout textarea { width: 100%; padding: 11px 13px; }

/* Région (state) and Ville (city) aren't plain <select> elements — the
   states-cities-and-places plugin enhances both with Select2, which hides
   the real <select> and renders its own span/div in its place. That markup
   never gets the padding rule just above, so it was rendering at Select2's
   library-default 28px tall next to 43px-tall text inputs. Matching height
   here (rather than un-Select2-ing the field) keeps the searchable dropdown
   behaviour intact. */
.select2-container--default .select2-selection--single {
	height: 43px;
	border: 1px solid var(--stone);
	border-radius: var(--r);
	background: var(--paper);
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
	line-height: 41px;
	padding-inline-start: 13px;
	padding-inline-end: 32px;
	font-size: 1rem;
	color: var(--ink);
}
.select2-container--default .select2-selection--single .select2-selection__placeholder { color: var(--stone); }
.select2-container--default .select2-selection--single .select2-selection__arrow {
	height: 41px;
	inset-inline-end: 8px;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--single {
	border-color: var(--leaf);
}
.woocommerce-checkout table.shop_table { border: 0; border-radius: 0; }
.woocommerce-checkout table.shop_table th,
.woocommerce-checkout table.shop_table td {
	padding: 7px 0;
	background: transparent;
	font-size: var(--fs-md);
}
.woocommerce-checkout table.shop_table .order-total .amount {
	font-family: var(--mono);
	font-weight: 700;
	font-size: 1.5rem;
	white-space: nowrap;
}
.woocommerce-checkout table.shop_table .order-total th,
.woocommerce-checkout table.shop_table .order-total td { width: 1%; white-space: nowrap; }

/* Order review: line items get the same product-thumbnail treatment as the
   cart page (see herbelo_cart_item_name filter in inc/woocommerce.php) —
   thead is visually hidden the same way the cart table's is, since giving
   tbody rows their own grid/flex layout takes them out of the table's normal
   column-sizing, so a visible thead would no longer line up with them. */
.woocommerce-checkout-review-order-table thead {
	position: absolute;
	width: 1px; height: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
}
.woocommerce-checkout-review-order-table tbody tr.cart_item {
	border-bottom: 1px solid var(--hairline);
}
.woocommerce-checkout-review-order-table tbody tr.cart_item:first-child td { padding-top: 0; }
.woocommerce-checkout-review-order-table tbody tr:first-child td {
	border-top: 0;
}
.woocommerce-checkout-review-order-table td.product-name {
	display: flex;
	align-items: center;
	/* wrap, not nowrap: a variable product's chosen attribute
	   (dl.variation, printed by wc_get_formatted_cart_item_data() straight
	   after .checkout-item-thumb-name below) needs to drop onto its own
	   line under the thumbnail+name rather than compete with them for the
	   same row — flex-basis: 100% on it, further down, is what actually
	   forces that line break, this just has to allow wrapping in the
	   first place. .checkout-item-thumb-name itself still won't wrap
	   internally (nowrap on that group specifically), so a long title
	   still starts on the same line as the thumbnail either way. */
	flex-wrap: wrap;
	gap: 6px 10px;
}
.checkout-item-thumb-name {
	display: flex;
	align-items: center;
	flex-wrap: nowrap;
	flex: 1 1 auto;
	min-width: 0;
	gap: 10px;
}
.checkout-item-thumb {
	width: 40px; height: 40px;
	object-fit: contain;
	background: var(--paper);
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	padding: 2px;
	flex-shrink: 0;
}
.checkout-item-name-text { flex: 1 1 auto; min-width: 0; font-size: var(--fs-sm); line-height: 1.35; }
/* Quantity now renders inline inside .checkout-item-name-text itself (see
   the woocommerce_cart_item_name filter in inc/woocommerce.php) so it wraps
   as part of the same text flow as the title, on the same line, no matter
   how long the title is. The template still prints its own separate
   ".product-quantity" badge straight after — hidden here so it isn't shown
   twice. */
.woocommerce-checkout-review-order-table .product-quantity { display: none; }
.checkout-item-qty-inline { color: var(--stone); font-weight: 600; white-space: nowrap; }
/* Variable product's chosen attribute (e.g. "Quantité dans l'emballage: 30
   pièces") — WooCommerce core prints this dl entirely unstyled, as a third
   sibling after .checkout-item-thumb-name in td.product-name. flex-basis:
   100% + order forces it onto its own row below the thumbnail+name instead
   of squeezed onto the same one; padding-inline-start (a logical property,
   so it's the right edge in RTL and the left edge in LTR automatically)
   lines it up under the name text rather than the thumbnail — no separate
   RTL override needed. */
.woocommerce-checkout-review-order-table td.product-name dl.variation {
	order: 2;
	flex: 1 1 100%;
	margin: 2px 0 0;
	padding-inline-start: 50px;
	font-size: var(--fs-xs);
	color: var(--stone);
	line-height: 1.4;
}
.woocommerce-checkout-review-order-table td.product-name dl.variation dt,
.woocommerce-checkout-review-order-table td.product-name dl.variation dd,
.woocommerce-checkout-review-order-table td.product-name dl.variation p {
	display: inline;
	margin: 0;
	font-weight: 400;
}
.woocommerce-checkout-review-order-table td.product-name dl.variation dd {
	margin-inline-end: 8px;
}
.woocommerce-checkout-review-order-table td.product-total {
	font-family: var(--mono);
	font-size: var(--fs-sm);
	white-space: nowrap;
	text-align: end;
}
.woocommerce-checkout-review-order-table tfoot th,
.woocommerce-checkout-review-order-table tfoot td { font-weight: 500; }
/* Every price cell (subtotal, discounts, total — anything that's just a
   plain <td> in tfoot, not the shipping row's colspan card) reads as a
   ledger column, so the amounts should line up on the right, not sit
   flush against the label like ordinary body text. */
.woocommerce-checkout-review-order-table tfoot td:not([colspan]) { text-align: end; }
.woocommerce-checkout-review-order-table tfoot tr.order-total th,
.woocommerce-checkout-review-order-table tfoot tr.order-total td {
	border-top: 0;
	padding-top: 14px;
}
.woocommerce-checkout-review-order-table tfoot tr.order-total th { font-size: 1.2rem; font-weight: 700; }
/* Shared with the cart page (below): #shipping_method is the same id/markup
   WooCommerce renders in both places, but the cart page's copy was never
   styled — it was still the browser's bare bulleted <ul><li>, the one part
   of the cart totals box that didn't match the rest of the site. Only the
   name/price span split (further below) stays checkout-only, since that's
   built by a PHP filter gated on is_checkout() — the cart page's label is
   still one plain string ("Livraison a domicile: 900 DA"), which reads
   fine as-is inside this same box/row styling. */
.woocommerce-checkout ul#shipping_method,
.woocommerce-cart ul#shipping_method {
	display: grid;
	padding-inline-start: 0;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	overflow: hidden;
	margin-bottom: 4px;
}
.woocommerce-checkout ul#shipping_method li,
.woocommerce-cart ul#shipping_method li {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: var(--fs-md);
	padding: 11px 12px;
	background: var(--paper);
	border-bottom: 1px solid var(--hairline);
}
.woocommerce-checkout ul#shipping_method li:last-child,
.woocommerce-cart ul#shipping_method li:last-child { border-bottom: 0; }
.woocommerce-checkout ul#shipping_method label,
.woocommerce-cart ul#shipping_method label {
	display: flex;
	flex-direction: row;
	align-items: baseline;
	gap: 8px;
	flex: 1 1 auto;
	min-width: 0;
	/* Overrides the mobile-only ".shop_table:not(.cart) td { white-space:
	   nowrap }" rule further below — .cart_totals's own table matches that
	   selector (it's a plain shop_table, not the .cart items table), and its
	   nowrap was inherited down into this label. On the cart page the label
	   is one unsplit string ("Livraison a domicile: 900 DA" — no name/price
	   span split there, see the split filter's is_checkout() guard), so
	   forcing it not to wrap was forcing a wide min-content width that
	   pushed the whole (auto-layout) table wider than its container,
	   pushing the subtotal/total amounts off-screen entirely. This has an id
	   in it (#shipping_method) specifically so it outranks that rule despite
	   coming first in the file. */
	white-space: normal;
}
.shipping-method-name { font-weight: 600; font-size: var(--fs-md); }
.shipping-method-price { font-family: var(--mono); font-size: var(--fs-sm); color: var(--stone); white-space: nowrap; }
/* The shipping row is now a genuine single full-width cell (colspan="2" —
   see the woocommerce_review_order_after_shipping hook in
   inc/woocommerce.php), not a th/td pair sharing column width with the
   Subtotal/Total rows' plain price cells. No display-type overrides needed:
   a colspan cell just *is* full width, in any browser. */
.woocommerce-checkout tr.woocommerce-shipping-totals td[colspan],
.woocommerce-cart tr.woocommerce-shipping-totals td[colspan] {
	padding: 12px 0;
}
.shipping-totals-label {
	display: block;
	margin-bottom: 8px;
	font-size: var(--fs-xs);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--stone);
}
/* Before a wilaya is picked, #shipping_method doesn't exist yet and this is
   just the placeholder sentence WooCommerce prints instead — framed as an
   inline notice rather than left as plain text. */
.woocommerce-checkout tr.woocommerce-shipping-totals td[colspan]:not(:has(#shipping_method)),
.woocommerce-cart tr.woocommerce-shipping-totals td[colspan]:not(:has(#shipping_method)) {
	background: var(--leaf-wash);
	border-radius: var(--r);
	padding: 12px 14px;
	color: var(--leaf-deep);
	font-size: var(--fs-sm);
	font-weight: 600;
}
.woocommerce-checkout .payment_methods {
	display: grid;
	gap: 10px;
	margin-bottom: 16px;
	padding: 0;
}
.woocommerce-checkout .payment_methods li {
	list-style: none;
	font-size: var(--fs-md);
	border: 0;
	border-radius: var(--r);
	padding: 12px 14px;
	background: none;
}
.woocommerce-checkout .payment_methods li:hover { border-color: transparent; }
.woocommerce-checkout .payment_methods li:has(input:checked) {
	border-color: transparent;
	background: none;
	box-shadow: none;
}
.woocommerce-checkout .payment_methods input[type="radio"] { margin-inline-end: 4px; }
.woocommerce-checkout .payment_methods label {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-weight: 700;
}
.woocommerce-checkout .payment_methods label::before {
	content: "";
	width: 20px; height: 20px;
	flex-shrink: 0;
	background-color: var(--leaf);
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Crect x='2' y='6' width='20' height='13' rx='2' stroke='%23000' stroke-width='1.8'/%3E%3Ccircle cx='12' cy='12.5' r='3' stroke='%23000' stroke-width='1.8'/%3E%3Cpath d='M6 6V5a2 2 0 0 1 2-2h9' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Crect x='2' y='6' width='20' height='13' rx='2' stroke='%23000' stroke-width='1.8'/%3E%3Ccircle cx='12' cy='12.5' r='3' stroke='%23000' stroke-width='1.8'/%3E%3Cpath d='M6 6V5a2 2 0 0 1 2-2h9' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}
.woocommerce-checkout .payment_box {
	margin-top: 8px;
	padding-top: 8px;
	border-top: 0;
	font-size: var(--fs-sm);
	color: var(--stone);
}
.woocommerce-checkout .payment_box p { margin: 0; }
.woocommerce-checkout #place_order {
	width: 100%;
	margin-top: 18px;
	padding: 17px 24px;
	font-size: 1.05rem;
	box-shadow: var(--shadow);
}
.woocommerce-checkout .woocommerce-form-coupon-toggle,
.woocommerce-form-coupon { margin-bottom: 14px; }

/* Desktop: #order_review is already visible the whole time in its sticky
   sidebar, so this mobile-only summary would just be a redundant second
   total sitting above the form — see the 1024px breakpoint for where it
   actually turns on, and herbelo_checkout_mobile_summary() for why it
   exists at all. */
.checkout-mobile-summary { display: none; }

/* Distraction-free checkout header/footer — see the is_checkout() branch in
   header.php / footer.php. Nothing here is meant to be left for; the cart
   link is the one deliberate exception (editing quantities is a legitimate
   reason to leave), so it's styled as a plain, quiet text link rather than
   an inviting button. */
.site-header--checkout .header-inner--checkout {
	justify-content: space-between;
	gap: 16px;
	flex-wrap: wrap;
	padding-top: 20px;
	padding-bottom: 20px;
}
/* Page title moved out of the top header bar and down into the strip below
   it (see header.php), inline with the cart-edit link — the duplicate
   <h1 class="entry-title"> the shared content-page.php template still
   renders further down is hidden below, rather than touching that template
   (it's shared by every static page, not just checkout). */
.checkout-header-title {
	margin: 0;
	font-size: 1.2rem;
	font-weight: 700;
	color: var(--ink);
}
body.woocommerce-checkout .entry-header { display: none; }
.checkout-below-header {
	border-bottom: 1px solid var(--hairline);
}
/* .header-inner nested here (rather than reusing checkout-below-header's own
   padding) is what aligns this strip's left edge with the header content
   above it — that shared class already carries the max-width/centering/24px
   side padding every other header-width container on the site uses. */
.checkout-below-header .header-inner {
	padding-top: 10px;
	padding-bottom: 10px;
}
.checkout-below-header-inner { justify-content: space-between; }
.checkout-header-cart-link {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	/* margin-inline-start:auto, not just the container's justify-content, is
	   what actually pins this to the end edge — it wins regardless of how
	   many other items end up in this row or how the container wraps,
	   rather than depending on this staying a clean 2-item space-between
	   row. */
	margin-inline-start: auto;
	flex-shrink: 0;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--stone);
	transition: color var(--t);
}
.checkout-header-cart-link:hover { color: var(--leaf); }
.checkout-header-secure {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 8px 14px;
	background: var(--leaf-wash);
	border-radius: 999px;
	font-size: var(--fs-sm);
	font-weight: 700;
	color: var(--leaf-deep);
}

.site-footer--checkout { border-top: 1px solid var(--hairline); }
.footer-inner--checkout {
	padding: 36px 24px;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 16px;
	text-align: center;
}
.footer-inner--checkout .payment-icons { justify-content: center; margin-top: 0; }
.footer-checkout-links {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 8px 20px;
	font-size: var(--fs-sm);
	color: var(--stone);
}
.footer-checkout-links a:hover { color: var(--leaf); }
.footer-inner--checkout .site-info { border-top: 0; padding-top: 0; }

/* ==========================================================================
   My account
   ========================================================================== */

/* Two-column dashboard only when the account nav exists (logged in) —
   logged out, this wrapper holds the login/register block. */
.woocommerce-account.logged-in .woocommerce {
	display: grid;
	grid-template-columns: 216px minmax(0, 1fr);
	gap: 40px;
	align-items: start;
}
.woocommerce-account.logged-in .woocommerce > * { grid-column: 2; min-width: 0; }
.woocommerce-account.logged-in .woocommerce > .woocommerce-MyAccount-navigation { grid-column: 1; grid-row: 1; }
.woocommerce-account.logged-in .woocommerce > .woocommerce-notices-wrapper { grid-column: 1 / -1; }

nav.woocommerce-MyAccount-navigation ul {
	display: flex;
	flex-direction: column;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	overflow: hidden;
	/* display:flex on its own doesn't suppress <li> markers (that's a
	   separate, explicit reset) — confirmed live, the box/border/active
	   state all rendered correctly but every item still had a bullet.
	   The extra "nav" type selector (matching the real markup, a <nav
	   class="woocommerce-MyAccount-navigation">) isn't decorative — this
	   whole page is wrapped in .entry-content, which has its own
	   `list-style: revert` for genuine blog-content lists
	   (assets/css/main.css, further down); that rule ties this one's
	   specificity and wins on source order, so bullets kept coming back
	   until this got bumped strictly higher. */
	list-style: none;
	margin: 0;
	padding: 0;
}
.woocommerce-MyAccount-navigation li { border-bottom: 1px solid var(--hairline); }
.woocommerce-MyAccount-navigation li:last-child { border-bottom: 0; }
.woocommerce-MyAccount-navigation a {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 11px 15px;
	font-size: var(--fs-md);
	font-weight: 500;
}
.woocommerce-MyAccount-navigation a:hover { background: var(--mist); }
.woocommerce-MyAccount-navigation li.is-active a {
	background: var(--leaf-wash);
	color: var(--leaf-deep);
	font-weight: 700;
}
.woocommerce-MyAccount-navigation a::before {
	content: "";
	width: 16px; height: 16px;
	flex-shrink: 0;
	background-color: currentColor;
	opacity: .75;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
}
.woocommerce-MyAccount-navigation-link--dashboard a::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'%3E%3Crect x='3' y='3' width='7' height='9' rx='1'/%3E%3Crect x='14' y='3' width='7' height='5' rx='1'/%3E%3Crect x='14' y='12' width='7' height='9' rx='1'/%3E%3Crect x='3' y='16' width='7' height='5' rx='1'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'%3E%3Crect x='3' y='3' width='7' height='9' rx='1'/%3E%3Crect x='14' y='3' width='7' height='5' rx='1'/%3E%3Crect x='14' y='12' width='7' height='9' rx='1'/%3E%3Crect x='3' y='16' width='7' height='5' rx='1'/%3E%3C/svg%3E");
}
.woocommerce-MyAccount-navigation-link--orders a::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4h2l1.5 9.5a2 2 0 002 1.5h6a2 2 0 002-1.5L19 7H6.4'/%3E%3Ccircle cx='9.5' cy='19.5' r='1.2' fill='%23000' stroke='none'/%3E%3Ccircle cx='16.5' cy='19.5' r='1.2' fill='%23000' stroke='none'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4h2l1.5 9.5a2 2 0 002 1.5h6a2 2 0 002-1.5L19 7H6.4'/%3E%3Ccircle cx='9.5' cy='19.5' r='1.2' fill='%23000' stroke='none'/%3E%3Ccircle cx='16.5' cy='19.5' r='1.2' fill='%23000' stroke='none'/%3E%3C/svg%3E");
}
.woocommerce-MyAccount-navigation-link--downloads a::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3v12m0 0l-4-4m4 4l4-4'/%3E%3Cpath d='M4 17v2a2 2 0 002 2h12a2 2 0 002-2v-2'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3v12m0 0l-4-4m4 4l4-4'/%3E%3Cpath d='M4 17v2a2 2 0 002 2h12a2 2 0 002-2v-2'/%3E%3C/svg%3E");
}
.woocommerce-MyAccount-navigation-link--edit-address a::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21s-7-6.1-7-11.5A7 7 0 0112 2a7 7 0 017 7.5C19 14.9 12 21 12 21z'/%3E%3Ccircle cx='12' cy='9.5' r='2.3'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21s-7-6.1-7-11.5A7 7 0 0112 2a7 7 0 017 7.5C19 14.9 12 21 12 21z'/%3E%3Ccircle cx='12' cy='9.5' r='2.3'/%3E%3C/svg%3E");
}
.woocommerce-MyAccount-navigation-link--edit-account a::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'%3E%3Ccircle cx='12' cy='7.5' r='3.5'/%3E%3Cpath d='M3 20c1.2-4 4.7-6.5 9-6.5s7.8 2.5 9 6.5' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'%3E%3Ccircle cx='12' cy='7.5' r='3.5'/%3E%3Cpath d='M3 20c1.2-4 4.7-6.5 9-6.5s7.8 2.5 9 6.5' stroke-linecap='round'/%3E%3C/svg%3E");
}
.woocommerce-MyAccount-navigation-link--customer-logout a::before {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4'/%3E%3Cpath d='M16 17l5-5-5-5M21 12H9'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4'/%3E%3Cpath d='M16 17l5-5-5-5M21 12H9'/%3E%3C/svg%3E");
}
.woocommerce-MyAccount-content { min-width: 0; }
.woocommerce-MyAccount-content .woocommerce-Addresses {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 22px;
}
.woocommerce-MyAccount-content address {
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	padding: 15px;
	font-style: normal;
	font-size: var(--fs-md);
}

/* Account dashboard overview (My Account landing page) — replaces
   WooCommerce's plain "Hello X / view your recent orders..." text wall. */
.account-dashboard-greeting {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	font-size: 1.1rem;
	margin: 0 0 24px;
}
.account-dashboard-logout {
	font-size: var(--fs-sm);
	font-weight: 500;
	color: var(--stone);
	text-decoration: underline;
	text-underline-offset: 2px;
}
.account-dashboard-logout:hover { color: var(--ink); }

.account-dashboard-cards {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 16px;
	margin-bottom: 24px;
}
.account-dashboard-card {
	border: 1px solid var(--hairline);
	border-radius: var(--r-lg);
	padding: 18px 20px;
	display: flex;
	flex-direction: column;
	gap: 4px;
}
.account-dashboard-card--muted {
	justify-content: center;
	align-items: flex-start;
	gap: 10px;
}
.account-dashboard-card-value {
	font-family: var(--mono);
	font-size: 1.9rem;
	font-weight: 700;
	line-height: 1;
	color: var(--ink);
}
.account-dashboard-card-value--status {
	font-family: var(--sans);
	font-size: 1.05rem;
}
.account-dashboard-card-value--status.is-completed { color: var(--leaf-deep); }
.account-dashboard-card-value--status.is-processing { color: var(--amber-deep); }
.account-dashboard-card-value--status.is-cancelled,
.account-dashboard-card-value--status.is-refunded,
.account-dashboard-card-value--status.is-failed { color: var(--crit); }
.account-dashboard-card-label {
	font-size: var(--fs-sm);
	color: var(--stone);
}
.account-dashboard-card-link {
	margin-top: 8px;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--leaf-deep);
}
.account-dashboard-card-link:hover { text-decoration: underline; }

.account-dashboard-quicklinks {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 12px;
	margin-bottom: 32px;
}
.account-dashboard-quicklink {
	border: 1px solid var(--hairline);
	border-radius: var(--r-lg);
	padding: 14px 12px;
	text-align: center;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--ink);
	transition: background var(--t), border-color var(--t);
}
.account-dashboard-quicklink:hover {
	background: var(--mist);
	border-color: var(--stone);
}

.account-dashboard-address {
	border: 1px solid var(--hairline);
	border-radius: var(--r-lg);
	padding: 18px 20px;
}
.account-dashboard-address h3 {
	font-size: var(--fs-base);
	margin: 0 0 10px;
}
.account-dashboard-address address {
	font-style: normal;
	font-size: var(--fs-md);
	color: var(--stone);
	margin: 0 0 10px;
}
.account-dashboard-address a {
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--leaf-deep);
}
.account-dashboard-address a:hover { text-decoration: underline; }

@media (max-width: 640px) {
	.account-dashboard-cards,
	.account-dashboard-quicklinks { grid-template-columns: minmax(0, 1fr); }
	.account-dashboard-greeting { flex-direction: column; align-items: flex-start; gap: 8px; }
}

/* Order status timeline — My Account > view a single order.
   .woocommerce-MyAccount-content (matching the real wrapper markup) rather
   than bare "ol.order-timeline": same tie-with-source-order problem as the
   nav list above — .entry-content ol also sets list-style: revert (for
   genuine blog-content lists) at equal specificity, further down this
   file, and was winning the "1. 2. 3." numbering back before this got
   bumped strictly higher. */
.woocommerce-MyAccount-content ol.order-timeline {
	display: flex;
	list-style: none;
	margin: 0 0 32px;
	padding: 20px 10px 0;
	border: 1px solid var(--hairline);
	border-radius: var(--r-lg);
}
.order-timeline-step {
	position: relative;
	flex: 1;
	text-align: center;
}
/* Connecting line, drawn across the whole row behind the dots, then
   re-drawn in green only up to however far the order has actually
   progressed — simpler than measuring per-segment widths in PHP. */
.order-timeline-step::before {
	content: "";
	position: absolute;
	top: 7px;
	inset-inline-start: -50%;
	width: 100%;
	height: 2px;
	background: var(--hairline);
	z-index: 0;
}
.order-timeline-step:first-child::before { content: none; }
.order-timeline-step--done::before,
.order-timeline-step--current::before { background: var(--leaf); }
.order-timeline-dot {
	position: relative;
	z-index: 1;
	display: inline-block;
	width: 16px; height: 16px;
	border-radius: 50%;
	background: var(--paper);
	border: 2px solid var(--hairline);
}
.order-timeline-step--done .order-timeline-dot {
	background: var(--leaf);
	border-color: var(--leaf);
}
.order-timeline-step--current .order-timeline-dot {
	border-color: var(--leaf);
	box-shadow: 0 0 0 3px var(--leaf-wash);
}
.order-timeline-label {
	display: block;
	margin-top: 10px;
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--stone);
}
.order-timeline-step--done .order-timeline-label,
.order-timeline-step--current .order-timeline-label { color: var(--ink); }
.order-timeline-date {
	display: block;
	margin-top: 2px;
	font-size: var(--fs-2xs);
	font-family: var(--mono);
	color: var(--stone);
}
.order-timeline--stopped {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0 0 32px;
	padding: 14px 16px;
	border: 1px solid var(--crit);
	border-radius: var(--r-lg);
	background: var(--crit-wash);
	color: var(--crit);
	font-weight: 600;
}
.order-timeline-stopped-icon {
	width: 18px; height: 18px;
	flex-shrink: 0;
	background-color: currentColor;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M15 9l-6 6M9 9l6 6'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M15 9l-6 6M9 9l6 6'/%3E%3C/svg%3E");
}

/* Account forms */
.woocommerce-form__label,
.woocommerce form .form-row label,
.woocommerce-EditAccountForm label {
	display: block;
	font-weight: 600;
	font-size: var(--fs-base);
	margin-bottom: 5px;
}
.woocommerce-Input,
.woocommerce-form__input,
input.input-text,
.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea { width: 100%; }
.woocommerce-form-row,
.woocommerce form .form-row { margin-bottom: 13px; }
.woocommerce-form__label-for-checkbox,
.woocommerce-form-login__rememberme {
	display: flex !important;
	align-items: center;
	gap: 8px;
	font-weight: 500;
	margin-bottom: 0;
}
.woocommerce-form__input-checkbox { width: auto; margin: 0; }
.woocommerce-Button,
.woocommerce-button,
.woocommerce-form-login__submit,
.woocommerce-form-register__submit { margin-top: 8px; }
.woocommerce-LostPassword { margin-top: 12px; font-size: var(--fs-base); }
.woocommerce-LostPassword a:hover { color: var(--leaf); text-decoration: underline; }
.woocommerce-privacy-policy-text {
	font-size: var(--fs-sm);
	color: var(--stone);
	margin: 12px 0;
}
.woocommerce-privacy-policy-text a { text-decoration: underline; }

/* Login + register side by side */
.woocommerce-account .u-columns.col2-set {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 28px;
}
.woocommerce-account .u-columns.col2-set .col-1,
.woocommerce-account .u-columns.col2-set .col-2 {
	width: auto;
	float: none;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	padding: 24px;
}
.woocommerce-account .u-columns.col2-set h2 { font-size: 1.14rem; margin-bottom: 16px; }

.woocommerce-form-login,
.woocommerce-form-register,
.woocommerce-EditAccountForm,
.woocommerce-ResetPassword { max-width: 520px; }

/* ==========================================================================
   Sidebar / custom shop filters
   ========================================================================== */

.shop-filters {
	background: var(--paper);
	border: 1px solid var(--hairline);
	border-radius: var(--r-lg);
	padding: 18px;
}
.shop-filters-panel-header,
.shop-filters-toggle { display: none; }

.shop-filters-section { margin-bottom: 26px; }
.shop-filters-section:last-child { margin-bottom: 0; }
.shop-filters-title {
	font-family: var(--sans);
	font-size: var(--fs-xs);
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--stone);
	padding-bottom: 9px;
	margin-bottom: 12px;
	border-bottom: 1px solid var(--hairline);
}

/* Every filter section collapses by default except Category (a plain div,
   not a <details>) — the one people almost always want visible right away. */
summary.shop-filters-title {
	display: flex;
	align-items: center;
	justify-content: space-between;
	cursor: pointer;
	list-style: none;
	user-select: none;
}
summary.shop-filters-title::-webkit-details-marker { display: none; }
summary.shop-filters-title::after {
	content: "";
	width: 9px; height: 9px;
	flex-shrink: 0;
	/* border-right + border-bottom rotated 45deg below is a chevron pointing
	   down/up (accordion expand indicator) — shape doesn't depend on reading
	   direction, only its spacing (this margin) from the label text does. */
	margin-inline-start: 8px;
	border-right: 1.5px solid var(--stone);
	border-bottom: 1.5px solid var(--stone);
	transform: rotate(45deg);
	transition: transform var(--t);
}
details[open] > summary.shop-filters-title::after { transform: rotate(-135deg); }
details.shop-filters-section > :not(summary) { animation: shop-filters-reveal var(--t) ease; }
@keyframes shop-filters-reveal {
	from { opacity: 0; }
	to { opacity: 1; }
}

.shop-filter-list li { list-style: none; }
.shop-filter-list { margin: 0; padding: 0; }
.shop-filter-item + .shop-filter-item { margin-top: 2px; }
.shop-filter-item > a {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 6px 4px;
	border-radius: var(--r);
	font-size: var(--fs-md);
	color: var(--ink);
	transition: color var(--t), background-color var(--t);
}
.shop-filter-item > a:hover { color: var(--leaf); background: var(--mist); }
.shop-filter-item.is-active > a { color: var(--leaf-deep); font-weight: 700; }
/* Category/brand filters: <a><span>Name</span><span class="shop-filter-count">
   N</span></a> — the label is the first span, so making it grow correctly
   pushes the count to the far end. The rating filter's checkbox-style list
   (shop-filter-list--check) puts a different, empty span FIRST instead —
   <span class="shop-filter-checkbox"></span><span class="shop-filter-stars">
   ...</span><span class="shop-filter-count">...</span> — so this same rule
   was growing that empty 15x15px checkbox to fill the entire row instead
   (confirmed live: a big blank bordered box next to the stars). Excluding
   it here and growing .shop-filter-stars instead, right below, fixes that
   without touching the category/brand rule this was written for. */
.shop-filter-item > a > span:first-of-type:not(.shop-filter-checkbox) { flex: 1; }
.shop-filter-list--check .shop-filter-stars,
.shop-filter-list--check .shop-filter-label { flex: 1; }
.shop-filter-count {
	font-family: var(--mono);
	font-size: var(--fs-2xs);
	color: var(--stone);
}

.shop-filter-checkbox {
	flex: 0 0 auto;
	width: 15px;
	height: 15px;
	border: 1.5px solid var(--hairline);
	border-radius: 3px;
	background: var(--paper);
	transition: border-color var(--t), background-color var(--t);
}
.shop-filter-item.is-active .shop-filter-checkbox {
	background: var(--leaf);
	border-color: var(--leaf);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M3.5 8.2l3 3 6-6.4'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: center;
}
.shop-filter-stars { color: var(--amber); letter-spacing: 1px; font-size: var(--fs-sm); }

/* Active filter chips */
.shop-filters-active { margin-bottom: 26px; }
.shop-filters-active-list { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.shop-filter-chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	background: var(--leaf-wash);
	color: var(--leaf-deep);
	border-radius: 2px;
	padding: 4px 8px 4px 10px;
	font-size: var(--fs-sm);
	font-weight: 700;
	transition: background-color var(--t);
}
.shop-filter-chip:hover { background: var(--hairline); }
.shop-filter-chip span[aria-hidden] { font-size: var(--fs-md); line-height: 1; opacity: .7; }
.shop-filters-clear {
	font-size: var(--fs-xs);
	color: var(--stone);
	text-decoration: underline;
	text-underline-offset: 2px;
}
.shop-filters-clear:hover { color: var(--leaf); }

/* Price range */
.shop-filter-price-row { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.shop-filter-price-row input[type="number"] {
	flex: 1 1 0;
	min-width: 0;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	padding: 8px 9px;
	font-family: var(--mono);
	font-size: var(--fs-sm);
	color: var(--ink);
	background: var(--paper);
}
.shop-filter-price-row input[type="number"]:focus { outline: none; border-color: var(--leaf); }
.shop-filter-price-sep { color: var(--stone); flex: 0 0 auto; }
.shop-filter-price-submit { width: 100%; padding: 9px 14px; font-size: var(--fs-sm); }

/* ==========================================================================
   Blog / archive / static pages
   ========================================================================== */

.post-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 22px;
	padding-top: 28px;
	padding-bottom: 48px;
}
.post-card {
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	overflow: hidden;
	background: var(--paper);
	transition: border-color var(--t);
}
.post-card:hover { border-color: var(--leaf); }
.post-card-thumb img { aspect-ratio: 16 / 10; object-fit: cover; width: 100%; }
.post-card-body { padding: 16px; }
.post-card-title { font-size: 1.02rem; margin-bottom: 6px; }
.post-card-meta {
	font-family: var(--mono);
	font-size: var(--fs-xs);
	color: var(--stone);
	margin-bottom: 8px;
}
.post-card-excerpt { font-size: var(--fs-md); color: var(--stone); }

.archive-header { padding-top: 32px; }
.entry-header {
	max-width: 74ch;
	margin: 40px auto 0;
	padding: 0 24px;
}
.entry-header .entry-title { font-size: clamp(1.7rem, 3.4vw, 2.35rem); letter-spacing: -.02em; }
.entry-meta {
	font-family: var(--mono);
	font-size: var(--fs-xs);
	color: var(--stone);
	display: flex;
	gap: 12px;
	flex-wrap: wrap;
}
.entry-thumbnail {
	max-width: var(--shell);
	margin: 26px auto 0;
	padding: 0 24px;
}
.entry-thumbnail img { border-radius: var(--r); }
.entry-content {
	max-width: 74ch;
	margin: 0 auto;
	padding: 22px 24px 60px;
	font-size: 1.02rem;
}
.entry-content h2, .entry-content h3 { margin-top: 1.6em; }
.entry-content p, .entry-content ul, .entry-content ol { margin-bottom: 1.15em; }
.entry-content ul, .entry-content ol { padding-inline-start: 1.3em; list-style: revert; }
/* Excluded from the prose-list revert just above: cart/checkout render
   inside .entry-content too (shortcodes on a plain Page — see the Cart
   section earlier in this file), so a WooCommerce notice that happens to be
   a <ul> (an error list, most commonly) was matching it and getting its
   bullets back, tied on specificity and only losing because this file
   placement put it later. More specific here instead of relying on staying
   earlier in the file. */
.entry-content ul.woocommerce-error,
.entry-content ul.woocommerce-message,
.entry-content ul.woocommerce-info,
.entry-content ul.woocommerce-notice {
	padding-inline-start: 42px;
	list-style: none;
}
.entry-content img { border-radius: var(--r); }
.entry-content a { color: var(--leaf); text-decoration: underline; }
.entry-footer {
	max-width: 74ch;
	margin: 0 auto;
	padding: 0 24px 40px;
	font-size: var(--fs-base);
	color: var(--stone);
}

.no-results,
.error-404 {
	max-width: 62ch;
	margin: 0 auto;
	padding: 60px 24px 80px;
	text-align: center;
}
.error-404 h1 { font-size: 1.9rem; }
.error-404 .search-form { margin: 20px 0; }
.error-404-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 72px;
	height: 72px;
	margin-bottom: 20px;
	border-radius: 50%;
	background: var(--mist);
}
/* Same magnifying-glass path as the header search icon — a lost page reads
   naturally as "couldn't find it," and reusing the shape avoids introducing
   a second icon style just for this one spot. */
.error-404-icon::before {
	content: "";
	width: 32px;
	height: 32px;
	background-color: var(--stone);
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='9' cy='9' r='6.5' stroke='%23000' stroke-width='1.5'/%3E%3Cpath d='M14 14L18 18' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Ccircle cx='9' cy='9' r='6.5' stroke='%23000' stroke-width='1.5'/%3E%3Cpath d='M14 14L18 18' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
}
.error-404-bestsellers { margin-top: 20px; }

.comments-area {
	max-width: 74ch;
	margin: 0 auto;
	padding: 0 24px 60px;
}
.comments-title { font-size: 1.2rem; }

/* ==========================================================================
   Assurance band + footer
   ========================================================================== */

.footer-newsletter {
	background: var(--mist);
	border-top: 1px solid var(--hairline);
	border-bottom: 1px solid var(--hairline);
	margin-top: 60px;
}
.footer-newsletter-inner {
	padding: 32px 24px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	flex-wrap: wrap;
}
.footer-newsletter-inner h2 { font-size: 1.2rem; margin-bottom: 3px; }
.footer-newsletter-inner p { margin: 0; color: var(--stone); font-size: var(--fs-md); }
.newsletter-form { display: flex; gap: 8px; flex-wrap: wrap; position: relative; }
.newsletter-form input[type="email"] { min-width: 250px; }
.newsletter-message {
	position: absolute;
	top: 100%; left: 0;
	margin: 6px 0 0;
	font-size: var(--fs-sm);
	color: var(--leaf-deep);
}

.site-footer { background: var(--paper); }
.footer-inner { padding: 44px 24px 28px; }
.footer-columns {
	display: grid;
	grid-template-columns: 1.3fr 0.9fr 0.9fr 0.9fr 0.9fr;
	gap: 32px;
	margin-bottom: 30px;
}
.footer-column .widget-title,
.footer-column h3 {
	font-family: var(--sans);
	font-size: var(--fs-xs);
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--ink);
	margin-bottom: 12px;
}
.footer-column ul { display: grid; gap: 8px; font-size: var(--fs-md); }
.footer-column a:hover { color: var(--leaf); }
.footer-logo img { width: 140px; height: auto; margin-bottom: 10px; }
.footer-about p { color: var(--stone); font-size: var(--fs-md); max-width: 34ch; margin-bottom: 14px; }

.footer-social { display: flex; gap: 8px; }
.footer-social-link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px; height: 34px;
	border: 1px solid var(--hairline);
	border-radius: 50%;
	color: var(--stone);
	transition: border-color var(--t), color var(--t);
}
.footer-social-link:hover { border-color: var(--leaf); color: var(--leaf); }
.footer-social-icon {
	width: 15px; height: 15px;
	background-color: currentColor;
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
}
.footer-social-icon--facebook {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M15 8.5h2.2V5.1h-2.6c-2.6 0-4 1.6-4 4.1v2.1H8.5v3.4h2.1V21h3.4v-6.3h2.6l.5-3.4h-3.1V9.4c0-.7.3-.9.9-.9Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M15 8.5h2.2V5.1h-2.6c-2.6 0-4 1.6-4 4.1v2.1H8.5v3.4h2.1V21h3.4v-6.3h2.6l.5-3.4h-3.1V9.4c0-.7.3-.9.9-.9Z'/%3E%3C/svg%3E");
}
.footer-social-icon--instagram {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M7 2h10a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H7a5 5 0 0 1-5-5V7a5 5 0 0 1 5-5Zm0 2a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V7a3 3 0 0 0-3-3H7Zm5 3.5A5.5 5.5 0 1 1 6.5 13 5.5 5.5 0 0 1 12 7.5Zm0 2A3.5 3.5 0 1 0 15.5 13 3.5 3.5 0 0 0 12 9.5ZM17.8 6a1.2 1.2 0 1 1 0 2.4 1.2 1.2 0 0 1 0-2.4Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M7 2h10a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H7a5 5 0 0 1-5-5V7a5 5 0 0 1 5-5Zm0 2a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V7a3 3 0 0 0-3-3H7Zm5 3.5A5.5 5.5 0 1 1 6.5 13 5.5 5.5 0 0 1 12 7.5Zm0 2A3.5 3.5 0 1 0 15.5 13 3.5 3.5 0 0 0 12 9.5ZM17.8 6a1.2 1.2 0 1 1 0 2.4 1.2 1.2 0 0 1 0-2.4Z'/%3E%3C/svg%3E");
}
.footer-social-icon--tiktok {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M16.6 5.8a4.6 4.6 0 0 1-3.8-4.1V1h-3.3v14.6a2.6 2.6 0 1 1-1.9-2.5V9.6a5.9 5.9 0 1 0 5.2 5.9V8.4a7.9 7.9 0 0 0 4.6 1.5V6.6a4.6 4.6 0 0 1-.8-.8Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M16.6 5.8a4.6 4.6 0 0 1-3.8-4.1V1h-3.3v14.6a2.6 2.6 0 1 1-1.9-2.5V9.6a5.9 5.9 0 1 0 5.2 5.9V8.4a7.9 7.9 0 0 0 4.6 1.5V6.6a4.6 4.6 0 0 1-.8-.8Z'/%3E%3C/svg%3E");
}
.footer-social-icon--whatsapp {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a10 10 0 0 0-8.6 15L2 22l5.2-1.4A10 10 0 1 0 12 2Zm0 1.8a8.2 8.2 0 0 1 6.9 12.6l-.2.4.9 3.2-3.3-.9-.4.2A8.2 8.2 0 1 1 12 3.8Zm-3.4 4c-.2 0-.5.1-.7.3-.2.2-.9.9-.9 2.2s.9 2.5 1.1 2.7c.1.2 1.8 2.9 4.5 3.9 2.2.9 2.7.7 3.1.6.5-.1 1.6-.6 1.8-1.3.2-.6.2-1.2.2-1.3-.1-.1-.3-.2-.5-.3-.2-.1-1.3-.6-1.5-.7-.2-.1-.3-.1-.5.1-.2.2-.6.7-.7.9-.1.1-.3.2-.5.1-.2-.1-1-.4-1.9-1.2-.7-.6-1.2-1.4-1.3-1.6-.1-.2 0-.4.1-.5.1-.1.3-.3.4-.5.1-.1.1-.3.2-.4 0-.1 0-.3 0-.4 0-.1-.5-1.3-.7-1.7-.2-.4-.4-.4-.5-.4h-.5Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a10 10 0 0 0-8.6 15L2 22l5.2-1.4A10 10 0 1 0 12 2Zm0 1.8a8.2 8.2 0 0 1 6.9 12.6l-.2.4.9 3.2-3.3-.9-.4.2A8.2 8.2 0 1 1 12 3.8Zm-3.4 4c-.2 0-.5.1-.7.3-.2.2-.9.9-.9 2.2s.9 2.5 1.1 2.7c.1.2 1.8 2.9 4.5 3.9 2.2.9 2.7.7 3.1.6.5-.1 1.6-.6 1.8-1.3.2-.6.2-1.2.2-1.3-.1-.1-.3-.2-.5-.3-.2-.1-1.3-.6-1.5-.7-.2-.1-.3-.1-.5.1-.2.2-.6.7-.7.9-.1.1-.3.2-.5.1-.2-.1-1-.4-1.9-1.2-.7-.6-1.2-1.4-1.3-1.6-.1-.2 0-.4.1-.5.1-.1.3-.3.4-.5.1-.1.1-.3.2-.4 0-.1 0-.3 0-.4 0-.1-.5-1.3-.7-1.7-.2-.4-.4-.4-.5-.4h-.5Z'/%3E%3C/svg%3E");
}

.payment-icons { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 10px; }
.payment-icon {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	font-size: var(--fs-sm);
	font-weight: 600;
	border: 1px solid var(--hairline);
	border-radius: var(--r);
	padding: 7px 11px;
	color: var(--ink);
	background: var(--paper);
}
.payment-icon-glyph {
	width: 15px; height: 15px;
	flex-shrink: 0;
	background-color: var(--leaf);
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
}
.payment-icon-glyph--cod {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Crect x='2' y='6' width='20' height='13' rx='2' stroke='%23000' stroke-width='1.8'/%3E%3Ccircle cx='12' cy='12.5' r='3' stroke='%23000' stroke-width='1.8'/%3E%3Cpath d='M6 6V5a2 2 0 0 1 2-2h9' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Crect x='2' y='6' width='20' height='13' rx='2' stroke='%23000' stroke-width='1.8'/%3E%3Ccircle cx='12' cy='12.5' r='3' stroke='%23000' stroke-width='1.8'/%3E%3Cpath d='M6 6V5a2 2 0 0 1 2-2h9' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
}
.site-info {
	border-top: 1px solid var(--hairline);
	padding-top: 18px;
	font-size: var(--fs-sm);
	color: var(--stone);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 6px 16px;
}
.site-info .herbelo-lang-switcher { font-size: var(--fs-sm); }
.footer-navigation ul { display: grid; gap: 8px; }

/* ==========================================================================
   Front page
   ========================================================================== */

.home-content { max-width: var(--shell); margin: 0 auto; padding: 0 24px; }

/* ---- Hero slider — designed banner slides, standard e-commerce banner
   height (was min-height: 82vh / max-height: 760px — near full-viewport,
   more like a splash screen than a hero banner). ---- */
.hero-slider {
	position: relative;
	min-height: 420px;
	height: 52vh;
	max-height: 560px;
	overflow: hidden;
	background: var(--ink);
}
.hero-slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	visibility: hidden;
	transition: opacity 1s ease, visibility 1s;
}
.hero-slide.is-active { opacity: 1; visibility: visible; z-index: 1; }
.hero-slide-bg {
	position: absolute;
	inset: 0;
	background-size: cover;
	background-position: center;
	background-color: var(--mist);
}
.hero-slide-overlay {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	background: linear-gradient(90deg, rgba(16,26,19,.85) 0%, rgba(16,26,19,.6) 42%, rgba(16,26,19,.2) 72%, transparent 100%);
}
.hero-slide-inner { max-width: 580px; padding: 0 24px; margin: 0 auto; width: 100%; }
.hero-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-family: var(--mono);
	font-size: var(--fs-xs);
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--leaf-deep);
	background: var(--leaf-wash);
	border-radius: 999px;
	padding: 5px 12px;
	margin-bottom: 18px;
}
.hero-slide-title {
	font-size: clamp(2rem, 4.4vw, 3.1rem);
	font-weight: 700;
	letter-spacing: -.025em;
	line-height: 1.1;
	color: var(--paper);
	margin-bottom: 14px;
}
.hero-slide-title--product { font-size: clamp(1.55rem, 3vw, 2.2rem); }
.hero-slide-text { color: rgba(255,255,255,.86); font-size: 1.08rem; max-width: 46ch; margin-bottom: 28px; }
.hero-slide-price,
.hero-slide-price .amount { font-family: var(--mono); font-weight: 700; font-size: 1.25rem; color: var(--paper) !important; }
.hero-slide-ctas { display: flex; gap: 12px; flex-wrap: wrap; }
.hero-slide-ctas .button-outline {
	color: var(--paper);
	border-color: rgba(255,255,255,.55);
}
.hero-slide-ctas .button-outline:hover {
	background: rgba(255,255,255,.12);
	color: var(--paper);
	border-color: var(--paper);
}

.hero-slider-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 3;
	width: 44px; height: 44px;
	border-radius: 50%;
	background: rgba(255,255,255,.14);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	border: 1px solid rgba(255,255,255,.4);
	cursor: pointer;
	transition: background var(--t), border-color var(--t);
}
.hero-slider-arrow:hover { background: rgba(255,255,255,.28); border-color: var(--paper); }
.hero-slider-arrow::before {
	content: "";
	position: absolute;
	top: 50%; left: 50%;
	width: 9px; height: 9px;
	border: 1.8px solid var(--paper);
	border-width: 1.8px 1.8px 0 0;
}
.hero-slider-prev { inset-inline-start: 24px; }
.hero-slider-prev::before { transform: translate(-30%, -50%) rotate(-135deg); }
.hero-slider-next { inset-inline-end: 24px; }
.hero-slider-next::before { transform: translate(-70%, -50%) rotate(45deg); }
/* Prev/next are index-based (see initHeroSlider in main.js), not scroll
   position, so the JS itself needs no RTL handling — but the chevrons still
   need to point toward the reading-appropriate side, same swap as the
   product sliders above. */
[dir="rtl"] .hero-slider-prev::before { transform: translate(-70%, -50%) rotate(45deg); }
[dir="rtl"] .hero-slider-next::before { transform: translate(-30%, -50%) rotate(-135deg); }

.hero-slider-dots {
	position: absolute;
	bottom: 26px;
	left: 50%;
	transform: translateX(-50%);
	z-index: 3;
	display: flex;
	gap: 8px;
}
.hero-slider-dot {
	width: 8px; height: 8px;
	padding: 0;
	border: 0;
	border-radius: 4px;
	background: rgba(255,255,255,.45);
	cursor: pointer;
	transition: background var(--t), width var(--t);
}
.hero-slider-dot:hover { background: rgba(255,255,255,.7); }
.hero-slider-dot.is-active { width: 26px; background: var(--paper); }

/* ---- Trust bar — real, verified numbers only (no fabricated stats) ---- */
.trust-bar { background: var(--paper); border-bottom: 1px solid var(--hairline); }
.trust-bar-inner {
	max-width: var(--shell);
	margin: 0 auto;
	padding: 22px 24px;
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 16px;
}
.trust-stat {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 2px;
	padding: 0 12px;
	border-inline-start: 1px solid var(--hairline);
}
.trust-stat:first-child { border-inline-start: 0; }
.trust-stat strong {
	font-family: var(--mono);
	font-size: 1.3rem;
	font-weight: 700;
	color: var(--leaf-deep);
}
.trust-stat span {
	font-size: var(--fs-xs);
	color: var(--stone);
	text-transform: uppercase;
	letter-spacing: .06em;
}

/* ---- Section shell, reused by every homepage block below the hero ---- */
/* 52px was doubling up between adjacent sections (52 + 52 = 104px of dead
   space where two .sec siblings meet), since padding doesn't collapse the
   way margins do. 40px keeps real breathing room without the excess. */
.sec { padding: 40px 0; }
.sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 26px; }
.sec-head h2 { font-size: 1.55rem; letter-spacing: -.01em; }
.sec-head > a { font-size: var(--fs-sm); font-weight: 700; color: var(--leaf); white-space: nowrap; }
.sec-head > a:hover { text-decoration: underline; }
.sec-eyebrow {
	display: block;
	font-family: var(--mono);
	font-size: var(--fs-xs);
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--stone);
	margin-bottom: 6px;
}

/* ---- Category grid ---- */
.cat-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.cat-card {
	display: flex;
	flex-direction: column;
	gap: 12px;
	padding: 20px;
	background: var(--paper);
	border: 1px solid var(--hairline);
	border-radius: var(--r-lg);
	transition: border-color var(--t), transform var(--t), box-shadow var(--t);
}
.cat-card:hover { border-color: var(--leaf); transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.cat-icon {
	width: 42px; height: 42px;
	border-radius: 10px;
	background: var(--leaf-wash);
	color: var(--leaf-deep);
	display: flex;
	align-items: center;
	justify-content: center;
}
.cat-card h3 { font-size: var(--fs-md); margin-bottom: 2px; }
.cat-count { font-family: var(--mono); font-size: var(--fs-sm); color: var(--stone); }

/* ---- "Complétez votre routine" — grouped by health goal, a grid of
   groups rather than one flat carousel (see herbelo_homepage_routine_bundle(),
   inc/homepage.php). Fixed 5-across (2 rows of 5 for the 10 goals shown)
   per request — see the max-width: 1000px override further down for the
   narrower-screen column count. ---- */
.routine-grid {
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
	gap: 4px;
	/* align-items: stretch (grid's default) rather than start — cards
	   otherwise sized to their own content (a 2-line goal title, or one
	   card's slider sitting slightly taller than another's) made same-row
	   cards visibly uneven heights. Stretching, plus display:flex below to
	   push each card's slider to fill the extra space, keeps every card in
	   a row matching the tallest one instead. */
}
.routine-group {
	display: flex;
	flex-direction: column;
	padding: 12px;
	background: var(--paper);
	border-radius: var(--r-lg);
}
.routine-group-slider { flex: 1 1 auto; display: flex; }
.routine-group-slider .routine-group-products { flex: 1 1 auto; }
.routine-group-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	margin-bottom: 8px;
}
.routine-group-title { font-size: var(--fs-md); margin-bottom: 0; }
/* Per-goal "see more in this niche" link — separate from the slider's own
   prev/next arrows (which just cycle the 2-3 products already loaded into
   this card): this jumps straight to the shop, pre-filtered to just this
   one goal, for the rest of that goal's catalog. */
.routine-group-more {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	color: var(--leaf);
	font-size: 1.1rem;
	line-height: 1;
	text-decoration: none;
	transition: transform var(--t);
}
.routine-group-more:hover { transform: translateX(3px); }
[dir="rtl"] .routine-group-more { transform: scaleX(-1); }
[dir="rtl"] .routine-group-more:hover { transform: scaleX(-1) translateX(3px); }
/* One product visible at a time per goal card, sliding between the rest of
   that goal's products (see the [data-slider] markup in front-page.php,
   reusing the same generic slider JS as the bestsellers/new-arrivals rows
   above) rather than a mini grid — a goal with 3 products no longer
   crowds 3 small cards into one card's width. ul.products is
   `display: grid !important` sitewide (see "Product grid" rules above) —
   matching its element+class specificity here (not just a bare class) is
   what lets this override win. */
ul.routine-group-products {
	display: flex !important;
	grid-template-columns: none !important;
	margin: 0 !important;
	gap: 0;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
}
.routine-group-products::-webkit-scrollbar { display: none; }
.routine-group-products > .product-card {
	scroll-snap-align: start;
	flex: 0 0 100%;
	width: 100%;
}
/* All of a group's product cards sit in this same flex row (scrolled
   horizontally, not swapped in/out of the DOM — see initSliders() in
   main.js), so by normal flex-layout rules the row's height is set by
   whichever ONE of them is tallest, even though only one is visible at a
   time. .product-card-brand and .product-card-rating are conditionally
   PRINTED — content-product.php only outputs them at all when the
   product actually has a brand/reviews; a min-height rule here can't
   reserve space for an element that was never rendered in the first
   place. The real fix is in content-product.php + front-page.php: this
   section sets a flag so a product missing either instead gets an empty,
   aria-hidden placeholder in the same spot — invisible but still taking
   up its normal box height, via .is-placeholder below — so every slide
   already lands at close to the same natural height before row-height-
   matching even comes into play. */
.routine-group-products .product-card-brand.is-placeholder,
.routine-group-products .product-card-rating.is-placeholder {
	visibility: hidden;
}
.routine-group-slider .slider-arrow { top: 38%; }
/* Out-of-stock products are included in this section (see
   herbelo_homepage_routine_bundle(), inc/homepage.php) so more health
   goals can show — WooCommerce already swaps the add-to-cart button for a
   "read more" link and adds the "outofstock" class for these, this badge
   just makes the reason visible at a glance rather than a silently
   missing buy button. Positioned like the sale badge (same corner,
   .product-card-image already has position: relative from that rule). */
.routine-group-products .outofstock .product-card-image::after {
	content: "Bientôt disponible";
	position: absolute;
	top: 10px;
	right: 10px;
	font-family: var(--mono);
	font-size: var(--fs-2xs);
	font-weight: 700;
	letter-spacing: .04em;
	padding: 3px 6px;
	border-radius: 2px;
	background: var(--stone);
	color: var(--paper);
}
[dir="rtl"] .routine-group-products .outofstock .product-card-image::after {
	content: "قريباً";
	right: auto;
	left: 10px;
}

/* ---- Sliders (bestsellers, related products): reuse the sitewide
   ul.products/.product-card styling, just need horizontal scroll-snap. ---- */
.slider { position: relative; }
/* ul.bestseller-grid / ul.related-grid (not bare .bestseller-grid etc.): the
   sitewide ul.products rule is itself `ul` + class, specificity (0,1,1) with
   !important — a bare class selector (0,1,0) would lose that tie even with
   matching !important, since ties fall back to specificity before source
   order. Matching the type+class shape here guarantees this rule wins
   (related products additionally fights .related ul.products, but that one
   isn't !important, so it loses outright regardless of specificity). */
ul.bestseller-grid,
ul.related-grid {
	max-width: none;
	margin: 0 !important;
	padding: 4px 4px 12px !important;
	display: flex !important;
	grid-template-columns: none !important;
	gap: 20px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-padding-inline-start: 4px;
	-webkit-overflow-scrolling: touch;
	/* Firefox + modern Chromium: hide the scrollbar but keep it scrollable —
	   the arrow buttons are the intended control, native drag/swipe still works. */
	scrollbar-width: none;
}
.bestseller-grid::-webkit-scrollbar,
.related-grid::-webkit-scrollbar { display: none; }
.bestseller-grid > .product-card,
.related-grid > .product-card {
	scroll-snap-align: start;
	flex: 0 0 260px;
}
.slider-arrow {
	position: absolute;
	top: 42%;
	transform: translateY(-50%);
	width: 40px; height: 40px;
	/* It's a real <button>, so it inherits the global button rule's
	   `padding: 12px 20px` — with box-sizing: border-box and no inset (or an
	   over-tight one) that padding doesn't fit inside a 40px (or the category
	   bar's 26px) box, so the browser was forced to grow the border-box past
	   its own explicit width/height to fit it — an oval, not a circle.
	   There's no text/icon content needing padding (the chevron is a
	   ::before), so reset it to 0. */
	padding: 0;
	border-radius: 50%;
	background: var(--paper);
	border: 1px solid var(--hairline);
	box-shadow: var(--shadow-lg);
	cursor: pointer;
	z-index: 2;
	transition: border-color var(--t), opacity var(--t);
}
/* Also from the global button rule: button:hover sets a solid dark-green
   background — undeclared here before, so it leaked through on hover
   instead of staying var(--paper) with just the border going green. */
.slider-arrow:hover { border-color: var(--leaf); background: var(--paper); }
.slider-arrow::before {
	content: "";
	position: absolute;
	top: 50%; left: 50%;
	width: 8px; height: 8px;
	border: 1.8px solid var(--ink);
	border-width: 1.8px 1.8px 0 0;
}
.slider-arrow-prev { inset-inline-start: -8px; }
.slider-arrow-prev::before { transform: translate(-30%, -50%) rotate(-135deg); }
.slider-arrow-next { inset-inline-end: -8px; }
.slider-arrow-next::before { transform: translate(-70%, -50%) rotate(45deg); }
.slider-arrow[disabled] { opacity: 0; pointer-events: none; }
/* initSliders() (main.js) flips which physical direction prev/next actually
   scroll toward in RTL, so the chevrons need to point the matching way too
   — swapped wholesale (not just the rotation) since the translate% each
   uses is tuned to its own rotation's visual center, not reusable across
   the two. */
[dir="rtl"] .slider-arrow-prev::before { transform: translate(-70%, -50%) rotate(45deg); }
[dir="rtl"] .slider-arrow-next::before { transform: translate(-30%, -50%) rotate(-135deg); }

/* Category bar reuses .slider-arrow/.slider-arrow-prev/-next (chevron shape,
   click-to-scroll JS, RTL mirroring, auto-hide at the scroll end via
   [disabled]) but the bar itself is much shorter than a product-card
   slider, so the button needs to be smaller and hug the edge rather than
   poke halfway outside a card. Two classes for specificity (0,2,0) over the
   plain .slider-arrow-prev/-next (0,1,0) — no !important needed. */
.category-bar-arrow {
	top: 50%;
	width: 26px; height: 26px;
}
.category-bar-arrow::before { width: 6px; height: 6px; }
.category-bar-arrow.slider-arrow-prev { inset-inline-start: 2px; }
.category-bar-arrow.slider-arrow-next { inset-inline-end: 2px; }

/* ---- Why Herbelo / value props ---- */
.value-band { background: var(--mist); border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
.value-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 32px; }
.value-item { display: flex; flex-direction: column; gap: 10px; }
.value-icon {
	width: 40px; height: 40px;
	border-radius: 10px;
	background: var(--paper);
	border: 1px solid var(--hairline);
	color: var(--leaf);
	display: flex;
	align-items: center;
	justify-content: center;
}
.value-item h3 { font-size: var(--fs-md); }
.value-item p { font-size: var(--fs-sm); color: var(--stone); margin: 0; line-height: 1.55; }

/* ---- Seasonal banner ---- */
/* Copy/link rotate automatically by month — see
   herbelo_homepage_seasonal_banner(), inc/homepage.php. A plain colored
   card rather than another image slide (like the hero above it): one
   static promotional strip doesn't need slider machinery, and the flat
   leaf-tinted background keeps it visually distinct from the hero photos
   and the plain white/mist sections around it. */
.seasonal-banner { margin: 40px auto 0; }
.seasonal-banner-inner {
	background: var(--leaf-wash);
	border: 1px solid var(--leaf);
	border-radius: var(--r-lg);
	padding: 32px;
	text-align: center;
}
.seasonal-banner-eyebrow {
	display: block;
	font-family: var(--mono);
	font-size: var(--fs-xs);
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--leaf-deep);
	margin-bottom: 8px;
}
.seasonal-banner-title { font-size: 1.5rem; letter-spacing: -.015em; margin-bottom: 8px; }
.seasonal-banner-text {
	max-width: 56ch;
	margin: 0 auto 18px;
	color: var(--stone);
	font-size: var(--fs-md);
	line-height: 1.55;
}
@media (max-width: 640px) {
	.seasonal-banner-inner { padding: 22px 18px; }
	.seasonal-banner-title { font-size: 1.25rem; }
}

/* ---- Brand strip ---- */
.brand-strip-eyebrow { text-align: center; margin-bottom: 22px; }
.brand-strip { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 16px 36px; }
.brand-strip a { font-weight: 700; font-size: 1rem; color: var(--stone); letter-spacing: -.01em; transition: color var(--t); }
.brand-strip a:hover { color: var(--ink); }

/* ---- Real customer reviews ---- */
.review-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.review-card { border: 1px solid var(--hairline); border-radius: var(--r-lg); padding: 22px; background: var(--paper); }
.review-card .star-rating { margin-bottom: 12px; }
.review-card p { font-size: var(--fs-md); color: var(--ink); margin: 0 0 16px; line-height: 1.6; }
.review-who { display: flex; align-items: center; gap: 10px; }
.review-avatar {
	width: 34px; height: 34px;
	border-radius: 50%;
	background: var(--leaf-wash);
	color: var(--leaf-deep);
	font-weight: 700;
	font-size: var(--fs-sm);
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}
.review-who b { display: block; font-size: var(--fs-base); }
.review-who span { font-size: var(--fs-xs); color: var(--stone); font-family: var(--mono); }
.review-product-link { color: var(--stone); text-decoration: underline; text-underline-offset: 2px; }
.review-product-link:hover { color: var(--leaf); }

@media (max-width: 1000px) {
	.cat-grid,
	.value-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.review-grid { grid-template-columns: minmax(0, 1fr); }
	.routine-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 680px) {
	.routine-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
	.routine-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 680px) {
	.hero-slider { min-height: 64vh; }
	.hero-slide-overlay {
		background: linear-gradient(180deg, rgba(16,26,19,.35) 0%, rgba(16,26,19,.78) 55%, rgba(16,26,19,.9) 100%);
		align-items: flex-end;
		padding-bottom: 56px;
	}
	.hero-slide-inner { max-width: none; }
	.hero-slider-arrow { display: none; }
	.cat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
	.cat-card { padding: 14px; }
	.sec { padding: 32px 0; }
	.sec-head { flex-direction: column; align-items: flex-start; gap: 8px; }
	.trust-bar-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 8px; padding: 18px 16px; }
	.trust-stat:nth-child(odd) { border-inline-start: 0; }
}

/* ==========================================================================
   Toast
   ========================================================================== */

.herbelo-toast {
	position: fixed;
	bottom: 22px; left: 50%;
	background: var(--ink);
	color: var(--paper);
	padding: 13px 18px;
	border-radius: var(--r);
	box-shadow: var(--shadow-lg);
	font-size: var(--fs-base);
	text-align: center;
	max-width: calc(100% - 32px);
	transform: translateX(-50%) translateY(18px);
	opacity: 0;
	pointer-events: none;
	transition: transform var(--t), opacity var(--t);
	z-index: var(--z-toast);
}
.herbelo-toast.is-visible { transform: translateX(-50%) translateY(0); opacity: 1; }

/* Desktop default: #order_review is already pinned in a sticky sidebar (see
   the grid rules on .woocommerce-checkout form.checkout below), so a second
   pinned total/button would just duplicate it. The mobile media query below
   turns this back on with display:flex. */
.checkout-sticky-cta { display: none; }

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1024px) {
	/* Single column: gallery, then summary, then everything else */
	.woocommerce div.product {
		grid-template-columns: minmax(0, 1fr);
		row-gap: 24px;
	}
	.woocommerce div.product > .woocommerce-product-gallery { grid-column: 1; grid-row: 1; }
	.woocommerce div.product > .summary,
	.woocommerce div.product > .entry-summary { grid-column: 1; grid-row: 2; }
	.woocommerce div.product > .product-delivery-info { grid-column: 1; grid-row: 3; }
	.woocommerce div.product .woocommerce-product-gallery { position: static; }

	.woocommerce-checkout form.checkout { grid-template-columns: minmax(0, 1fr); }
	.woocommerce-checkout #order_review_heading,
	.woocommerce-checkout #order_review {
		grid-column: 1;
		grid-row: auto;
		position: static;
	}
	/* The 40px margin-top and 15px padding set above are both desktop-only:
	   the margin only exists to clear the heading while both share
	   grid-row:1 on desktop, and on mobile they're back in normal document
	   flow (stacked in source order via grid-row:auto) so that offset would
	   just be extra dead space — cancel it. Padding reverts to the tighter
	   size mobile already had, per request. */
	.woocommerce-checkout #order_review { margin-top: 0; padding: 5px 2px 2px; }

	.checkout-mobile-summary {
		display: block;
		border: 0;
		border-radius: var(--r-lg);
		background: var(--mist);
		box-shadow: var(--shadow);
		margin-bottom: 16px;
	}
	.checkout-mobile-summary summary {
		display: grid;
		grid-template-columns: 1fr auto 12px;
		align-items: center;
		gap: 10px;
		padding: 2px;
		font-weight: 700;
		font-size: var(--fs-md);
		cursor: pointer;
		list-style: none;
	}
	.checkout-mobile-summary summary::-webkit-details-marker { display: none; }
	.checkout-mobile-summary summary::after {
		content: "";
		width: 10px; height: 10px;
		border-right: 1.6px solid var(--stone);
		border-bottom: 1.6px solid var(--stone);
		transform: rotate(45deg);
		transition: transform var(--t);
	}
	.checkout-mobile-summary[open] summary::after { transform: rotate(-135deg); }
	.checkout-mobile-summary-total { font-family: var(--mono); font-size: 1.05rem; color: var(--leaf-deep); }
	.checkout-mobile-summary-items {
		display: grid;
		gap: 10px;
		margin: 0;
		padding: 2px;
		border-top: 1px solid var(--hairline);
	}
	.checkout-mobile-summary-items li {
		display: flex;
		align-items: center;
		gap: 10px;
		font-size: var(--fs-sm);
	}
	.checkout-mobile-summary-item-thumb {
		width: 34px; height: 34px;
		object-fit: contain;
		background: var(--paper);
		border: 1px solid var(--hairline);
		border-radius: var(--r);
		padding: 2px;
		flex-shrink: 0;
	}
	.checkout-mobile-summary-item-name { flex: 1 1 auto; min-width: 0; }
	.checkout-mobile-summary-item-qty { color: var(--stone); margin-inline-start: 3px; }
	.checkout-mobile-summary-item-price { font-family: var(--mono); flex-shrink: 0; }

	/* Full-width product grid; filters move into the drawer below instead
	   of taking a grid row of their own. */
	.shop-layout { grid-template-columns: minmax(0, 1fr); gap: 32px; }
	.shop-layout > .site-main { grid-column: 1; grid-row: 1; }
	.shop-layout ul.products,
	.related ul.products,
	.upsells ul.products { grid-template-columns: repeat(3, minmax(0, 1fr)); }

	.footer-columns { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	/* Filters become a bottom-sheet drawer instead of a full-width block
	   dumped below every product — reachable from a floating button
	   without scrolling past the whole grid first. */
	.shop-filters-toggle {
		display: flex;
		align-items: center;
		gap: 7px;
		position: fixed;
		left: 50%;
		bottom: max(18px, env(safe-area-inset-bottom));
		transform: translateX(-50%);
		/* Below --z-drawer (mini-cart-drawer/shop-filters panel use it): this
		   is a page-level floating button, not a drawer, so an actually-open
		   drawer must paint over it instead of sharing its tier and winning
		   on source order — confirmed live, the mini-cart drawer left this
		   pill floating on top of it when opened from the shop page. */
		z-index: var(--z-header);
		background: var(--ink);
		color: var(--paper);
		border: 0;
		border-radius: 999px;
		padding: 12px 22px;
		font-size: var(--fs-sm);
		font-weight: 700;
		box-shadow: var(--shadow-lg);
		cursor: pointer;
	}
	/* Confirmed live: with the shop-filters drawer itself open, its z-index
	   (--z-drawer) sits above this button's own --z-header tier — same
	   ordering the comment above exists for, but that was tuned for the
	   MINI-CART drawer covering this pill, not the filters drawer hiding
	   it from itself. The open filter drawer's bottom edge lands flush
	   with the viewport bottom, fully covering the pill underneath it —
	   so the spinner swap above never actually got seen while filtering
	   from inside the drawer, the one place it matters most. Scoped to
	   aria-expanded (already toggled by the existing JS open/close
	   handlers, no new JS needed) rather than raising the button's tier
	   generally, so the mini-cart drawer still covers it as intended. */
	.shop-filters-toggle[aria-expanded="true"] {
		z-index: calc(var(--z-drawer) + 1);
	}
	.shop-filters-toggle-icon {
		width: 14px; height: 14px;
		background-color: currentColor;
		-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 5h14M6 10h8M9 15h2' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
		mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M3 5h14M6 10h8M9 15h2' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
		-webkit-mask-size: contain;
		mask-size: contain;
		-webkit-mask-repeat: no-repeat;
		mask-repeat: no-repeat;
	}
	/* Filtering is AJAX (main.js loadUrl()) and swaps the skeleton grid in
	   behind this drawer while it's open — invisible to whoever just tapped
	   a checkbox, since the drawer covers the grid the whole time. This
	   floating pill stays on screen regardless of drawer state (position:
	   fixed, above the drawer's own content but still visible past its
	   edge), so swapping its icon for a spinner here is the one loading
	   indicator guaranteed to actually be seen on a tap. */
	.shop-filters-toggle-spinner {
		display: none;
		width: 14px; height: 14px;
		flex-shrink: 0;
		border: 2px solid rgba(255, 255, 255, .35);
		border-top-color: var(--paper);
		border-radius: 50%;
		animation: herbelo-spin .6s linear infinite;
	}
	.shop-layout.is-loading .shop-filters-toggle-icon { display: none; }
	.shop-layout.is-loading .shop-filters-toggle-spinner { display: block; }
	@keyframes herbelo-spin {
		to { transform: rotate(360deg); }
	}

	.shop-layout > #secondary { display: contents; }
	.shop-filters {
		position: fixed;
		inset: auto 0 0 0;
		max-height: 85vh;
		overflow-y: auto;
		border: 0;
		border-radius: 16px 16px 0 0;
		box-shadow: var(--shadow-lg);
		padding: 18px 18px max(18px, env(safe-area-inset-bottom));
		transform: translateY(100%);
		transition: transform var(--t-slow);
		z-index: var(--z-drawer);
	}
	.shop-filters.is-open { transform: translateY(0); }

	.shop-filters-panel-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin-bottom: 14px;
		padding-bottom: 12px;
		border-bottom: 1px solid var(--hairline);
	}
	.shop-filters-panel-title { margin: 0; font-size: 1.05rem; }
	.shop-filters-close {
		background: transparent;
		border: 0;
		color: var(--stone);
		font-size: 1.5rem;
		line-height: 1;
		padding: 2px 6px;
		cursor: pointer;
	}
	.shop-filters-close:hover { background: transparent; color: var(--ink); }

	/* Pinned Total + Commander bar: the address form is long enough that the
	   real place-order button (in #order_review, below the whole form) is
	   often a full screen or more of scrolling away. This proxies a click to
	   that real button — see herbelo_checkout_sticky_cta() — so there's no
	   second submit path to keep in sync, just a shortcut to the existing one. */
	body.woocommerce-checkout { padding-bottom: 82px; }
	.checkout-sticky-cta {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 14px;
		position: fixed;
		inset-inline: 0; bottom: 0;
		z-index: var(--z-drawer);
		background: var(--paper);
		border-top: 1px solid var(--hairline);
		box-shadow: var(--shadow-lg);
		padding: 12px 16px max(12px, env(safe-area-inset-bottom));
	}
	.checkout-sticky-cta-total { display: flex; flex-direction: column; line-height: 1.25; }
	.checkout-sticky-cta-total-label {
		font-size: var(--fs-xs);
		color: var(--stone);
		text-transform: uppercase;
		letter-spacing: .06em;
	}
	.checkout-sticky-cta-total-amount { font-family: var(--mono); font-weight: 700; font-size: 1.15rem; color: var(--leaf-deep); }
	.checkout-sticky-cta-button {
		flex-shrink: 0;
		background: var(--leaf);
		color: var(--paper);
		border: 0;
		border-radius: var(--r);
		padding: 14px 28px;
		font-weight: 700;
		font-size: var(--fs-md);
		cursor: pointer;
	}
	.checkout-sticky-cta-button:hover,
	.checkout-sticky-cta-button:active { background: var(--leaf-deep); }
}

@media (max-width: 900px) {
	ul.products,
	.shop-layout ul.products,
	.related ul.products,
	.upsells ul.products { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.post-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.woocommerce-MyAccount-content .woocommerce-Addresses { grid-template-columns: minmax(0, 1fr); }
	.woocommerce-cart .cart-collaterals { max-width: none; }
	/* Same reasoning as #order_review's own mobile padding override: less
	   padding here means more width left over for the shipping method row's
	   label — at 20px a side, "Livraison a domicile" (flexing against the
	   nowrap price next to it) didn't have room to stay on one or two
	   sensible lines and wrapped almost one word per line instead. */
	.woocommerce-cart .cart_totals { padding: 14px; }
	.woocommerce-cart ul#shipping_method li { padding: 10px; }

	/* Not enough width for logo + nav + a persistent search bar + icons on
	   one line — let the header wrap, with the search bar forced onto its
	   own full-width row below the logo/nav/icons instead of being hidden. */
	.header-inner { flex-wrap: wrap; }
	.header-search-bar { flex-basis: 100%; order: 10; margin: 4px 0 0; }
}

@media (max-width: 680px) {
	.shell,
	.header-inner,
	.footer-inner,
	.footer-newsletter-inner,
	.site-main,
	.post-grid,
	.archive-header,
	.shop-layout,
	.woocommerce-products-header,
	.entry-content,
	.entry-header { padding-inline: 16px; }

	/* Checkout: .site-main and .entry-content are nested (main > article >
	   entry-content), so the two 16px rules above stack into a 32px inset on
	   each side. Collapsing that to a single 3% inset here (scoped to the
	   checkout body class, so no other page is affected) matches what was
	   asked for without touching the shared site-wide rule above. */
	body.woocommerce-checkout .site-main { padding-inline: 3%; }
	body.woocommerce-checkout .entry-content { padding-inline: 0; }
	/* Same nested-double-padding stacking as checkout above, same fix — cart
	   asked for a 5px inset specifically, rather than checkout's 5%. */
	body.woocommerce-cart .site-main { padding-inline: 5px; }
	body.woocommerce-cart .entry-content { padding-inline: 0; }
	/* Home page — same 5px inset as cart, requested separately. No nested
	   .entry-content here (front-page.php's .site-main has no article/
	   entry-content wrapper), so a single override is enough. */
	.site-main.front-page { padding-inline: 5px; }

	.menu-toggle { display: block; order: -1; }
	.header-inner { gap: 8px; flex-wrap: wrap; }
	.category-bar-list { padding: 0 16px; }
	.site-branding img { width: 110px; height: auto; }

	/* Logo + cart link + secure badge don't all fit one line on a phone —
	   the secure badge is reassurance, not navigation, so its label is the
	   one to drop first; the lock icon alone still reads fine. */
	.checkout-header-secure-text { display: none; }

	.main-navigation {
		position: fixed;
		top: 0; inset-inline-start: 0; bottom: 0;
		width: 84%;
		max-width: 320px;
		background: var(--paper);
		z-index: var(--z-drawer);
		transform: translateX(-100%);
		transition: transform var(--t-slow);
		padding: 20px 20px max(20px, env(safe-area-inset-bottom));
		overflow-y: auto;
		display: block;
	}
	.main-navigation.is-open { transform: translateX(0); }
	/* Same translateX-has-no-logical-equivalent issue as the mini-cart
	   drawer (see that rule for the full explanation) — inset-inline-start:0
	   above anchors this to the right edge in RTL, so hiding it needs a
	   push to the right (+100%) instead of this rule's left-edge -100%. */
	[dir="rtl"] .main-navigation { transform: translateX(100%); }
	[dir="rtl"] .main-navigation.is-open { transform: translateX(0); }
	.main-navigation > ul { flex-direction: column; gap: 0; }
	.main-navigation ul ul { display: block; padding-inline-start: 14px; }
	.main-navigation a {
		display: block;
		padding: 12px 0;
		border-bottom: 1px solid var(--hairline);
	}

	.header-icon-button { width: 42px; height: 42px; }

	/* Cart/checkout tables: scroll the table, not the page — except the cart
	   item table itself, which is already a stack of cards (see .cart_item
	   grid rules above) and needs none of this. Also excludes .cart_totals's
	   table below: unlike a genuinely wide data table (order history, with
	   many columns), it's a simple 2-column label/value summary that should
	   just wrap, not scroll — display:block + overflow-x:auto here was
	   sizing its row to its content's preferred (unwrapped) width and
	   scrolling the rest off to the right, silently, with no visible
	   scrollbar hint in a plain screenshot. */
	.woocommerce table.shop_table:not(.cart) {
		display: block;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
	}
	.woocommerce-cart .cart_totals table.shop_table_responsive {
		display: table;
		overflow-x: visible;
	}
	.woocommerce-cart .cart_totals table.shop_table_responsive th,
	.woocommerce-cart .cart_totals table.shop_table_responsive td {
		white-space: normal;
	}
	.woocommerce table.shop_table:not(.cart) th,
	.woocommerce table.shop_table:not(.cart) td { padding: 11px; white-space: nowrap; }
	.woocommerce table.shop_table td.product-name,
	.woocommerce table.shop_table td.product-subtotal { white-space: normal; }
	.woocommerce table.shop_table:not(.cart) td.product-thumbnail img { width: 46px; }
	.woocommerce-cart table.cart tr.cart_item {
		grid-template-columns: 64px minmax(0, 1fr) auto;
		column-gap: 12px;
		padding: 12px;
	}
	.woocommerce-cart table.cart td.product-thumbnail img { width: 64px; height: 64px; }
	.woocommerce-checkout table.shop_table { display: table; }
	.woocommerce-checkout table.shop_table th,
	.woocommerce-checkout table.shop_table td { white-space: normal; }

	/* Touch targets */
	.quantity .qty,
	.quantity select { min-height: 44px; }
	.quantity-stepper-button { width: 42px; }
	.woocommerce form .form-row input[type="radio"],
	.woocommerce form .form-row input[type="checkbox"],
	.woocommerce-checkout form.checkout input[type="radio"],
	.woocommerce-checkout form.checkout input[type="checkbox"] { width: 20px; height: 20px; }
	.woocommerce-checkout .payment_methods li { padding: 11px 12px; }

	/* Arrows can't rely on hover on touch devices */
	.woocommerce div.product .flex-direction-nav a { opacity: 1; }
	.woocommerce div.product .woocommerce-product-gallery { padding: 14px; }

	/* Toolbar stacks */
	.shop-layout .woocommerce-result-count,
	.shop-layout .woocommerce-ordering {
		float: none;
		display: block;
		line-height: 1.5;
	}
	.shop-layout .woocommerce-ordering { margin-top: 10px; }
	.woocommerce-ordering select, select.orderby { width: 100%; }

	ul.products,
	.shop-layout ul.products,
	.related ul.products,
	.upsells ul.products { gap: 12px; }
	.post-grid { grid-template-columns: minmax(0, 1fr); }

	.woocommerce div.product .summary .product_title { font-size: 1.15rem; }
	.woocommerce div.product p.price { font-size: 1.42rem; }

	.woocommerce-account .u-columns.col2-set { grid-template-columns: minmax(0, 1fr); gap: 18px; }
	.woocommerce-account .u-columns.col2-set .col-1,
	.woocommerce-account .u-columns.col2-set .col-2 { padding: 18px; }
	.woocommerce-account.logged-in .woocommerce { grid-template-columns: minmax(0, 1fr); }
	.woocommerce-account.logged-in .woocommerce > *,
	.woocommerce-account.logged-in .woocommerce > .woocommerce-MyAccount-navigation { grid-column: 1; }
	.woocommerce-MyAccount-navigation ul { flex-direction: row; flex-wrap: wrap; }
	.woocommerce-MyAccount-navigation li { border-bottom: 0; border-inline-end: 1px solid var(--hairline); }

	.page-numbers { min-width: 36px; height: 36px; padding: 0 9px; }

	/* start/end (not center): reads as left in French, right in Arabic —
	   these are logical values, so this one rule set covers both
	   directions without a separate [dir="rtl"] override. */
	.footer-columns { grid-template-columns: minmax(0, 1fr); gap: 28px; text-align: start; }
	.footer-social { justify-content: flex-start; }
	.footer-column ul { justify-items: start; }
	.payment-icons { justify-content: flex-start; }
	.footer-newsletter-inner { flex-direction: column; text-align: start; }
	.newsletter-form { justify-content: flex-start; width: 100%; }
	.newsletter-form input[type="email"] { flex: 1; min-width: 0; }

	.hero { padding: 40px 20px; }
	.section-title { margin: 34px 0 16px; }

	.sticky-add-to-cart { padding-bottom: max(10px, env(safe-area-inset-bottom)); }
	.sticky-add-to-cart-details { max-width: 42vw; }
	.herbelo-toast { bottom: 16px; max-width: calc(100% - 32px); }
}

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		transition-duration: .01ms !important;
		animation-duration: .01ms !important;
	}
	html { scroll-behavior: auto; }
}
