/*
Theme Name: Aflora Natural
Theme URI:
Description: Child theme of Storefront for Aflora Natural.
Author: Aflora Natural
Template: storefront
Version: 4.8.0
Text Domain: beauty-storefront
*/

/* ==========================================================================
   SECTION INDEX
   0.  Design tokens
   1.  Base and layout
   2.  Buttons and forms
   3.  Announcement bar
   4.  Header
   5.  Section shell
   6.  Homepage — hero
   7.  Homepage — trust bar
   8.  Homepage — categories
   9.  Product cards
   10. Carousels and sliders
   11. Shop and archive pages
   12. Single product
   13. Newsletter
   14. Sticky mobile buy bar
   15. Cart
   16. Checkout and account
   17. Footer
   18. Utilities and accessibility
   19. Conversion / AOV components  [NEW in 4.0.0]
   21. Buy-box purchase options and cart drawer   [v4.1.0]
   22. Product page, decluttered                  [v4.2.0]
   23. Product page repairs                       [4.3.0]
   24. Product page repairs, round two            [NEW in 4.4.0]
       24.1 stars amber, not WooCommerce purple
       24.2 gallery and title start on the same line
       24.3 the gallery actually pins
       24.4 the ritual set, inside the ritual box
   25. Quantity stepper beside Add to cart        [NEW in 4.5.0]
   26. Product card: rating and price block       [NEW in 4.7.0]
       26.1 one meta block, one rhythm
       26.2 stars and review count, side by side
       26.3 price — now first, was second
       26.4 price per 100g
       26.5 narrow screens
   27. Product card: one column, one rhythm       [NEW in 4.8.0]
       27.1 --bs-card-title-lines
       27.2 title
       27.3 meta block gaps
       27.4 price and /100g on one line
       27.5 one left edge for the whole card
       27.6 the grid itself
       27.7 narrow screens
   ========================================================================== */


/* ==========================================================================
   0. Design tokens
   Change colours, radii and spacing here. Nothing below hard-codes a colour.
   ========================================================================== */

:root {
	/* --- Colour ----------------------------------------------------- */
	--bs-bg:            #f5f7f2;   /* page — pale leaf white */
	--bs-surface:       #ffffff;   /* cards, panels, image boxes */
	--bs-surface-sunk:  #eef2ea;   /* quiet fills */
	--bs-ink:           #14201a;   /* headings and body */
	--bs-ink-soft:      #55645b;   /* secondary text */
	--bs-line:          #dde4d9;   /* hairlines and borders */

	--bs-accent:        #2b6b45;   /* brand green — links, active states */
	--bs-accent-dark:   #1c4a2f;
	--bs-accent-tint:   #e6efe7;

	--bs-cta:           #2b6b45;   /* buttons */
	--bs-cta-dark:      #1c4a2f;
	--bs-cta-text:      #ffffff;

	/* Second button colour, used where a green button would disappear into
	   a green panel — currently only the newsletter subscribe button. */
	--bs-cta-warm:      #b35c33;
	--bs-cta-warm-dark: #8f4726;

	--bs-amber:         #9a5715;   /* sale badge, sale price — the one warm note */
	--bs-amber-tint:    #f7ecdf;

	--bs-success:       #2b6b45;
	--bs-error:         #a32a20;

	/* --- Radius ------------------------------------------------------ */
	--bs-radius-sm:     10px;
	--bs-radius:        14px;
	--bs-radius-lg:     20px;
	--bs-radius-xl:     28px;
	--bs-radius-button: 999px;     /* set to 14px if you prefer square-ish buttons */

	/* --- Type -------------------------------------------------------- */
	--bs-font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
	                "Helvetica Neue", Arial, "Noto Sans", "Noto Sans Arabic", sans-serif;
	--bs-font-head: var(--bs-font-body);

	--bs-text-xs:    0.75rem;
	--bs-text-sm:    0.875rem;
	--bs-text-base:  1rem;
	--bs-text-lg:    1.125rem;
	--bs-text-xl:    1.375rem;
	--bs-text-2xl:   1.75rem;
	--bs-text-3xl:   2.25rem;
	--bs-text-4xl:   3rem;

	--bs-weight-normal: 400;
	--bs-weight-medium: 500;
	--bs-weight-bold:   700;

	--bs-leading-tight: 1.15;
	--bs-leading-body:  1.6;
	--bs-tracking-tight: -0.02em;

	/* --- Space ------------------------------------------------------- */
	--bs-space-1:  0.25rem;
	--bs-space-2:  0.5rem;
	--bs-space-3:  0.75rem;
	--bs-space-4:  1rem;
	--bs-space-5:  1.25rem;
	--bs-space-6:  1.5rem;
	--bs-space-8:  2rem;
	--bs-space-10: 2.5rem;
	--bs-space-12: 3rem;
	--bs-space-16: 4rem;
	--bs-space-20: 5rem;

	/* --- Layout ------------------------------------------------------ */
	--bs-container:      1280px;
	--bs-container-text: 68ch;
	--bs-gutter:         1.25rem;
	--bs-section-y:      var(--bs-space-16);
	--bs-header-h:       72px;

	/* --- Depth and motion -------------------------------------------- */
	--bs-shadow:    0 1px 2px rgba(20, 32, 26, 0.04), 0 6px 20px rgba(20, 32, 26, 0.06);
	--bs-shadow-lg: 0 8px 40px rgba(20, 32, 26, 0.12);
	--bs-duration:  180ms;
	--bs-ease:      cubic-bezier(0.2, 0, 0.2, 1);
}

@media (min-width: 768px) {
	:root {
		--bs-gutter:    2rem;
		--bs-section-y: var(--bs-space-20);
		--bs-header-h:  84px;
	}
}


/* ==========================================================================
   1. Base and layout
   ========================================================================== */

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

body {
	background-color: var(--bs-bg);
	color: var(--bs-ink);
	font-family: var(--bs-font-body);
	font-size: var(--bs-text-base);
	line-height: var(--bs-leading-body);
	-webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4,
.entry-title,
.section-title {
	font-family: var(--bs-font-head);
	color: var(--bs-ink);
	font-weight: var(--bs-weight-bold);
	line-height: var(--bs-leading-tight);
	letter-spacing: var(--bs-tracking-tight);
}

a {
	color: var(--bs-accent);
	text-decoration: none;
	transition: color var(--bs-duration) var(--bs-ease);
}

a:hover {
	color: var(--bs-accent-dark);
}

p {
	max-width: var(--bs-container-text);
}

hr {
	border: 0;
	border-top: 1px solid var(--bs-line);
	margin: var(--bs-space-12) 0;
}

/* One container width for the whole site. */
.col-full,
.bs-container {
	max-width: var(--bs-container);
	margin-left: auto;
	margin-right: auto;
	padding-left: var(--bs-gutter);
	padding-right: var(--bs-gutter);
	width: 100%;
}

/* Sidebars are off on the shop, cart, checkout, account and homepage. */
.bs-full-width .content-area,
.bs-full-width #primary {
	width: 100%;
	float: none;
	margin: 0;
}

.bs-full-width #secondary,
.bs-full-width .widget-area {
	display: none;
}

/* The hero carries the page title on the homepage. */
.home .entry-title,
.page-template-template-homepage .entry-title {
	display: none;
}

.site-content {
	padding-top: var(--bs-space-8);
	padding-bottom: var(--bs-space-16);
}


/* ==========================================================================
   2. Buttons and forms
   ========================================================================== */

.button,
button,
input[type="submit"],
.woocommerce #respond input#submit,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--bs-space-2);
	background-color: var(--bs-cta);
	color: var(--bs-cta-text);
	font-family: inherit;
	font-size: var(--bs-text-base);
	font-weight: var(--bs-weight-medium);
	line-height: 1.2;
	letter-spacing: 0;
	text-align: center;
	border: 1px solid transparent;
	border-radius: var(--bs-radius-button);
	padding: 0.8em 1.6em;
	min-height: 44px;
	cursor: pointer;
	text-shadow: none;
	transition: background-color var(--bs-duration) var(--bs-ease),
	            border-color var(--bs-duration) var(--bs-ease),
	            color var(--bs-duration) var(--bs-ease);
}

.button:hover,
button:hover,
input[type="submit"]:hover,
.woocommerce #respond input#submit:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover {
	background-color: var(--bs-cta-dark);
	color: var(--bs-cta-text);
}

.woocommerce a.button.alt,
.woocommerce button.button.alt,
.woocommerce input.button.alt {
	background-color: var(--bs-cta);
	color: var(--bs-cta-text);
}

.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover {
	background-color: var(--bs-cta-dark);
}

/* Outline button — "Load more", "Update cart", "Continue shopping". */
.bs-button--quiet,
.woocommerce .button.bs-button--quiet,
.woocommerce button.button[name="update_cart"],
.woocommerce a.button.wc-backward {
	background-color: transparent;
	color: var(--bs-ink);
	border-color: var(--bs-line);
}

.bs-button--quiet:hover,
.woocommerce .button.bs-button--quiet:hover,
.woocommerce button.button[name="update_cart"]:hover,
.woocommerce a.button.wc-backward:hover {
	background-color: var(--bs-surface);
	border-color: var(--bs-accent);
	color: var(--bs-accent-dark);
}

button:disabled,
.button:disabled,
.woocommerce button.button:disabled {
	opacity: 0.45;
	cursor: not-allowed;
}

input[type="text"],
input[type="email"],
input[type="tel"],
input[type="url"],
input[type="password"],
input[type="search"],
input[type="number"],
input[type="date"],
textarea,
select,
.select2-container .select2-selection--single {
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-sm);
	color: var(--bs-ink);
	font-family: var(--bs-font-body);
	font-size: var(--bs-text-base);
	line-height: 1.4;
	padding: 0.7rem 0.9rem;
	min-height: 44px;
	box-shadow: none;
	width: 100%;
}

input:focus,
textarea:focus,
select:focus {
	border-color: var(--bs-accent);
	outline: none;
	box-shadow: 0 0 0 3px var(--bs-accent-tint);
}

label {
	display: block;
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	color: var(--bs-ink);
	margin-bottom: var(--bs-space-1);
}

.bs-icon {
	flex: none;
	width: 1.25em;
	height: 1.25em;
}


/* ==========================================================================
   3. Announcement bar
   ========================================================================== */

.bs-announce {
	background-color: var(--bs-accent-dark);
	color: #fff;
	font-size: var(--bs-text-sm);
	text-align: center;
}

.bs-announce__inner {
	max-width: var(--bs-container);
	margin: 0 auto;
	padding: 0.6rem var(--bs-gutter);
}

.bs-announce a {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 2px;
}


/* ==========================================================================
   4. Header — one sticky row: logo, menu, search icon, cart
   ========================================================================== */

.site-header {
	position: sticky;
	top: 0;
	z-index: 500;
	background-color: var(--bs-bg);
	border-bottom: 1px solid var(--bs-line);
	padding: 0;
	margin: 0;
	transition: box-shadow var(--bs-duration) var(--bs-ease);
}

.admin-bar .site-header {
	top: 32px;
}

@media (max-width: 782px) {
	.admin-bar .site-header {
		top: 46px;
	}
}

.site-header .bs-header.is-stuck {
	box-shadow: var(--bs-shadow);
}

.bs-header {
	background-color: var(--bs-bg);
	position: relative;
}

.bs-header__inner {
	max-width: var(--bs-container);
	margin: 0 auto;
	padding: 0 var(--bs-gutter);
	min-height: var(--bs-header-h);
	display: flex;
	align-items: center;
	gap: var(--bs-space-4);
}

/* --- Brand ---------------------------------------------------------- */

.bs-header__brand {
	display: flex;
	align-items: center;
	flex: none;
	margin: 0;
}

.bs-header__brand .custom-logo-link,
.bs-header__brand a {
	display: block;
	line-height: 0;
}

.bs-header__brand img,
.bs-header__brand .custom-logo {
	width: auto;
	max-width: 190px;
	max-height: 46px;
	height: auto;
	object-fit: contain;
	display: block;
}

.bs-brand__text {
	font-family: var(--bs-font-head);
	font-size: var(--bs-text-lg);
	font-weight: var(--bs-weight-bold);
	letter-spacing: var(--bs-tracking-tight);
	color: var(--bs-ink);
	line-height: 1.2;
}

/* --- Menu -----------------------------------------------------------
   Product categories are spelled out as their own items rather than
   hidden behind a "Categories" dropdown, so the row can get long. It
   scrolls sideways rather than wrapping onto a second line.           */

.bs-header__nav {
	flex: 1 1 auto;
	display: none;
	min-width: 0;
}

@media (min-width: 992px) {
	.bs-header__nav {
		display: block;
	}
}

.bs-menu {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: nowrap;
	gap: var(--bs-space-1);
	list-style: none;
	margin: 0;
	padding: 0;
	overflow-x: auto;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.bs-menu::-webkit-scrollbar {
	display: none;
}

.bs-menu li {
	position: relative;
	margin: 0;
	list-style: none;
	flex: none;
}

.bs-menu > li > a {
	display: block;
	color: var(--bs-ink);
	font-size: var(--bs-text-base);
	font-weight: var(--bs-weight-medium);
	padding: 0.55rem 0.9rem;
	border-radius: var(--bs-radius-button);
	white-space: nowrap;
	transition: background-color var(--bs-duration) var(--bs-ease),
	            color var(--bs-duration) var(--bs-ease);
}

.bs-menu > li > a:hover,
.bs-menu > li.current-menu-item > a,
.bs-menu > li.current-menu-parent > a,
.bs-menu > li.current-menu-ancestor > a {
	background-color: var(--bs-accent-tint);
	color: var(--bs-accent-dark);
}

/* Category items sit slightly quieter than Home and Shop. */
.bs-menu > li.bs-menu-cat > a {
	font-weight: var(--bs-weight-normal);
	color: var(--bs-ink-soft);
}

.bs-menu > li.bs-menu-cat > a:hover,
.bs-menu > li.bs-menu-cat.current-menu-item > a {
	color: var(--bs-accent-dark);
}

/* Dropdowns — still supported for any menu the admin nests by hand. */
.bs-menu .sub-menu {
	position: absolute;
	top: calc(100% + 8px);
	left: 0;
	min-width: 220px;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius);
	box-shadow: var(--bs-shadow);
	padding: var(--bs-space-2);
	margin: 0;
	list-style: none;
	opacity: 0;
	visibility: hidden;
	transform: translateY(-4px);
	transition: opacity var(--bs-duration) var(--bs-ease),
	            transform var(--bs-duration) var(--bs-ease);
	z-index: 10;
}

.bs-menu li:hover > .sub-menu,
.bs-menu li:focus-within > .sub-menu {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}

.bs-menu .sub-menu a {
	display: block;
	padding: 0.5rem 0.75rem;
	border-radius: var(--bs-radius-sm);
	color: var(--bs-ink);
	font-size: var(--bs-text-sm);
}

.bs-menu .sub-menu a:hover {
	background-color: var(--bs-surface-sunk);
	color: var(--bs-accent-dark);
}

/* --- Right-hand actions --------------------------------------------- */

.bs-header__actions {
	flex: none;
	display: flex;
	align-items: center;
	gap: var(--bs-space-1);
	margin-left: auto;
}

.bs-icon-button {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	min-height: 0;
	padding: 0;
	background-color: transparent;
	color: var(--bs-ink);
	border: 0;
	border-radius: var(--bs-radius-button);
	cursor: pointer;
}

.bs-icon-button:hover,
.woocommerce .bs-icon-button:hover {
	background-color: var(--bs-accent-tint);
	color: var(--bs-accent-dark);
}

.bs-icon-button .bs-icon,
.bs-icon-button svg {
	width: 22px;
	height: 22px;
}

/* --- Cart link: icon, count badge and running total ------------------ */

.bs-cart-link {
	display: inline-flex;
	align-items: center;
	gap: var(--bs-space-2);
	height: 44px;
	padding: 0 var(--bs-space-3) 0 var(--bs-space-2);
	color: var(--bs-ink);
	border-radius: var(--bs-radius-button);
}

.bs-cart-link:hover {
	background-color: var(--bs-accent-tint);
	color: var(--bs-accent-dark);
}

.bs-cart-link__icon-wrap {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	flex: none;
}

.bs-cart-link__icon-wrap .bs-icon {
	width: 22px;
	height: 22px;
}

.bs-cart-link__count {
	position: absolute;
	top: 0;
	right: -2px;
	min-width: 19px;
	height: 19px;
	padding: 0 5px;
	border-radius: 999px;
	background-color: var(--bs-amber);
	color: #fff;
	font-size: 0.6875rem;
	font-weight: var(--bs-weight-bold);
	line-height: 19px;
	text-align: center;
}

.bs-cart-link__total {
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	white-space: nowrap;
}

.bs-cart-link__total .woocommerce-Price-amount {
	color: inherit;
}

@media (max-width: 480px) {
	.bs-cart-link__total {
		display: none;
	}

	.bs-cart-link {
		padding-right: var(--bs-space-1);
	}
}

.bs-nav-toggle {
	display: inline-flex;
	margin-right: calc(var(--bs-space-1) * -1);
}

@media (min-width: 992px) {
	.bs-nav-toggle {
		display: none;
	}
}

/* --- Search panel --------------------------------------------------- */

.bs-search-panel {
	border-top: 1px solid var(--bs-line);
	background-color: var(--bs-surface);
}

.bs-search-panel[hidden] {
	display: none;
}

.bs-search-panel__inner {
	max-width: 720px;
	margin: 0 auto;
	padding: var(--bs-space-4) var(--bs-gutter);
}

.bs-search-panel form,
.bs-search-panel .woocommerce-product-search,
.bs-search-panel .search-form {
	display: flex;
	gap: var(--bs-space-2);
	align-items: stretch;
	margin: 0;
}

.bs-search-panel input[type="search"],
.bs-search-panel .search-field {
	flex: 1 1 auto;
	border-radius: var(--bs-radius-button);
	padding-left: 1.1rem;
}

.bs-search-panel button,
.bs-search-panel input[type="submit"] {
	flex: none;
}

/* --- Mobile menu ---------------------------------------------------- */

.bs-mobile-nav {
	border-top: 1px solid var(--bs-line);
	background-color: var(--bs-surface);
	max-height: calc(100vh - var(--bs-header-h) - 60px);
	overflow-y: auto;
}

.bs-mobile-nav[hidden] {
	display: none;
}

.bs-mobile-nav__inner {
	max-width: var(--bs-container);
	margin: 0 auto;
	padding: var(--bs-space-4) var(--bs-gutter) var(--bs-space-6);
}

.bs-mobile-menu,
.bs-mobile-menu .sub-menu {
	list-style: none;
	margin: 0;
	padding: 0;
}

.bs-mobile-menu li {
	list-style: none;
	margin: 0;
}

.bs-mobile-menu a {
	display: block;
	padding: 0.85rem 0.25rem;
	color: var(--bs-ink);
	font-size: var(--bs-text-lg);
	font-weight: var(--bs-weight-medium);
	border-bottom: 1px solid var(--bs-line);
}

.bs-mobile-menu .sub-menu a {
	font-size: var(--bs-text-base);
	font-weight: var(--bs-weight-normal);
	padding-left: var(--bs-space-4);
	color: var(--bs-ink-soft);
}

.bs-mobile-nav__cta {
	width: 100%;
	margin-top: var(--bs-space-5);
}

body.bs-nav-open {
	overflow: hidden;
}

/* Breadcrumbs */
.woocommerce-breadcrumb {
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
	margin: 0 0 var(--bs-space-8);
}

.woocommerce-breadcrumb a {
	color: var(--bs-ink-soft);
}

.woocommerce-breadcrumb a:hover {
	color: var(--bs-accent);
}


/* ==========================================================================
   5. Section shell
   ========================================================================== */

.bs-section {
	margin-bottom: var(--bs-section-y);
}

.bs-section:last-child {
	margin-bottom: 0;
}

.bs-section__head {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--bs-space-3) var(--bs-space-6);
	margin-bottom: var(--bs-space-6);
}

.bs-section__headings {
	min-width: 0;
	flex: 1 1 260px;
}

.bs-section__title {
	font-size: var(--bs-text-2xl);
	margin: 0;
}

.bs-section__sub {
	color: var(--bs-ink-soft);
	font-size: var(--bs-text-base);
	margin: var(--bs-space-2) 0 0;
	max-width: var(--bs-container-text);
}

/* The "Shop all products" link and the slider arrows are siblings in one
   row: link on the left of the group, arrows on its right. Both the
   direction and the no-wrap are stated outright so a longer link label
   can never push the arrows onto a second line. */
.bs-section__actions {
	display: flex;
	flex-direction: row;
	flex-wrap: nowrap;
	align-items: center;
	gap: var(--bs-space-4);
	flex: none;
	margin-left: auto;
}

.bs-section__link {
	flex: none;
	order: 1;
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	color: var(--bs-accent);
	border-bottom: 1px solid currentColor;
	padding-bottom: 1px;
	white-space: nowrap;
}

.bs-section__actions .bs-slider__nav {
	order: 2;
}

@media (min-width: 768px) {
	.bs-section__title {
		font-size: var(--bs-text-3xl);
	}
}


/* ==========================================================================
   6. Homepage — hero
   ========================================================================== */

.bs-hero {
	display: grid;
	gap: var(--bs-space-8);
	align-items: center;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-xl);
	padding: var(--bs-space-8);
	margin-bottom: var(--bs-section-y);
	overflow: hidden;
}

@media (min-width: 900px) {
	.bs-hero {
		grid-template-columns: 1.05fr 0.95fr;
		padding: var(--bs-space-16) var(--bs-space-12);
		gap: var(--bs-space-12);
	}
}

.bs-hero__eyebrow {
	color: var(--bs-accent);
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	margin: 0 0 var(--bs-space-3);
}

.bs-hero__heading {
	font-size: clamp(2rem, 5.5vw, var(--bs-text-4xl));
	margin: 0;
	max-width: 16ch;
}

.bs-hero__sub {
	color: var(--bs-ink-soft);
	font-size: var(--bs-text-lg);
	margin: var(--bs-space-4) 0 0;
	max-width: 44ch;
}

.bs-hero__buttons {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--bs-space-4) var(--bs-space-6);
	margin-top: var(--bs-space-8);
}

.bs-hero__cta {
	font-size: var(--bs-text-lg);
	padding: 0.9em 2em;
}

.bs-hero__secondary {
	font-weight: var(--bs-weight-medium);
	border-bottom: 1px solid currentColor;
	padding-bottom: 2px;
}

.bs-hero__points {
	display: flex;
	flex-wrap: wrap;
	gap: var(--bs-space-3) var(--bs-space-6);
	list-style: none;
	margin: var(--bs-space-8) 0 0;
	padding: var(--bs-space-6) 0 0;
	border-top: 1px solid var(--bs-line);
	color: var(--bs-ink-soft);
	font-size: var(--bs-text-sm);
}

.bs-hero__points li {
	margin: 0;
	list-style: none;
}

.bs-hero__media {
	display: flex;
	align-items: center;
	justify-content: center;
	min-width: 0;
}

.bs-hero__media img {
	width: 100%;
	max-width: 460px;
	height: auto;
	max-height: 460px;
	object-fit: contain;
	display: block;
}


/* ==========================================================================
   7. Homepage — trust bar
   ========================================================================== */

.bs-trustbar__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--bs-space-4);
	list-style: none;
	margin: 0;
	padding: 0;
}

@media (min-width: 1000px) {
	.bs-trustbar__grid {
		grid-template-columns: repeat(4, 1fr);
	}
}

.bs-trustcard {
	list-style: none;
	margin: 0;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-lg);
	padding: var(--bs-space-6);
}

.bs-trustcard__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: var(--bs-radius-button);
	background-color: var(--bs-accent-tint);
	color: var(--bs-accent-dark);
	margin-bottom: var(--bs-space-4);
}

.bs-trustcard__icon .bs-icon {
	width: 22px;
	height: 22px;
}

.bs-trustcard__title {
	font-size: var(--bs-text-base);
	margin: 0 0 var(--bs-space-2);
}

.bs-trustcard__text {
	color: var(--bs-ink-soft);
	font-size: var(--bs-text-sm);
	margin: 0;
	max-width: none;
}


/* ==========================================================================
   8. Homepage — categories
   ========================================================================== */

.bs-cats__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--bs-space-6) var(--bs-space-4);
	list-style: none;
	margin: 0;
	padding: 0;
}

@media (min-width: 700px) {
	.bs-cats__grid {
		grid-template-columns: repeat(4, 1fr);
	}
}

.bs-cat {
	list-style: none;
	margin: 0;
}

.bs-cat__link {
	display: block;
	color: var(--bs-ink);
	text-align: center;
}

.bs-cat__media {
	display: block;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-lg);
	overflow: hidden;
	margin-bottom: var(--bs-space-3);
	transition: border-color var(--bs-duration) var(--bs-ease),
	            box-shadow var(--bs-duration) var(--bs-ease);
}

.bs-cat__media img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	height: auto;
	object-fit: contain;
	padding: var(--bs-space-4);
	background-color: var(--bs-surface);
}

.bs-cat__link:hover .bs-cat__media {
	border-color: var(--bs-accent);
	box-shadow: var(--bs-shadow);
}

.bs-cat__name {
	display: block;
	font-weight: var(--bs-weight-medium);
	line-height: 1.3;
}

.bs-cat__count {
	display: block;
	color: var(--bs-ink-soft);
	font-size: var(--bs-text-sm);
	margin-top: 2px;
}


/* ==========================================================================
   9. Product cards
   Every photo sits whole inside an identical white square, whatever its
   original shape or size. That is what makes the grid look even.
   ========================================================================== */

.woocommerce ul.products,
ul.products {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--bs-space-8) var(--bs-space-5);
	list-style: none;
	margin: 0;
	padding: 0;
}

.woocommerce ul.products::before,
.woocommerce ul.products::after {
	content: none;
}

@media (min-width: 768px) {
	.woocommerce ul.products,
	ul.products {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (min-width: 1100px) {
	.woocommerce ul.products,
	ul.products {
		grid-template-columns: repeat(4, 1fr);
	}
}

.woocommerce ul.products li.product,
ul.products li.product {
	width: 100% !important;
	float: none !important;
	clear: none !important;
	margin: 0 !important;
	padding: 0;
	display: flex;
	flex-direction: column;
	position: relative;
	list-style: none;
	text-align: left;
}

/* --- The uniform image box ------------------------------------------ */

.woocommerce ul.products li.product a img,
.woocommerce ul.products li.product img.woocommerce-placeholder,
ul.products li.product a img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	height: auto;
	object-fit: contain;
	object-position: center;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-lg);
	padding: var(--bs-space-4);
	margin: 0 0 var(--bs-space-4);
	transition: border-color var(--bs-duration) var(--bs-ease),
	            box-shadow var(--bs-duration) var(--bs-ease);
}

.woocommerce ul.products li.product:hover a img {
	border-color: var(--bs-accent);
	box-shadow: var(--bs-shadow);
}

/* --- Title ----------------------------------------------------------- */

.woocommerce ul.products li.product .woocommerce-loop-product__title {
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	line-height: 1.4;
	letter-spacing: 0;
	color: var(--bs-ink);
	padding: 0;
	margin: 0 0 var(--bs-space-2);
	unicode-bidi: plaintext;

	/* Two lines, so every card is the same height. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	min-height: 2.8em;
}

.woocommerce ul.products li.product a:hover .woocommerce-loop-product__title {
	color: var(--bs-accent-dark);
}

/* --- Price ----------------------------------------------------------- */

.woocommerce ul.products li.product .price {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--bs-space-2);
	font-size: var(--bs-text-base);
	font-weight: var(--bs-weight-bold);
	color: var(--bs-ink);
	margin: 0 0 var(--bs-space-4);
}

.woocommerce ul.products li.product .price del {
	color: var(--bs-ink-soft);
	font-weight: var(--bs-weight-normal);
	font-size: var(--bs-text-sm);
	opacity: 1;
	margin: 0;
}

.woocommerce ul.products li.product .price ins {
	text-decoration: none;
	background: none;
	color: var(--bs-amber);
}

.price bdi,
.amount bdi {
	white-space: nowrap;
}

.woocommerce-Price-currencySymbol {
	margin-inline-end: 0.15em;
	font-weight: inherit;
}

/* --- Add to cart ------------------------------------------------------ */

.woocommerce ul.products li.product .button,
.woocommerce ul.products li.product .added_to_cart {
	margin-top: auto;
	width: 100%;
	font-size: var(--bs-text-sm);
}

.woocommerce ul.products li.product .added_to_cart {
	margin-top: var(--bs-space-2);
	text-align: center;
	font-weight: var(--bs-weight-medium);
}

/* --- Sale badge ------------------------------------------------------- */

.woocommerce span.onsale {
	background-color: var(--bs-amber);
	color: #fff;
	font-size: var(--bs-text-xs);
	font-weight: var(--bs-weight-bold);
	letter-spacing: 0.01em;
	border-radius: var(--bs-radius-button);
	padding: 0.25rem 0.65rem;
	min-height: 0;
	min-width: 0;
	line-height: 1.5;
	margin: 0;
	top: auto;
	left: auto;
	right: auto;
}

.woocommerce ul.products li.product span.onsale {
	position: absolute;
	top: var(--bs-space-3);
	left: var(--bs-space-3);
	z-index: 2;
}


/* ==========================================================================
   10. Carousels and sliders
   Used by the homepage rows, "You may also like", upsells and cross-sells.
   ========================================================================== */

.woocommerce .bs-carousel ul.products,
.woocommerce .related.products ul.products,
.woocommerce .up-sells ul.products,
.woocommerce .cross-sells ul.products,
.bs-carousel ul.products,
.related.products ul.products,
.up-sells ul.products {
	display: flex;
	flex-wrap: nowrap;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x proximity;
	scroll-padding-left: 2px;
	gap: var(--bs-space-5);
	padding-bottom: var(--bs-space-2);
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.woocommerce .bs-carousel ul.products::-webkit-scrollbar,
.woocommerce .related.products ul.products::-webkit-scrollbar,
.woocommerce .up-sells ul.products::-webkit-scrollbar,
.bs-carousel ul.products::-webkit-scrollbar {
	display: none;
}

.woocommerce .bs-carousel ul.products > li.product,
.woocommerce .related.products ul.products > li.product,
.woocommerce .up-sells ul.products > li.product,
.woocommerce .cross-sells ul.products > li.product,
.bs-carousel ul.products > li.product,
.related.products ul.products > li.product,
.up-sells ul.products > li.product {
	flex: 0 0 72%;
	max-width: 72%;
	scroll-snap-align: start;
}

@media (min-width: 600px) {
	.woocommerce .bs-carousel ul.products > li.product,
	.woocommerce .related.products ul.products > li.product,
	.woocommerce .up-sells ul.products > li.product,
	.bs-carousel ul.products > li.product,
	.related.products ul.products > li.product,
	.up-sells ul.products > li.product {
		flex-basis: calc((100% - var(--bs-space-5)) / 2);
		max-width: calc((100% - var(--bs-space-5)) / 2);
	}
}

@media (min-width: 900px) {
	.woocommerce .bs-carousel ul.products > li.product,
	.woocommerce .related.products ul.products > li.product,
	.woocommerce .up-sells ul.products > li.product,
	.bs-carousel ul.products > li.product,
	.related.products ul.products > li.product,
	.up-sells ul.products > li.product {
		flex-basis: calc((100% - var(--bs-space-5) * 2) / 3);
		max-width: calc((100% - var(--bs-space-5) * 2) / 3);
	}
}

@media (min-width: 1100px) {
	.woocommerce .bs-carousel ul.products > li.product,
	.woocommerce .related.products ul.products > li.product,
	.woocommerce .up-sells ul.products > li.product,
	.bs-carousel ul.products > li.product,
	.related.products ul.products > li.product,
	.up-sells ul.products > li.product {
		flex-basis: calc((100% - var(--bs-space-5) * 3) / 4);
		max-width: calc((100% - var(--bs-space-5) * 3) / 4);
	}
}

/* --- Arrows ---------------------------------------------------------- */

.bs-slider {
	position: relative;
}

.bs-slider__nav {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: var(--bs-space-2);
	flex: none;
}

.bs-slider__nav[hidden] {
	display: none;
}

/* Rows that come from a WooCommerce template have no section header to
   sit in, so their arrows are pinned to the top right instead. */
.related.products > .bs-slider__nav,
.up-sells > .bs-slider__nav,
.cross-sells > .bs-slider__nav {
	position: absolute;
	top: 0;
	right: 0;
}

.bs-slider__arrow {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	min-height: 0;
	padding: 0;
	background-color: var(--bs-surface);
	color: var(--bs-ink);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-button);
	cursor: pointer;
	transition: background-color var(--bs-duration) var(--bs-ease),
	            border-color var(--bs-duration) var(--bs-ease),
	            opacity var(--bs-duration) var(--bs-ease);
}

.bs-slider__arrow .bs-icon {
	width: 20px;
	height: 20px;
}

.bs-slider__arrow:hover:not(:disabled),
.woocommerce .bs-slider__arrow:hover:not(:disabled) {
	background-color: var(--bs-accent);
	border-color: var(--bs-accent);
	color: #fff;
}

.bs-slider__arrow:disabled {
	opacity: 0.35;
	cursor: default;
}

.related.products > h2,
.up-sells > h2,
.cross-sells > h2 {
	font-size: var(--bs-text-xl);
	margin: 0 0 var(--bs-space-6);
	padding-right: 100px;
}

/* Arrows are pointless on a touch screen that already scrolls. */
@media (max-width: 599px) {
	.bs-slider__nav {
		display: none;
	}
}


/* ==========================================================================
   11. Shop and archive pages
   ========================================================================== */

.woocommerce-products-header {
	margin-bottom: var(--bs-space-6);
}

.woocommerce-products-header__title,
.woocommerce-products-header .page-title {
	font-size: var(--bs-text-3xl);
	margin: 0 0 var(--bs-space-3);
}

.term-description {
	color: var(--bs-ink-soft);
	max-width: var(--bs-container-text);
}

/* --- The toolbar above the grid --------------------------------------
   One plain row: how many results on the left, the sort select on the
   right. No panel, no border, and no second copy of the pagination —
   page numbers belong under the grid, not above it.                    */

.bs-toolbar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--bs-space-3) var(--bs-space-4);
	margin: 0 0 var(--bs-space-8);
	padding: 0;
	background: none;
	border: 0;
}

.bs-toolbar::before,
.bs-toolbar::after {
	content: none;
}

/* If Storefront's own wrapper ever comes back, strip it to the same shape. */
.woocommerce .storefront-sorting {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--bs-space-3) var(--bs-space-4);
	background: none;
	border: 0;
	border-radius: 0;
	padding: 0;
	margin: 0 0 var(--bs-space-8);
}

.woocommerce .storefront-sorting::before,
.woocommerce .storefront-sorting::after {
	content: none;
}

.woocommerce .storefront-sorting nav.woocommerce-pagination {
	display: none;
}

.woocommerce .woocommerce-result-count {
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
	margin: 0;
	max-width: none;
	order: 1;
}

.woocommerce .woocommerce-ordering {
	margin: 0;
	order: 2;
}

.woocommerce .woocommerce-ordering select {
	width: auto;
	min-width: 210px;
	border-radius: var(--bs-radius-button);
	padding-left: 1rem;
	min-height: 40px;
}

/* --- Load more -------------------------------------------------------- */

.bs-loadmore {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--bs-space-4);
	margin-top: var(--bs-space-12);
	padding-top: var(--bs-space-8);
	border-top: 1px solid var(--bs-line);
	text-align: center;
}

.bs-loadmore__count {
	color: var(--bs-ink-soft);
	font-size: var(--bs-text-sm);
	margin: 0;
	max-width: none;
}

.woocommerce .bs-loadmore__button,
.bs-loadmore__button {
	background-color: transparent;
	color: var(--bs-ink);
	border: 1px solid var(--bs-ink);
	min-width: 240px;
}

.woocommerce .bs-loadmore__button:hover,
.bs-loadmore__button:hover {
	background-color: var(--bs-ink);
	color: #fff;
	border-color: var(--bs-ink);
}

.bs-loadmore__button.is-loading {
	opacity: 0.6;
}

/* Numbered pagination is the fallback when the button is active. */
body.bs-has-loadmore .woocommerce nav.woocommerce-pagination {
	display: none;
}

.woocommerce nav.woocommerce-pagination {
	margin-top: var(--bs-space-12);
	padding-top: var(--bs-space-8);
	border-top: 1px solid var(--bs-line);
}

.woocommerce nav.woocommerce-pagination ul {
	border: 0;
	display: flex;
	flex-wrap: wrap;
	gap: var(--bs-space-2);
	justify-content: center;
	margin: 0;
	padding: 0;
}

.woocommerce nav.woocommerce-pagination ul li {
	border: 0;
	margin: 0;
	overflow: visible;
}

.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-sm);
	color: var(--bs-ink);
	padding: 0.5rem 0.9rem;
	min-width: 44px;
	text-align: center;
}

.woocommerce nav.woocommerce-pagination ul li span.current,
.woocommerce nav.woocommerce-pagination ul li a:hover {
	background-color: var(--bs-accent);
	border-color: var(--bs-accent);
	color: #fff;
}

/* --- Empty states ----------------------------------------------------- */

.woocommerce-info,
.woocommerce-message,
.woocommerce-error,
.woocommerce-no-products-found .woocommerce-info {
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-top: 3px solid var(--bs-accent);
	border-radius: var(--bs-radius);
	color: var(--bs-ink);
	padding: var(--bs-space-4) var(--bs-space-6);
	margin: 0 0 var(--bs-space-6);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--bs-space-4);
	justify-content: space-between;
}

.woocommerce-error {
	border-top-color: var(--bs-error);
	list-style: none;
}

.woocommerce-info::before,
.woocommerce-message::before,
.woocommerce-error::before {
	content: none;
}


/* ==========================================================================
   12. Single product
   ========================================================================== */

/* div.product is left as a plain block. Everything WooCommerce and its
   plugins print inside it — the top wrapper, the description, the upsell
   row, recently viewed — stacks in source order and nothing can be pulled
   sideways by a stray extra child. */
.single-product div.product {
	display: block !important;
	position: relative;
}

.single-product div.product::before,
.single-product div.product::after {
	content: "";
	display: table;
	clear: both;
}

/* The two-column top of the page: photo on the left, everything you buy
   with on the right. This wrapper is added in functions.php around the
   gallery and the summary only. */
.bs-product-top {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--bs-space-8);
	position: relative;
	margin-bottom: var(--bs-space-10);
}

@media (min-width: 900px) {
	.bs-product-top {
		grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
		gap: var(--bs-space-12);
		align-items: start;
	}
}

.bs-product-top > span.onsale {
	position: absolute;
	top: var(--bs-space-4);
	left: var(--bs-space-4);
	z-index: 3;
}

/* --- Gallery ----------------------------------------------------------
   Thumbnails run down the LEFT of the main photo from 700px up, which is
   what stops the gallery reading as "one picture, then some orphan squares
   underneath it". Below 700px they stay in a row under the photo, because a
   vertical rail on a phone would eat a third of the screen width.

   The photo is also the column that pins. On a product page the right-hand
   column is the long one — price, options, button, details — so pinning the
   summary instead left a short column stuck to the viewport while the tall
   one ran past it, which is what made the page feel broken. */

.single-product div.product .woocommerce-product-gallery {
	grid-column: 1;
	width: 100% !important;
	float: none !important;
	margin: 0 !important;
	position: relative;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-xl);
	padding: var(--bs-space-4);
}

.single-product .woocommerce-product-gallery__wrapper {
	margin: 0;
}

.single-product .woocommerce-product-gallery__image img,
.single-product .woocommerce-product-gallery img {
	width: 100%;
	aspect-ratio: 1 / 1;
	height: auto;
	object-fit: contain;
	background-color: var(--bs-surface);
	border-radius: var(--bs-radius-lg);
	display: block;
}

.single-product .flex-control-thumbs {
	display: flex;
	flex-wrap: wrap;
	gap: var(--bs-space-2);
	margin: var(--bs-space-4) 0 0;
	padding: 0;
	list-style: none;
}

.single-product .flex-control-thumbs li {
	width: auto !important;
	float: none !important;
	margin: 0;
	list-style: none;
}

.single-product .flex-control-thumbs img {
	width: 72px;
	height: 72px;
	aspect-ratio: 1 / 1;
	object-fit: contain;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-sm);
	padding: 4px;
	opacity: 1;
	cursor: pointer;
	transition: border-color var(--bs-duration) var(--bs-ease);
}

.single-product .flex-control-thumbs img:hover,
.single-product .flex-control-thumbs img.flex-active {
	border-color: var(--bs-accent);
}

/* Two columns: thumbnail rail, then the photo.

   FlexSlider wraps .woocommerce-product-gallery__wrapper in .flex-viewport
   once it initialises, but not before, and not at all if its script fails —
   so both are placed into column 2 explicitly and the layout survives
   either state. The body class comes from bs_buy_options_body_class() and
   carries browsers with no :has() support. */
@media (min-width: 700px) {

	.bs-has-gallery-thumbs.single-product div.product .woocommerce-product-gallery,
	.single-product div.product .woocommerce-product-gallery:has(.flex-control-thumbs) {
		display: grid;
		grid-template-columns: 76px minmax(0, 1fr);
		grid-template-rows: auto;
		gap: var(--bs-space-3);
		align-items: start;
	}

	.bs-has-gallery-thumbs.single-product .woocommerce-product-gallery .flex-control-thumbs,
	.single-product .woocommerce-product-gallery:has(.flex-control-thumbs) .flex-control-thumbs {
		grid-column: 1;
		grid-row: 1;
		flex-direction: column;
		flex-wrap: nowrap;
		margin: 0;
		max-height: 100%;
		overflow-y: auto;
		scrollbar-width: none;
	}

	.single-product .woocommerce-product-gallery .flex-control-thumbs::-webkit-scrollbar {
		width: 0;
	}

	.bs-has-gallery-thumbs.single-product .woocommerce-product-gallery .flex-control-thumbs img,
	.single-product .woocommerce-product-gallery:has(.flex-control-thumbs) .flex-control-thumbs img {
		width: 100%;
		height: auto;
	}

	.bs-has-gallery-thumbs.single-product .woocommerce-product-gallery > .flex-viewport,
	.bs-has-gallery-thumbs.single-product .woocommerce-product-gallery > .woocommerce-product-gallery__wrapper,
	.single-product .woocommerce-product-gallery:has(.flex-control-thumbs) > .flex-viewport,
	.single-product .woocommerce-product-gallery:has(.flex-control-thumbs) > .woocommerce-product-gallery__wrapper {
		grid-column: 2;
		grid-row: 1;
		min-width: 0;
	}
}

/* The zoom trigger is absolutely positioned by WooCommerce, so it has to be
   pulled out of the grid or it claims a cell of its own. */
.woocommerce-product-gallery__trigger {
	position: absolute;
	top: var(--bs-space-4);
	right: var(--bs-space-4);
	z-index: 2;
	border-radius: var(--bs-radius-button);
}

/* --- Summary ---------------------------------------------------------- */

.single-product div.product .summary,
.single-product div.product .entry-summary {
	display: block !important;
	width: 100% !important;
	float: none !important;
	margin: 0 !important;
	min-width: 0;
}

@media (min-width: 900px) {

	.single-product div.product .summary,
	.single-product div.product .entry-summary {
		grid-column: 2;
		position: static;
	}

	/* Pinned to just under the sticky header, and never taller than the
	   space left below it, so a portrait image can still scroll its own
	   last few pixels into view instead of being clipped. */
	.single-product div.product .woocommerce-product-gallery {
		position: sticky;
		top: calc(var(--bs-header-h) + var(--bs-space-6));
		align-self: start;
		max-height: calc(100vh - var(--bs-header-h) - var(--bs-space-10));
		overflow-y: auto;
		scrollbar-width: none;
	}

	.single-product div.product .woocommerce-product-gallery::-webkit-scrollbar {
		width: 0;
	}
}

/* position: sticky dies inside any ancestor with a clipping overflow, so the
   two wrappers between the gallery and the page are held open explicitly. */
@media (min-width: 900px) {
	.single-product div.product,
	.bs-product-top {
		overflow: visible;
	}
}

.single-product .product_title {
	font-size: var(--bs-text-xl);
	margin: 0 0 var(--bs-space-4);
	unicode-bidi: plaintext;
}

@media (min-width: 768px) {
	.single-product .product_title {
		font-size: var(--bs-text-2xl);
	}
}

.single-product div.product p.price,
.single-product div.product span.price {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--bs-space-3);
	font-size: var(--bs-text-xl);
	font-weight: var(--bs-weight-bold);
	color: var(--bs-ink);
	margin: 0 0 var(--bs-space-5);
	max-width: none;
}

.single-product div.product p.price del {
	color: var(--bs-ink-soft);
	font-size: var(--bs-text-base);
	font-weight: var(--bs-weight-normal);
	opacity: 1;
}

.single-product div.product p.price ins {
	text-decoration: none;
	background: none;
	color: var(--bs-amber);
}

.single-product .woocommerce-product-details__short-description {
	color: var(--bs-ink-soft);
	margin-bottom: var(--bs-space-6);
}

.single-product .stock.in-stock {
	color: var(--bs-success);
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
}

.single-product .stock.out-of-stock {
	color: var(--bs-error);
}

/* --- Add to cart ------------------------------------------------------ */

.single-product form.cart {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--bs-space-3);
	margin: 0 0 var(--bs-space-6) !important;
}

.single-product form.cart .quantity {
	flex: none;
	margin: 0;
}

.single-product form.cart .quantity .qty {
	width: 92px;
	min-height: 48px;
	text-align: center;
	border-radius: var(--bs-radius-button);
}

.single-product form.cart .single_add_to_cart_button {
	flex: 1 1 220px;
	min-height: 48px;
	font-size: var(--bs-text-lg);
}

.single-product form.cart.variations_form {
	display: block;
}

.single-product .variations {
	width: 100%;
	margin-bottom: var(--bs-space-4);
}

.single-product .variations td,
.single-product .variations th {
	display: block;
	padding: 0 0 var(--bs-space-2);
	border: 0;
	text-align: left;
}

.single-product .variations select {
	border-radius: var(--bs-radius-sm);
}

/* --- Trust list -------------------------------------------------------- */

.bs-trust {
	list-style: none;
	margin: 0 0 var(--bs-space-6);
	padding: var(--bs-space-4) var(--bs-space-5);
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius);
	display: grid;
	gap: var(--bs-space-3);
}

.bs-trust li {
	display: flex;
	align-items: center;
	gap: var(--bs-space-3);
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
}

.bs-trust li .bs-icon {
	width: 20px;
	height: 20px;
	color: var(--bs-accent);
}

.bs-trust--checkout {
	margin-bottom: var(--bs-space-8);
}

@media (min-width: 768px) {
	.bs-trust--checkout {
		grid-template-columns: repeat(3, 1fr);
	}
}

/* --- Meta -------------------------------------------------------------- */

.bs-meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--bs-space-2) var(--bs-space-6);
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
	padding-top: var(--bs-space-4);
	border-top: 1px solid var(--bs-line);
}

.bs-meta a {
	color: var(--bs-ink-soft);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.bs-meta a:hover {
	color: var(--bs-accent);
}

/* --- Description and reviews -------------------------------------------
   The tab strip is gone from the markup, so all of its styling went with
   it. Neither of the two blocks left is a card. The reviews never were: a
   bordered white panel around user writing makes it read as another block
   of store copy, which is the one thing reviews must not look like. The
   Details block was, and matching it to the reviews is what stopped the
   page below the gallery reading as a row of boxes.
   ------------------------------------------------------------------------ */

/* No box. A white panel on a near-white page, holding two lines of copy,
   gave the section more weight than it earns and made everything below the
   gallery read as a stack of containers. Same treatment as the reviews
   underneath it now: the heading and the space around it do the separating.
   The bottom margin absorbs the padding that came out. */
.bs-product-desc {
	clear: both;
	background-color: transparent;
	border: 0;
	border-radius: 0;
	padding: 0;
	margin: 0 0 var(--bs-space-8);
}

.bs-product-desc h2 {
	font-size: var(--bs-text-xl);
	margin: 0 0 var(--bs-space-4);
}

.bs-product-desc p,
.bs-product-desc li {
	color: var(--bs-ink-soft);
}

.bs-product-desc ul,
.bs-product-desc ol {
	padding-left: 1.2em;
}

/* Reviews: no box, no panel, just a ruled list. */
.bs-reviews {
	clear: both;
	margin: var(--bs-space-10) 0 0;
	padding-top: var(--bs-space-8);
	border-top: 1px solid var(--bs-line);
}

.bs-reviews #reviews,
.bs-reviews .woocommerce-Reviews {
	background: none;
	border: 0;
	padding: 0;
	margin: 0;
}

.bs-reviews .woocommerce-Reviews-title {
	font-size: var(--bs-text-xl);
	margin: 0 0 var(--bs-space-6);
}

.bs-reviews ol.commentlist {
	list-style: none;
	margin: 0;
	padding: 0;
}

.bs-reviews ol.commentlist li {
	margin: 0;
	padding: var(--bs-space-5) 0;
	border-bottom: 1px solid var(--bs-line);
	list-style: none;
}

.bs-reviews ol.commentlist li:first-child {
	padding-top: 0;
}

/* Storefront wraps every review in a bordered white .comment_container with
   its own padding. Flattened here — the row rule above is the only divider
   the list needs. */
.bs-reviews .comment_container {
	display: grid;
	grid-template-columns: 40px minmax(0, 1fr);
	gap: var(--bs-space-4);
	align-items: start;
	background: none !important;
	border: 0 !important;
	border-radius: 0 !important;
	box-shadow: none !important;
	padding: 0 !important;
	margin: 0;
}

.bs-reviews .comment_container img.avatar {
	position: static !important;
	width: 40px !important;
	height: 40px !important;
	padding: 0 !important;
	margin: 0 !important;
	border: 0 !important;
	border-radius: 50%;
	background: var(--bs-line);
}

.bs-reviews .comment-text {
	background: none !important;
	border: 0 !important;
	border-radius: 0 !important;
	padding: 0 !important;
	margin: 0 !important;
	min-width: 0;
}

/* Name, date and stars on one line instead of three stacked rows. */
.bs-reviews .comment-text .meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--bs-space-1) var(--bs-space-3);
	margin: 0 0 var(--bs-space-2);
	font-size: var(--bs-text-sm);
}

.bs-reviews .comment-text .meta strong {
	font-weight: var(--bs-weight-bold);
	color: var(--bs-ink);
}

.bs-reviews .comment-text .meta time,
.bs-reviews .comment-text .woocommerce-review__published-date {
	color: var(--bs-ink-soft);
	font-size: var(--bs-text-xs);
}

/* The stars were floating right into the far edge of the page, a full
   column away from the review they belonged to. */
.bs-reviews .comment-text .star-rating {
	float: none !important;
	margin: 0 0 var(--bs-space-2);
	color: var(--bs-amber);
}

.bs-reviews .comment-text p:last-child {
	margin-bottom: 0;
}

.bs-reviews .comment-text p {
	color: var(--bs-ink-soft);
}

/* Review form */
.bs-reviews #review_form_wrapper {
	margin-top: var(--bs-space-8);
}

.bs-reviews #reply-title {
	display: block;
	font-size: var(--bs-text-lg);
	font-weight: var(--bs-weight-bold);
	margin: 0 0 var(--bs-space-4);
}

.bs-reviews .comment-form label {
	display: block;
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	margin-bottom: var(--bs-space-2);
}

.bs-reviews .comment-form textarea {
	width: 100%;
	min-height: 120px;
}

.bs-reviews .comment-form-rating .stars {
	margin: 0 0 var(--bs-space-4);
}

/* --- Upsell rows under the product -------------------------------------- */

.single-product .bs-related,
.single-product .bs-recent,
.related.products,
.up-sells.products,
.cross-sells {
	clear: both;
	margin-top: var(--bs-space-12);
	margin-bottom: 0;
	position: relative;
}


/* ==========================================================================
   13. Newsletter
   ========================================================================== */

.bs-newsletter__panel {
	display: grid;
	gap: var(--bs-space-8);
	background-color: var(--bs-accent-dark);
	color: #fff;
	border-radius: var(--bs-radius-xl);
	padding: var(--bs-space-8);
}

@media (min-width: 900px) {
	.bs-newsletter__panel {
		grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
		align-items: center;
		padding: var(--bs-space-12);
		gap: var(--bs-space-10);
	}
}

.bs-newsletter__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: var(--bs-radius-button);
	background-color: rgba(255, 255, 255, 0.14);
	color: #fff;
	margin-bottom: var(--bs-space-4);
}

.bs-newsletter__title {
	color: #fff;
	font-size: var(--bs-text-2xl);
	margin: 0 0 var(--bs-space-3);
}

.bs-newsletter__sub {
	color: rgba(255, 255, 255, 0.82);
	margin: 0;
}

/* Name, email and the button share one row, with the button last on the
   right so the form reads left to right and ends on the action. */
.bs-newsletter__form {
	display: grid;
	gap: var(--bs-space-4);
}

@media (min-width: 560px) {
	.bs-newsletter__form {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
		align-items: end;
		gap: var(--bs-space-4) var(--bs-space-3);
	}

	.bs-newsletter__message,
	.bs-newsletter__fineprint {
		grid-column: 1 / -1;
	}
}

.bs-field {
	margin: 0;
	max-width: none;
	min-width: 0;
}

.bs-field label {
	color: rgba(255, 255, 255, 0.82);
	font-size: var(--bs-text-sm);
	margin-bottom: var(--bs-space-2);
}

.bs-newsletter__form input[type="text"],
.bs-newsletter__form input[type="email"] {
	border-radius: var(--bs-radius-button);
	border-color: transparent;
	padding-left: 1.1rem;
}

.bs-newsletter__form input:focus {
	box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.35);
}

/* Warm terracotta so the button reads as the action, not as a third
   input sitting next to the two white fields. */
.woocommerce .bs-newsletter__button,
.bs-newsletter__button {
	background-color: var(--bs-cta-warm);
	color: #fff;
	border-color: transparent;
	min-height: 44px;
	padding: 0.8em 1.9em;
	white-space: nowrap;
	justify-self: stretch;
}

@media (min-width: 560px) {
	.woocommerce .bs-newsletter__button,
	.bs-newsletter__button {
		justify-self: end;
		align-self: end;
	}
}

.woocommerce .bs-newsletter__button:hover,
.bs-newsletter__button:hover {
	background-color: var(--bs-cta-warm-dark);
	color: #fff;
}

.bs-newsletter__message {
	margin: 0;
	min-height: 1.4em;
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	color: #fff;
	max-width: none;
}

.bs-newsletter__message.is-error {
	color: #ffd9d4;
}

.bs-newsletter__fineprint {
	margin: 0;
	font-size: var(--bs-text-xs);
	color: rgba(255, 255, 255, 0.6);
	max-width: none;
}

/* Honeypot — hidden from people, visible to bots. */
.bs-field--hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}


/* ==========================================================================
   14. Sticky mobile buy bar
   ========================================================================== */

.bs-sticky-buy {
	display: none;
}

@media (max-width: 767px) {
	.bs-sticky-buy {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		z-index: 400;
		display: flex;
		align-items: center;
		gap: var(--bs-space-4);
		background-color: var(--bs-surface);
		border-top: 1px solid var(--bs-line);
		box-shadow: 0 -6px 24px rgba(20, 32, 26, 0.1);
		padding: var(--bs-space-3) var(--bs-gutter);
		padding-bottom: calc(var(--bs-space-3) + env(safe-area-inset-bottom, 0px));
	}

	.single-product .site-content {
		padding-bottom: 96px;
	}
}

.bs-sticky-buy__info {
	display: flex;
	flex-direction: column;
	min-width: 0;
	flex: 1 1 auto;
}

.bs-sticky-buy__name {
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.bs-sticky-buy__price {
	font-weight: var(--bs-weight-bold);
	font-size: var(--bs-text-base);
}

.bs-sticky-buy__price del {
	display: none;
}

.bs-sticky-buy__button {
	flex: none;
}


/* ==========================================================================
   15. Cart
   A line item is a picture and a name. Descriptions, excerpts and any
   other marketing copy a plugin prints under the name are hidden — in the
   classic table and in the newer cart block alike.
   ========================================================================== */

.bs-shipping-bar {
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius);
	padding: var(--bs-space-4) var(--bs-space-5);
	margin-bottom: var(--bs-space-6);
}

.bs-shipping-bar__text {
	margin: 0 0 var(--bs-space-3);
	font-size: var(--bs-text-sm);
	max-width: none;
}

.bs-shipping-bar__track {
	height: 8px;
	border-radius: 999px;
	background-color: var(--bs-surface-sunk);
	overflow: hidden;
}

.bs-shipping-bar__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background-color: var(--bs-accent);
	transition: width 400ms var(--bs-ease);
}
/* --- Free-delivery progress bar, cart and checkout blocks --------------- */

.bs-shipping-bar__text strong {
	font-weight: var(--bs-weight-bold);
	color: var(--bs-ink);
	white-space: nowrap;
}

.bs-shipping-bar.is-qualified {
	border-color: var(--bs-accent);
	background-color: var(--bs-accent-tint);
}

.bs-shipping-bar.is-qualified .bs-shipping-bar__track {
	background-color: var(--bs-surface);
}

/* Full width, sitting above both cart columns. */
.wp-block-woocommerce-cart > .bs-shipping-bar {
	margin-bottom: var(--bs-space-8);
}

/* Above the order summary panel on checkout. */
.wc-block-components-sidebar > .bs-shipping-bar {
	margin-bottom: var(--bs-space-4);
}

/* Never let the empty shell flash before the script fills it in. */
#bs-shipping-bar:not([data-bs-stamp]) {
	display: none;
}
.woocommerce table.shop_table {
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-lg);
	border-collapse: separate;
	border-spacing: 0;
	overflow: hidden;
}

.woocommerce table.shop_table th,
.woocommerce table.shop_table td {
	border-color: var(--bs-line);
	padding: var(--bs-space-4);
}

.woocommerce table.shop_table thead th {
	background-color: var(--bs-surface-sunk);
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-bold);
}

.woocommerce table.cart img,
.woocommerce-cart table.cart img {
	width: 72px;
	height: 72px;
	object-fit: contain;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-sm);
	padding: 4px;
}

/* --- Classic cart: name only ------------------------------------------ */

.woocommerce td.product-name .bs-cart-item-name {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	font-weight: var(--bs-weight-medium);
	color: var(--bs-ink);
	line-height: 1.4;
}

.woocommerce td.product-name p,
.woocommerce td.product-name .woocommerce-product-details__short-description,
.woocommerce td.product-name .product-excerpt,
.woocommerce td.product-name > ul:not(.variation) {
	display: none;
}

/* --- Cart and checkout blocks ----------------------------------------- */

/* Only the short description is hidden. Note that
   .wc-block-components-order-summary-item__description is the wrapper around
   the product name and its metadata, not a description — hiding it blanks the
   product name on checkout. */
.wc-block-components-product-metadata__description,
.wc-block-cart-item__product .wc-block-components-product-metadata p {
	display: none !important;
}

.wc-block-components-product-name,
.wc-block-components-order-summary-item__title .wc-block-components-product-name {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	font-weight: var(--bs-weight-medium);
	line-height: 1.4;
	color: var(--bs-ink);
}

.wc-block-cart-item__image img,
.wc-block-components-order-summary-item__image img {
	width: 72px;
	height: 72px;
	object-fit: contain;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-sm);
	padding: 4px;
}

.wc-block-components-button,
.wc-block-cart__submit-button {
	border-radius: var(--bs-radius-button);
}

/* --- Totals ------------------------------------------------------------ */

.woocommerce .cart-collaterals .cart_totals,
.woocommerce-cart .cart-collaterals .cart_totals {
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-lg);
	padding: var(--bs-space-6);
}

.woocommerce .cart_totals h2 {
	font-size: var(--bs-text-xl);
	margin: 0 0 var(--bs-space-4);
}

.woocommerce .cart_totals table.shop_table {
	border: 0;
	border-radius: 0;
}

.woocommerce .wc-proceed-to-checkout .button {
	width: 100%;
	font-size: var(--bs-text-lg);
	min-height: 50px;
}

.woocommerce .coupon input[type="text"] {
	border-radius: var(--bs-radius-button);
}

.bs-keep-shopping {
	margin: var(--bs-space-4) 0 0;
	text-align: center;
	font-size: var(--bs-text-sm);
}

.woocommerce .cart-empty,
.woocommerce .return-to-shop {
	text-align: center;
}


/* ==========================================================================
   16. Checkout and account
   ========================================================================== */

.woocommerce-checkout .col2-set .col-1,
.woocommerce-checkout .col2-set .col-2 {
	float: none;
	width: 100%;
}

.woocommerce-checkout #customer_details,
.woocommerce-checkout #order_review,
.woocommerce-checkout #order_review_heading + #order_review {
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-lg);
	padding: var(--bs-space-6);
	margin-bottom: var(--bs-space-6);
}

/* Order review: image and name, same rule as the cart. */
.woocommerce-checkout #order_review td.product-name p,
.woocommerce-checkout #order_review td.product-name .woocommerce-product-details__short-description,
.woocommerce-checkout #order_review td.product-name > ul:not(.variation) {
	display: none;
}

.woocommerce-checkout #order_review td.product-name {
	line-height: 1.4;
}

.woocommerce-checkout h3,
.woocommerce-account h2,
.woocommerce-checkout #order_review_heading {
	font-size: var(--bs-text-xl);
	margin: 0 0 var(--bs-space-4);
}

.woocommerce form .form-row {
	padding: 0;
	margin: 0 0 var(--bs-space-4);
}

.woocommerce form .form-row label {
	margin-bottom: var(--bs-space-2);
}

.woocommerce #payment {
	background-color: transparent;
	border-radius: 0;
}

.woocommerce #payment ul.payment_methods {
	border: 0;
	padding: 0;
}

.woocommerce #payment ul.payment_methods li {
	background-color: var(--bs-surface-sunk);
	border-radius: var(--bs-radius);
	padding: var(--bs-space-4);
	margin-bottom: var(--bs-space-3);
	list-style: none;
}

.woocommerce #payment div.payment_box {
	background-color: transparent;
	border-radius: var(--bs-radius-sm);
	font-size: var(--bs-text-sm);
}

.woocommerce #payment div.payment_box::before {
	content: none;
}

.woocommerce #place_order,
.woocommerce #payment #place_order {
	width: 100%;
	font-size: var(--bs-text-lg);
	min-height: 52px;
}

.woocommerce-order,
.woocommerce-order-received .woocommerce-order-overview {
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-lg);
	padding: var(--bs-space-6);
}

/* --- My Account navigation ---------------------------------------------
   WooCommerce core floats this nav at 30% width and puts hairline borders
   on the list and its items. Un-float it, strip the borders, and lay the
   links out as a single roomy pill row above the content. */

.woocommerce-account .woocommerce-MyAccount-navigation {
	float: none !important;
	width: 100% !important;
	max-width: none;
	margin: 0 0 var(--bs-space-8);
	border: 0 !important;
	box-shadow: none;
}

.woocommerce-account .woocommerce-MyAccount-navigation ul {
	list-style: none;
	margin: 0;
	padding: 0;
	border: 0 !important;
	box-shadow: none;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--bs-space-3);
}

/* Kill core's clearfix pseudo-elements — flex handles the layout. */
.woocommerce-account .woocommerce-MyAccount-navigation ul::before,
.woocommerce-account .woocommerce-MyAccount-navigation ul::after {
	content: none !important;
	display: none !important;
}

.woocommerce-account .woocommerce-MyAccount-navigation li {
	float: none;
	margin: 0;
	padding: 0;
	border: 0 !important;
	list-style: none;
}

.woocommerce-account .woocommerce-MyAccount-navigation li a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.625rem;
	min-height: 46px;
	padding: 0.625rem 1.375rem;
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-button);
	background-color: var(--bs-surface);
	color: var(--bs-ink);
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	line-height: 1.2;
	white-space: nowrap;
	text-decoration: none;
	transition: background-color var(--bs-duration) ease,
	            border-color var(--bs-duration) ease,
	            color var(--bs-duration) ease;
}

/* Icons injected by WooCommerce or a plugin: keep them inside the pill,
   vertically centred, never absolutely positioned, never floated. */
.woocommerce-account .woocommerce-MyAccount-navigation li a::before,
.woocommerce-account .woocommerce-MyAccount-navigation li a::after {
	position: static !important;
	float: none !important;
	flex: 0 0 auto;
	width: auto;
	height: auto;
	margin: 0 !important;
	padding: 0 !important;
	top: auto;
	right: auto;
	bottom: auto;
	left: auto;
	transform: none;
	font-size: 0.95em;
	line-height: 1;
	opacity: 0.85;
}

.woocommerce-account .woocommerce-MyAccount-navigation li a:hover,
.woocommerce-account .woocommerce-MyAccount-navigation li a:focus-visible {
	border-color: var(--bs-accent);
	color: var(--bs-accent);
	background-color: var(--bs-accent-tint);
}

.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a {
	background-color: var(--bs-accent);
	border-color: var(--bs-accent);
	color: #fff;
}

.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a::before,
.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a::after {
	opacity: 1;
}

.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a:hover {
	background-color: var(--bs-accent-dark);
	border-color: var(--bs-accent-dark);
	color: #fff;
}

.woocommerce-account .woocommerce-MyAccount-content {
	width: 100%;
	max-width: none;
	float: none;
	clear: both;
}

/* Small screens: one swipeable row rather than a ragged stack. */
@media (max-width: 600px) {
	.woocommerce-account .woocommerce-MyAccount-navigation ul {
		flex-wrap: nowrap;
		overflow-x: auto;
		padding-bottom: var(--bs-space-2);
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}

	.woocommerce-account .woocommerce-MyAccount-navigation ul::-webkit-scrollbar {
		display: none;
	}

	.woocommerce-account .woocommerce-MyAccount-navigation li a {
		padding: 0.625rem 1.125rem;
	}
}

.woocommerce-account .woocommerce-form-login,
.woocommerce-account .woocommerce-form-register {
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-lg);
	padding: var(--bs-space-6);
}


/* ==========================================================================
   17. Footer
   ========================================================================== */

.site-footer {
	background-color: var(--bs-surface);
	border-top: 1px solid var(--bs-line);
	color: var(--bs-ink-soft);
	font-size: var(--bs-text-sm);
	padding: var(--bs-space-16) 0 var(--bs-space-10);
	margin: 0;
}

.site-footer a {
	color: var(--bs-ink-soft);
}

.site-footer a:hover {
	color: var(--bs-accent);
}

.bs-footer__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--bs-space-8);
}

@media (min-width: 900px) {
	.bs-footer__grid {
		grid-template-columns: 1.6fr 1fr 1fr 1fr;
		gap: var(--bs-space-12);
	}
}

.bs-footer__brand img,
.bs-footer__brand .custom-logo {
	max-width: 170px;
	max-height: 44px;
	width: auto;
	height: auto;
	object-fit: contain;
	margin-bottom: var(--bs-space-4);
}

.bs-footer__brand {
	grid-column: 1 / -1;
}

@media (min-width: 900px) {
	.bs-footer__brand {
		grid-column: auto;
	}
}

.bs-footer__blurb {
	margin: 0 0 var(--bs-space-5);
	max-width: 40ch;
}

.bs-footer__badges {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: var(--bs-space-3) var(--bs-space-5);
}

.bs-footer__badges li {
	display: flex;
	align-items: center;
	gap: var(--bs-space-2);
	margin: 0;
	list-style: none;
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
}

.bs-footer__badges .bs-icon {
	width: 18px;
	height: 18px;
	color: var(--bs-accent);
}

.bs-footer__heading {
	color: var(--bs-ink);
	font-size: var(--bs-text-base);
	margin: 0 0 var(--bs-space-4);
}

.bs-footer__col ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: var(--bs-space-3);
}

.bs-footer__col li {
	margin: 0;
	list-style: none;
}

.bs-footer__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--bs-space-4) var(--bs-space-8);
	margin-top: var(--bs-space-12);
	padding-top: var(--bs-space-6);
	border-top: 1px solid var(--bs-line);
	font-size: var(--bs-text-xs);
}

.bs-footer__copy {
	margin: 0;
	max-width: none;
}

.bs-footer__links {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: var(--bs-space-5);
}

.bs-footer__links li {
	margin: 0;
	list-style: none;
}


/* ==========================================================================
   18. Utilities and accessibility
   19. Conversion / AOV components  [NEW in 4.0.0]
   ========================================================================== */

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.button:focus-visible {
	outline: 2px solid var(--bs-accent);
	outline-offset: 2px;
}

img {
	max-width: 100%;
	height: auto;
}

.bs-sr-only,
.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}
/* ==========================================================================
   12b. Single product — remove the next/previous product side links
   --------------------------------------------------------------------------
   The Storefront Product Pagination plugin pins a thumbnail of the previous
   and next product to the left and right edges of the single product page.
   They pull attention away from the product being viewed, so hide them.
   Deactivating the plugin is cleaner; this is the CSS fallback.
   ========================================================================== */

.storefront-product-pagination,
.single-product .storefront-product-pagination,
.storefront-product-pagination a,
.storefront-product-pagination__title {
	display: none !important;
}

/* Some builds wrap the links in a generic nav instead. */
.single-product nav[class*="product-pagination"],
.single-product .product-pagination {
	display: none !important;
}


/* ==========================================================================
   19. Conversion / AOV components
   --------------------------------------------------------------------------
   Everything added in the 4.0.0 conversion pass lives here so it can be
   reviewed, tuned or lifted out in one piece. It uses the same tokens as the
   rest of the file — nothing below hard-codes a colour.
   ========================================================================== */

/* Some resets set display on elements that then ignore [hidden]. */
[hidden] {
	display: none !important;
}


/* --- 19.1 Slide-out cart drawer ---------------------------------------- */

.bs-drawer-backdrop {
	position: fixed;
	inset: 0;
	z-index: 900;
	background-color: rgba(20, 32, 26, 0.42);
	opacity: 0;
	transition: opacity var(--bs-duration) ease;
}

.bs-drawer-backdrop.is-open {
	opacity: 1;
}

.bs-drawer {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	z-index: 901;
	width: min(420px, 100vw);
	display: flex;
	flex-direction: column;
	background-color: var(--bs-bg);
	box-shadow: var(--bs-shadow-lg);
	transform: translateX(100%);
	transition: transform 240ms cubic-bezier(0.32, 0.72, 0, 1);
	overscroll-behavior: contain;
}

.bs-drawer.is-open {
	transform: translateX(0);
}

body.bs-drawer-open {
	overflow: hidden;
}

.bs-drawer__head {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--bs-space-3);
	padding: var(--bs-space-5) var(--bs-space-5) var(--bs-space-4);
	border-bottom: 1px solid var(--bs-line);
	background-color: var(--bs-surface);
}

.bs-drawer__title {
	margin: 0;
	font-size: var(--bs-text-lg);
	font-weight: var(--bs-weight-bold);
	letter-spacing: var(--bs-tracking-tight);
}

.bs-drawer__count {
	color: var(--bs-ink-soft);
	font-weight: var(--bs-weight-normal);
	margin-left: var(--bs-space-1);
}

.bs-drawer__body {
	flex: 1 1 auto;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	padding: var(--bs-space-4) var(--bs-space-5) var(--bs-space-6);
}

.bs-drawer__items {
	list-style: none;
	margin: 0;
	padding: 0;
}

.bs-drawer__empty {
	text-align: center;
	padding: var(--bs-space-12) 0;
	color: var(--bs-ink-soft);
}

.bs-drawer__empty .button {
	margin-top: var(--bs-space-4);
}

/* Line items */

.bs-line {
	display: grid;
	grid-template-columns: 72px 1fr auto;
	gap: var(--bs-space-4);
	align-items: start;
	padding: var(--bs-space-4) 0;
	border-bottom: 1px solid var(--bs-line);
}

.bs-line:first-child {
	padding-top: 0;
}

.bs-line__image {
	width: 72px;
	height: 72px;
	object-fit: contain;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-sm);
}

.bs-line__text {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: var(--bs-space-2);
}

.bs-line__name {
	font-size: var(--bs-text-sm);
	line-height: 1.35;
	color: var(--bs-ink);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.bs-line__price {
	font-weight: var(--bs-weight-bold);
	font-size: var(--bs-text-sm);
}

.bs-line__gift {
	display: inline-flex;
	align-self: flex-start;
	background-color: var(--bs-accent-tint);
	color: var(--bs-accent-dark);
	font-size: var(--bs-text-xs);
	font-weight: var(--bs-weight-bold);
	padding: 2px 8px;
	border-radius: var(--bs-radius-button);
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.bs-line.is-gift .bs-line__image {
	border-color: var(--bs-accent);
}

/* Quantity stepper — 44px targets, per mobile tap-target guidance. */

.bs-line__qty {
	display: inline-flex;
	align-items: center;
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-button);
	background-color: var(--bs-surface);
	align-self: flex-start;
	overflow: hidden;
}

.bs-qty {
	appearance: none;
	border: 0;
	background: none;
	cursor: pointer;
	width: 36px;
	height: 36px;
	font-size: var(--bs-text-base);
	line-height: 1;
	color: var(--bs-ink);
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

.bs-qty:hover {
	background-color: var(--bs-surface-sunk);
}

.bs-qty__value {
	min-width: 28px;
	text-align: center;
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	font-variant-numeric: tabular-nums;
}

.bs-line__remove {
	appearance: none;
	border: 0;
	background: none;
	cursor: pointer;
	color: var(--bs-ink-soft);
	padding: var(--bs-space-2);
	border-radius: var(--bs-radius-sm);
	line-height: 0;
}

.bs-line__remove:hover {
	color: var(--bs-error);
	background-color: var(--bs-surface-sunk);
}

/* Footer — the checkout action never scrolls out of reach. */

.bs-drawer__foot {
	flex: none;
	border-top: 1px solid var(--bs-line);
	background-color: var(--bs-surface);
	padding: var(--bs-space-4) var(--bs-space-5);
	padding-bottom: calc(var(--bs-space-4) + env(safe-area-inset-bottom, 0px));
}

.bs-drawer__totals {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	font-size: var(--bs-text-base);
	margin-bottom: var(--bs-space-1);
}

.bs-drawer__totals strong {
	font-size: var(--bs-text-lg);
	font-weight: var(--bs-weight-bold);
}

.bs-drawer__note {
	margin: 0 0 var(--bs-space-4);
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
	max-width: none;
}

.bs-drawer__checkout {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--bs-space-2);
	width: 100%;
	text-align: center;
	font-weight: var(--bs-weight-bold);
}

.bs-drawer__keep {
	display: block;
	text-align: center;
	margin-top: var(--bs-space-3);
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
	text-decoration: underline;
}

.bs-trust--drawer {
	margin-top: var(--bs-space-4);
	padding-top: var(--bs-space-4);
	border-top: 1px solid var(--bs-line);
	gap: var(--bs-space-2);
}

.bs-trust--drawer li {
	font-size: var(--bs-text-xs);
}


/* --- 19.2 Multi-tier reward progress bar -------------------------------- */

.bs-tiers {
	flex: none;
	padding: var(--bs-space-4) var(--bs-space-5) var(--bs-space-8);
	background-color: var(--bs-accent-tint);
	border-bottom: 1px solid var(--bs-line);
}

.bs-tiers__message {
	margin: 0 0 var(--bs-space-3);
	font-size: var(--bs-text-sm);
	line-height: 1.4;
	color: var(--bs-accent-dark);
	max-width: none;
}

.bs-tiers__message strong {
	font-weight: var(--bs-weight-bold);
}

.bs-tiers__message span {
	font-weight: var(--bs-weight-bold);
}

.bs-tiers__track {
	position: relative;
	height: 6px;
	border-radius: 999px;
	background-color: rgba(20, 32, 26, 0.12);
	overflow: hidden;
}

.bs-tiers__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background-color: var(--bs-accent);
	transition: width 320ms cubic-bezier(0.32, 0.72, 0, 1);
}

.bs-tiers.is-complete .bs-tiers__fill {
	background-color: var(--bs-success);
}

.bs-tiers__list {
	position: relative;
	list-style: none;
	margin: 0;
	padding: 0;
	height: 22px;
}

.bs-tier {
	position: absolute;
	top: -4px;
	transform: translateX(-50%);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 4px;
	white-space: nowrap;
}

.bs-tier:first-child {
	transform: translateX(-25%);
}

.bs-tier:last-child {
	transform: translateX(-75%);
}

.bs-tier__dot {
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background-color: var(--bs-bg);
	border: 2px solid rgba(20, 32, 26, 0.2);
}

.bs-tier.is-done .bs-tier__dot {
	background-color: var(--bs-accent);
	border-color: var(--bs-accent);
}

.bs-tier__label {
	font-size: 0.6875rem;
	color: var(--bs-ink-soft);
	line-height: 1;
}

.bs-tier.is-done .bs-tier__label {
	color: var(--bs-accent-dark);
	font-weight: var(--bs-weight-bold);
}


/* --- 19.3 In-drawer impulse add-ons ------------------------------------- */

.bs-addons {
	margin-top: var(--bs-space-6);
	padding-top: var(--bs-space-5);
	border-top: 1px solid var(--bs-line);
}

.bs-addons__title {
	margin: 0 0 var(--bs-space-3);
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-bold);
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--bs-ink-soft);
}

.bs-addons__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--bs-space-3);
}

.bs-addon {
	display: grid;
	grid-template-columns: 56px 1fr auto;
	gap: var(--bs-space-3);
	align-items: center;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius);
	padding: var(--bs-space-3);
}

.bs-addon__image {
	width: 56px;
	height: 56px;
	object-fit: contain;
	border-radius: var(--bs-radius-sm);
}

.bs-addon__text {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.bs-addon__name {
	font-size: var(--bs-text-sm);
	line-height: 1.3;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.bs-addon__rating {
	font-size: var(--bs-text-xs);
	color: var(--bs-amber);
}

.bs-addon__rating span {
	color: var(--bs-ink-soft);
}

.bs-addon__price {
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-bold);
}

.bs-addon__add {
	appearance: none;
	cursor: pointer;
	border: 1px solid var(--bs-cta);
	background-color: transparent;
	color: var(--bs-cta);
	font-weight: var(--bs-weight-bold);
	font-size: var(--bs-text-sm);
	padding: 0 var(--bs-space-4);
	height: 40px;
	border-radius: var(--bs-radius-button);
	white-space: nowrap;
	transition: background-color var(--bs-duration) ease, color var(--bs-duration) ease;
}

.bs-addon__add:hover,
.bs-addon__add:focus-visible {
	background-color: var(--bs-cta);
	color: var(--bs-cta-text);
}

.bs-addon__add[disabled] {
	opacity: 0.6;
	cursor: default;
}


/* --- 19.4 Product page: social proof, unit price, delivery nudge --------- */

.bs-social-proof {
	display: flex;
	align-items: center;
	gap: var(--bs-space-2);
	flex-wrap: wrap;
	margin-bottom: var(--bs-space-3);
	font-size: var(--bs-text-sm);
}

.bs-social-proof .star-rating {
	margin: 0;
	color: var(--bs-amber);
}

.bs-social-proof__link {
	color: var(--bs-ink-soft);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.bs-social-proof__none {
	color: var(--bs-ink-soft);
	font-size: var(--bs-text-xs);
}

.bs-rating {
	display: flex;
	align-items: center;
	gap: var(--bs-space-2);
	margin: var(--bs-space-1) 0;
}

.bs-rating .star-rating {
	margin: 0;
	font-size: 0.8em;
	color: var(--bs-amber);
}

.bs-rating__count {
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
}

/* Unit price — the rational justification for trading up a size. */
.bs-unit-price {
	display: block;
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
	margin-top: 2px;
	font-variant-numeric: tabular-nums;
}

/* Sits UNDER the Add to cart button now, not above it. The full-width flex
   row it used to be would have read as a second button directly beneath the
   real one, so it is a self-width pill instead — clearly a badge. */
.bs-ship-nudge {
	display: inline-flex;
	align-items: center;
	gap: var(--bs-space-2);
	margin: var(--bs-space-3) 0 0;
	padding: var(--bs-space-2) var(--bs-space-4);
	background-color: var(--bs-accent-tint);
	border-radius: var(--bs-radius-lg);
	font-size: var(--bs-text-sm);
	color: var(--bs-accent-dark);
	max-width: none;
}

.bs-ship-nudge .bs-icon {
	width: 20px;
	height: 20px;
	flex: none;
}

.bs-ship-nudge .woocommerce-Price-amount {
	font-weight: var(--bs-weight-bold);
}



/* --- 19.6 Sticky buy bar additions -------------------------------------- */

.bs-sticky-buy__thumb {
	display: none;
}

@media (max-width: 767px) {
	.bs-sticky-buy__thumb {
		display: block;
		width: 44px;
		height: 44px;
		flex: none;
		object-fit: contain;
		border-radius: var(--bs-radius-sm);
		background-color: var(--bs-surface);
	}

	/* Minimum ergonomic tap target. */
	.bs-sticky-buy__button {
		min-height: 46px;
		padding-left: var(--bs-space-6);
		padding-right: var(--bs-space-6);
	}

	/* Never let the sticky bar sit over the drawer's checkout button. */
	body.bs-drawer-open .bs-sticky-buy {
		display: none;
	}
}


/* --- 19.7 Checkout: enclosure, field pruning, payment trust -------------- */

/* Enclosed checkout — every outbound link is a leak. */
.bs-enclosed-checkout .bs-header__nav,
.bs-enclosed-checkout .bs-mobile-nav,
.bs-enclosed-checkout .bs-nav-toggle,
.bs-enclosed-checkout .bs-search-toggle,
.bs-enclosed-checkout .bs-search-panel,
.bs-enclosed-checkout .bs-account-link,
.bs-enclosed-checkout .bs-cart-link,
.bs-enclosed-checkout .bs-announce,
.bs-enclosed-checkout .bs-footer__nav,
.bs-enclosed-checkout .bs-footer__newsletter,
.bs-enclosed-checkout .bs-sticky-buy {
	display: none !important;
}

.bs-enclosed-checkout .bs-header__inner {
	justify-content: center;
}

/* Fields the theme prunes. Kept in the DOM so validation and autofill still
   work; hidden so the form reads as 6–8 inputs rather than 12. */
.bs-field-hidden,
.woocommerce-checkout .bs-field-hidden,
.wc-block-components-address-form .bs-field-hidden {
	display: none !important;
}

/* Address line 2 collapses behind its own label until it is focused or
   filled, so the majority who have no apartment number never see a box they
   cannot answer. */
.woocommerce-checkout .bs-address-2 {
	margin-top: calc(var(--bs-space-2) * -1);
}

.woocommerce-checkout .bs-address-2 label.bs-field-optional {
	font-size: var(--bs-text-sm);
	color: var(--bs-accent);
	text-decoration: underline;
	cursor: pointer;
}

/* Single-column form on mobile — split rows cause tab-order errors. */
@media (max-width: 767px) {
	.woocommerce-checkout .form-row-first,
	.woocommerce-checkout .form-row-last,
	.wc-block-components-address-form__field-wrapper > * {
		width: 100% !important;
		float: none !important;
	}
}

/* Security marks adjacent to the payment fields, not stranded in the footer. */
.bs-paytrust {
	display: flex;
	align-items: center;
	gap: var(--bs-space-3);
	margin-top: var(--bs-space-4);
	padding: var(--bs-space-3) var(--bs-space-4);
	background-color: var(--bs-surface-sunk);
	border-radius: var(--bs-radius-sm);
}

.bs-paytrust .bs-icon {
	width: 22px;
	height: 22px;
	flex: none;
	color: var(--bs-accent);
}

.bs-paytrust ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: var(--bs-space-1) var(--bs-space-4);
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
}

.bs-paytrust li::before {
	content: "✓";
	margin-right: 4px;
	color: var(--bs-accent);
}

/* Express wallets belong ABOVE the form, not after it. Stripe measures a
   large conversion difference between the two placements. */
.wp-block-woocommerce-checkout-express-payment-block,
.wc-block-checkout__express-payment {
	order: -1;
	margin-bottom: var(--bs-space-5) !important;
}

/* The coupon field: visible, empty promo boxes send shoppers off-site to hunt
   for a code, and a meaningful share never come back. The block checkout
   already collapses it behind a link — this keeps it quiet on the classic one. */
.woocommerce-checkout .checkout_coupon {
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-sm);
	background-color: var(--bs-surface);
}

.woocommerce-checkout .woocommerce-form-coupon-toggle .woocommerce-info {
	font-size: var(--bs-text-sm);
	background: none;
	border: 0;
	padding: 0 0 var(--bs-space-3);
	color: var(--bs-ink-soft);
}

/* Gift line item marker in the classic cart / order summary. */
.bs-gift-tag {
	display: inline-block;
	margin-left: var(--bs-space-2);
	background-color: var(--bs-accent-tint);
	color: var(--bs-accent-dark);
	font-size: var(--bs-text-xs);
	font-weight: var(--bs-weight-bold);
	padding: 2px 8px;
	border-radius: var(--bs-radius-button);
	text-transform: uppercase;
	letter-spacing: 0.04em;
}


/* --- 19.8 Post-purchase account creation -------------------------------- */

.bs-thankyou-account {
	margin: var(--bs-space-8) 0;
	padding: var(--bs-space-5);
	background-color: var(--bs-accent-tint);
	border-radius: var(--bs-radius);
}

.bs-thankyou-account h3 {
	margin: 0 0 var(--bs-space-1);
	font-size: var(--bs-text-lg);
}

.bs-thankyou-account p {
	margin: 0 0 var(--bs-space-4);
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
	max-width: none;
}

.bs-thankyou-account__form {
	display: flex;
	gap: var(--bs-space-3);
	flex-wrap: wrap;
}

.bs-thankyou-account__form input {
	flex: 1 1 220px;
	min-width: 0;
}

.bs-thankyou-account__form .button {
	flex: none;
}


/* --- 19.9 Header cart badge --------------------------------------------- */

/* The badge and total are now painted by JavaScript from a local mirror, so
   they must not reserve space or flash a stale value before they are known. */
.bs-cart-link__count[hidden],
.bs-cart-link__total[hidden] {
	display: none !important;
}

.bs-cart-link {
	cursor: pointer;
}


/* --- 19.10 Motion ------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	.bs-drawer,
	.bs-drawer-backdrop,
	.bs-tiers__fill {
		transition: none !important;
	}
}


/* --- 19.11 Cart drawer note ---------------------------------------------
   The cash-on-delivery line that used to live here is gone: BS_COD_FEE is 0,
   so there is no fee to disclose and nothing to print on the product page.
   Setting the constant back above zero restores the drawer copy only.
   ------------------------------------------------------------------------ */

.bs-drawer__note {
	line-height: 1.5;
}

/* --- 19.12 Stripe express checkout --------------------------------------
   Apple Pay and Google Pay arrive with Stripe. Placement is the part that
   carries the measured difference: shown early, above the form, not tacked
   on after it. Enable "Express checkout" on the Stripe gateway and add the
   Express Payment block at the top of your Checkout block.
   ------------------------------------------------------------------------ */

.wc-block-checkout__express-payment,
.wp-block-woocommerce-checkout-express-payment-block {
	padding-top: 0 !important;
}

.wc-block-components-express-payment__title-container {
	font-weight: var(--bs-weight-bold);
}

/* The COD radio should not out-shout the card option once Stripe is live. */
.wc-block-components-radio-control__option[for*="cod"] .wc-block-components-radio-control__label {
	color: var(--bs-ink-soft);
}


/* ==========================================================================
   21. Buy-box purchase options, and a quieter cart drawer          [v4.1.0]
   ========================================================================== */

/* --- 21.1 Buy one / Bundle of five -------------------------------------- */

.bs-buy-options {
	display: grid;
	gap: var(--bs-space-2);
	margin: 0 0 var(--bs-space-4);
}

.bs-buy-option {
	position: relative;
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	align-items: center;
	gap: var(--bs-space-3);
	padding: var(--bs-space-4);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-lg);
	background-color: var(--bs-bg);
	cursor: pointer;
	transition:
		border-color var(--bs-duration) var(--bs-ease),
		background-color var(--bs-duration) var(--bs-ease);
}

.bs-buy-option:hover {
	border-color: var(--bs-accent);
}

.bs-buy-option.is-selected {
	border-color: var(--bs-accent);
	background-color: var(--bs-accent-tint);
	box-shadow: inset 0 0 0 1px var(--bs-accent);
}

/* The native input stays in the accessibility tree and keeps keyboard and
   screen-reader behaviour; the visible control is the dot beside it. */
.bs-buy-option input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

.bs-buy-option__dot {
	width: 20px;
	height: 20px;
	border-radius: 50%;
	border: 2px solid var(--bs-line);
	background-color: var(--bs-bg);
	flex: none;
	position: relative;
}

.bs-buy-option.is-selected .bs-buy-option__dot {
	border-color: var(--bs-accent);
}

.bs-buy-option.is-selected .bs-buy-option__dot::after {
	content: "";
	position: absolute;
	inset: 3px;
	border-radius: 50%;
	background-color: var(--bs-accent);
}

.bs-buy-option input:focus-visible ~ .bs-buy-option__dot {
	outline: 2px solid var(--bs-accent);
	outline-offset: 2px;
}

.bs-buy-option__text {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

.bs-buy-option__name {
	font-weight: var(--bs-weight-bold);
	font-size: var(--bs-text-base);
	line-height: 1.2;
}

.bs-buy-option__meta {
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
}

.bs-buy-option__price {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 2px;
	font-weight: var(--bs-weight-bold);
	font-size: var(--bs-text-base);
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

.bs-buy-option__was {
	font-size: var(--bs-text-xs);
	font-weight: var(--bs-weight-normal);
	color: var(--bs-ink-soft);
	text-decoration: line-through;
}

.bs-buy-option__now {
	color: var(--bs-accent-dark);
}

/* Saving badge, notched into the top edge so it reads as a label on the
   card rather than another line of copy competing inside it. */
.bs-buy-option--pack {
	margin-top: var(--bs-space-2);
}

.bs-buy-option__flag {
	position: absolute;
	top: 0;
	right: var(--bs-space-4);
	transform: translateY(-50%);
	background-color: var(--bs-accent);
	color: #fff;
	font-size: var(--bs-text-xs);
	font-weight: var(--bs-weight-bold);
	line-height: 1;
	padding: 5px 10px;
	border-radius: var(--bs-radius-button);
	white-space: nowrap;

	/* The badge names the rewards now ("FREE Delivery and 10% OFF") rather
	   than a short money figure, so it can outgrow the card it is pinned to.
	   Capping it against the card keeps the pill inside the rounded corner
	   instead of bleeding into the gutter. */
	max-width: calc(100% - var(--bs-space-4) * 2);
	overflow: hidden;
	text-overflow: ellipsis;
}

/* Below roughly a phone width there is no room for the label on one line, so
   it wraps and the pill grows downward rather than being clipped. Left aligned
   with the card edge, because a wrapped pill hanging off the right reads as a
   layout fault. */
@media (max-width: 480px) {

	.bs-buy-option__flag {
		white-space: normal;
		text-align: center;
		line-height: 1.25;
		text-overflow: clip;
	}
}

/* The radios are the quantity control once they exist, so the spinner is
   redundant. It stays in the DOM because WooCommerce and the Store API both
   read its value. */
.bs-has-buy-options.single-product form.cart .quantity,
.single-product form.cart:has(.bs-buy-options) .quantity {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

.bs-has-buy-options.single-product form.cart .single_add_to_cart_button,
.single-product form.cart:has(.bs-buy-options) .single_add_to_cart_button {
	width: 100%;
}


/* --- 21.2 Drawer, decongested ------------------------------------------- */

/* Reward strip: one sentence and a bar. The pip rail underneath it was
   stacking two labels into the last 40px of a 420px panel. */
.bs-tiers {
	padding: var(--bs-space-3) var(--bs-space-4);
}

.bs-tiers__message {
	margin: 0 0 var(--bs-space-2);
	font-size: var(--bs-text-xs);
}

.bs-tiers__track {
	height: 4px;
}

.bs-drawer__head {
	padding: var(--bs-space-4) var(--bs-space-5);
}

.bs-drawer__body {
	padding: var(--bs-space-2) var(--bs-space-5) var(--bs-space-4);
}

/* Tighter line items: 56px thumb, name and price on one row, stepper and
   remove sharing the row below. Three lines instead of five. */
.bs-line {
	grid-template-columns: 56px minmax(0, 1fr) auto;
	gap: var(--bs-space-3);
	padding: var(--bs-space-3) 0;
}

.bs-line__image {
	width: 56px;
	height: 56px;
}

.bs-line__text {
	gap: var(--bs-space-1);
}

.bs-line__name {
	font-size: var(--bs-text-xs);
	line-height: 1.4;
}

.bs-line__qty {
	margin-top: 2px;
}

.bs-qty {
	width: 30px;
	height: 30px;
}

.bs-qty__value {
	min-width: 24px;
}

/* Footer: subtotal, one short note, the button. Everything else is a
   single reassurance line, because three trust rows above the fold of a
   drawer push the checkout button off it on a short laptop screen. */
.bs-drawer__foot {
	padding: var(--bs-space-4) var(--bs-space-5);
	padding-bottom: calc(var(--bs-space-4) + env(safe-area-inset-bottom, 0px));
}

.bs-drawer__note {
	margin: 0 0 var(--bs-space-3);
	font-size: 0.6875rem;
	line-height: 1.45;
}

.bs-drawer__keep {
	margin-top: var(--bs-space-2);
}

.bs-drawer__reassure {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--bs-space-2);
	margin: var(--bs-space-3) 0 0;
	padding-top: var(--bs-space-3);
	border-top: 1px solid var(--bs-line);
	font-size: 0.6875rem;
	color: var(--bs-ink-soft);
	text-align: center;
	max-width: none;
}

.bs-drawer__reassure .bs-icon {
	width: 14px;
	height: 14px;
	flex: none;
}

.bs-drawer__saving {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	margin: 0 0 var(--bs-space-1);
	font-size: var(--bs-text-sm);
	color: var(--bs-success);
	max-width: none;
}

.bs-drawer__saving strong {
	font-weight: var(--bs-weight-bold);
	font-variant-numeric: tabular-nums;
}


/* ==========================================================================
   22. Product page, decluttered                                    [v4.2.0]

   Everything a shopper needs to decide now lives in one column beside the
   photo, in the order the decision actually gets made: what it is, what it
   costs, one jar or the set, the button, delivery, trust, then the detail
   they go looking for. The tab strip, the cross-sell shelf and the
   category link that used to carry this work are gone.
   ========================================================================== */

/* --- 22.1 Specification accordions -------------------------------------- */

/* The old "Additional information" tab, unpacked into the buy box. Native
   <details>, so it opens with no JavaScript and is keyboard operable free. */
.bs-specs {
	margin-top: var(--bs-space-5);
	border-top: 1px solid var(--bs-line);
}

.bs-spec {
	border-bottom: 1px solid var(--bs-line);
}

.bs-spec__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--bs-space-4);
	padding: var(--bs-space-4) 0;
	cursor: pointer;
	list-style: none;
	font-weight: var(--bs-weight-medium);
	font-size: var(--bs-text-sm);
	color: var(--bs-ink);
}

/* Safari still paints its own disclosure triangle without this. */
.bs-spec__head::-webkit-details-marker,
.bs-set__head::-webkit-details-marker {
	display: none;
}

.bs-spec__head:hover {
	color: var(--bs-accent);
}

.bs-spec__head:focus-visible {
	outline: 2px solid var(--bs-accent);
	outline-offset: 2px;
	border-radius: var(--bs-radius-sm);
}

.bs-spec__chevron {
	width: 9px;
	height: 9px;
	flex: none;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg) translate(-2px, -2px);
	transition: transform var(--bs-duration) var(--bs-ease);
	opacity: 0.55;
}

.bs-spec[open] > .bs-spec__head .bs-spec__chevron,
.bs-set[open] > .bs-set__head .bs-spec__chevron {
	transform: rotate(225deg) translate(-2px, -2px);
}

.bs-spec__body {
	padding: 0 0 var(--bs-space-4);
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
}

.bs-spec__body p {
	margin: 0 0 var(--bs-space-2);
	max-width: none;
}

.bs-spec__body p:last-child {
	margin-bottom: 0;
}

/* --- 22.2 "What is in the set" disclosure ------------------------------- */

.bs-set {
	margin-top: var(--bs-space-1);
}

.bs-set__head {
	display: flex;
	align-items: center;
	gap: var(--bs-space-2);
	padding: var(--bs-space-2) var(--bs-space-1);
	cursor: pointer;
	list-style: none;
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
}

.bs-set__head:hover {
	color: var(--bs-accent);
}

.bs-set__list {
	list-style: none;
	margin: 0;
	padding: var(--bs-space-2) 0 var(--bs-space-1);
}

.bs-set__item {
	display: grid;
	grid-template-columns: 44px minmax(0, 1fr) auto;
	gap: var(--bs-space-3);
	align-items: center;
	padding: var(--bs-space-2) 0;
}

.bs-set__media img {
	width: 44px;
	height: 44px;
	object-fit: contain;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-sm);
	display: block;
}

.bs-set__name {
	font-size: var(--bs-text-sm);
	color: var(--bs-ink);
	line-height: 1.35;
	min-width: 0;
}

a.bs-set__name:hover {
	color: var(--bs-accent);
}

.bs-set__this {
	display: inline-block;
	margin-left: var(--bs-space-2);
	font-style: normal;
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
}

.bs-set__price {
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

/* --- 22.3 Buy-box corrections ------------------------------------------- */

/* The set option is five different products, so the quantity field is not
   the control any more — the radio is. The spinner stays in the DOM because
   WooCommerce and the Store API both read it, but it is only shown when a
   single unit is what is being bought. */
.bs-buy-option--set {
	margin-top: var(--bs-space-2);
}

.bs-buy-options .bs-set,
.bs-buy-options .bs-set__head {
	cursor: pointer;
}

/* Loading state while the five Store API adds run. */
.single_add_to_cart_button.is-loading {
	opacity: 0.65;
	pointer-events: none;
}

/* Attributes, delivery badge and trust list all sit inside the summary
   column, so nothing below the button should stretch to the page width. */
.single-product .bs-specs,
.single-product .bs-trust {
	max-width: none;
}


/* ==========================================================================
   23. Product page repairs                                        [v4.3.0]

   Five things were wrong on the single product page and every one of them
   was a spacing or containment bug rather than a design decision:

     23.1  the breadcrumb sat under the sticky header, and the gap below it
           was carrying padding from four different wrappers at once
     23.2  the gallery and the title started at different heights
     23.3  the gallery's sticky never engaged, because an ancestor was
           clipping its overflow
     23.4  the reviews were a stack of bordered cards, not the three-column
           list the layout asks for
     23.5  the ritual set was hidden behind a disclosure
   ========================================================================== */


/* --- 23.1 The top of the page ------------------------------------------

   Everything between the header and the first line of the product was
   being contributed by a different element: Storefront's breadcrumb
   wrapper, our own breadcrumb margin, .site-content's padding and
   .site-main's own. They are collapsed to one number here — the padding
   on the breadcrumb row — so there is a single place to change it.      */

:root {
	--bs-crumb-top:    var(--bs-space-5);
	--bs-crumb-bottom: var(--bs-space-6);
}

/* Any in-page jump has to clear the sticky header, or the thing you
   jumped to lands behind it. */
html {
	scroll-padding-top: calc(var(--bs-header-h) + var(--bs-space-6));
}

.single-product .site-content {
	padding-top: 0;
}

.single-product .storefront-breadcrumb {
	margin: 0;
	padding: 0;
	background: none;
	border: 0;
}

.single-product .woocommerce-breadcrumb {
	position: relative;
	z-index: 1;
	margin: 0;
	padding: var(--bs-crumb-top) 0 var(--bs-crumb-bottom);
	line-height: 1.5;
}

/* WooCommerce prints this wrapper on every load, empty or not. */
.single-product .woocommerce-notices-wrapper {
	margin: 0;
}

.single-product .woocommerce-notices-wrapper:empty {
	display: none;
}

.single-product #primary,
.single-product .content-area,
.single-product .site-main {
	margin-top: 0;
	padding-top: 0;
}

.single-product div.product,
.single-product .bs-product-top {
	margin-top: 0;
}


/* --- 23.2 Gallery and title start on the same line ---------------------

   Both are grid children of .bs-product-top, so an even top is only a
   matter of neither one carrying a margin of its own into the row.     */

.single-product .bs-product-top > * {
	margin-top: 0;
}

.single-product div.product .woocommerce-product-gallery {
	margin-top: 0 !important;
	align-self: start;
}

.single-product div.product .summary > *:first-child,
.single-product div.product .entry-summary > *:first-child {
	margin-top: 0;
}

.single-product .product_title {
	margin-top: 0;
	padding-top: 0;
}


/* --- 23.3 The gallery actually pins ------------------------------------

   position: sticky is cancelled by any ancestor with a clipping overflow,
   and there are five wrappers between the gallery and the page. They are
   held open explicitly here.

   The pin releases at the bottom of .bs-product-top, which is exactly
   where the Details panel starts — so the photo holds still through the
   whole buy box and then scrolls away with everything else.            */

@media (min-width: 900px) {

	.single-product .site-content,
	.single-product .site-content > .col-full,
	.single-product #primary,
	.single-product .content-area,
	.single-product .site-main,
	.single-product div.product,
	.single-product .bs-product-top {
		overflow: visible !important;
	}

	.single-product div.product .woocommerce-product-gallery {
		position: sticky;
		top: calc(var(--bs-header-h) + var(--bs-space-4));
		align-self: start;
		max-height: calc(100vh - var(--bs-header-h) - var(--bs-space-8));
		overflow-y: auto;
		overscroll-behavior: contain;
		scrollbar-width: none;
	}

	.admin-bar.single-product div.product .woocommerce-product-gallery {
		top: calc(var(--bs-header-h) + var(--bs-space-4) + 32px);
		max-height: calc(100vh - var(--bs-header-h) - var(--bs-space-8) - 32px);
	}
}


/* --- 23.4 Customer reviews ---------------------------------------------

   Four columns across the section: a summary that pins on the left, then
   author, review, and any photo. No borders, no cards — the columns and
   the gap between rows are the only structure there is.                */

.bs-reviews {
	clear: both;
	margin: var(--bs-space-16) 0 0;
	padding-top: 0;
	border-top: 0;
}

.bs-reviews__title {
	font-size: var(--bs-text-2xl);
	margin: 0 0 var(--bs-space-8);
}

/* WooCommerce prints "4 reviews for <product>" of its own; ours is above
   it and says the same thing in fewer words. */
.bs-reviews .woocommerce-Reviews-title {
	display: none;
}

.bs-reviews__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--bs-space-8);
	align-items: start;
}

.bs-reviews__main {
	min-width: 0;
}

@media (min-width: 900px) {

	.bs-reviews__grid {
		grid-template-columns: 260px minmax(0, 1fr);
		gap: var(--bs-space-12);
	}

	.bs-rsum {
		position: sticky;
		top: calc(var(--bs-header-h) + var(--bs-space-6));
		align-self: start;
	}

	.admin-bar .bs-rsum {
		top: calc(var(--bs-header-h) + var(--bs-space-6) + 32px);
	}
}

/* Summary panel */

.bs-rsum__inner {
	display: grid;
	gap: var(--bs-space-6);
	justify-items: start;
}

.bs-rsum__head {
	display: flex;
	align-items: center;
	gap: var(--bs-space-3);
}

.bs-rsum__score {
	font-family: var(--bs-font-head);
	font-size: 2.75rem;
	font-weight: var(--bs-weight-bold);
	line-height: 1;
	letter-spacing: var(--bs-tracking-tight);
}

.bs-rsum__of {
	display: grid;
	gap: 3px;
}

.bs-rsum__count {
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
}

.bs-rsum__bars {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: var(--bs-space-2);
	width: 100%;
	max-width: 240px;
}

.bs-rsum__row {
	display: grid;
	grid-template-columns: 34px minmax(0, 1fr) 42px;
	align-items: center;
	gap: var(--bs-space-3);
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
}

.bs-rsum__level {
	display: inline-flex;
	align-items: center;
	gap: 3px;
	font-variant-numeric: tabular-nums;
}

.bs-rsum__star {
	color: var(--bs-amber);
}

.bs-rsum__track {
	height: 6px;
	border-radius: 999px;
	background-color: var(--bs-surface-sunk);
	overflow: hidden;
}

.bs-rsum__fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background-color: var(--bs-accent);
}

.bs-rsum__num {
	text-align: right;
	font-variant-numeric: tabular-nums;
}

.bs-rsum__none {
	font-size: var(--bs-text-sm);
	color: var(--bs-ink-soft);
	margin: 0;
}

.bs-rsum__write {
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	color: var(--bs-accent);
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* Star bar, used by the summary and by every review row */

.bs-stars {
	position: relative;
	display: inline-block;
	white-space: nowrap;
	line-height: 1;
	font-size: var(--bs-text-base);
	color: var(--bs-line);
}

.bs-stars::before,
.bs-stars__fill::before {
	content: "\2605\2605\2605\2605\2605";
	letter-spacing: 2px;
}

.bs-stars__fill {
	position: absolute;
	top: 0;
	left: 0;
	height: 100%;
	overflow: hidden;
	color: var(--bs-amber);
}

/* The list */

.bs-reviews ol.commentlist {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: var(--bs-space-8);
}

.bs-reviews ol.commentlist li,
.bs-reviews ol.commentlist li:first-child {
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	list-style: none;
}

.bs-review__row {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--bs-space-4);
	align-items: start;
}

@media (min-width: 768px) {

	.bs-review__row {
		grid-template-columns: 150px minmax(0, 1fr) auto;
		gap: var(--bs-space-6);
	}

	/* When any review in the list carries a photo, every row reserves the
	   same width for one — otherwise the text column would change width
	   from row to row down the page. */
	.bs-reviews ol.commentlist:has(.bs-review__media:not(.is-empty)) .bs-review__row {
		grid-template-columns: 150px minmax(0, 1fr) 168px;
	}
}

.bs-review__author {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--bs-space-2);
	min-width: 0;
}

.bs-reviews .bs-review__avatar,
.bs-reviews .comment_container img.avatar {
	position: static !important;
	float: none !important;
	width: 48px !important;
	height: 48px !important;
	margin: 0 !important;
	padding: 0 !important;
	border: 0 !important;
	border-radius: 50%;
	background-color: var(--bs-surface-sunk);
}

.bs-review__name {
	font-weight: var(--bs-weight-bold);
	font-size: var(--bs-text-sm);
	color: var(--bs-ink);
	overflow-wrap: anywhere;
}

.bs-review__body {
	min-width: 0;
}

.bs-review__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--bs-space-2) var(--bs-space-4);
	margin: 0 0 var(--bs-space-3);
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
}

.bs-review__meta .bs-stars {
	font-size: var(--bs-text-sm);
}

.bs-review__date {
	font-variant-numeric: tabular-nums;
}

.bs-review__verified {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	color: var(--bs-success);
	font-weight: var(--bs-weight-medium);
}

.bs-review__verified .bs-icon {
	width: 14px;
	height: 14px;
	flex: none;
}

.bs-review__title {
	font-size: var(--bs-text-base);
	font-weight: var(--bs-weight-bold);
	margin: 0 0 var(--bs-space-2);
}

.bs-review__text p {
	margin: 0 0 var(--bs-space-2);
	color: var(--bs-ink-soft);
}

.bs-review__text p:last-child {
	margin-bottom: 0;
}

.bs-review__pending {
	margin: var(--bs-space-2) 0 0;
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
}

.bs-review__media {
	display: flex;
	flex-wrap: wrap;
	gap: var(--bs-space-2);
	min-width: 0;
}

.bs-review__media.is-empty {
	display: none;
}

@media (min-width: 768px) {
	.bs-review__media.is-empty {
		display: block;
	}
}

.bs-review__shot img {
	width: 78px;
	height: 78px;
	object-fit: cover;
	border-radius: var(--bs-radius-sm);
	background-color: var(--bs-surface);
	display: block;
}

/* Review form */

.bs-reviews #review_form_wrapper {
	margin-top: var(--bs-space-12);
}

.bs-reviews .comment-form {
	max-width: 640px;
}

.bs-reviews .comment-form input[type="text"],
.bs-reviews .comment-form input[type="email"] {
	width: 100%;
}

.bs-reviews .comment-form-review-title,
.bs-reviews .comment-form-review-photos {
	margin-bottom: var(--bs-space-4);
}

.bs-form-hint {
	display: block;
	margin-top: 4px;
	font-size: var(--bs-text-xs);
	color: var(--bs-ink-soft);
}


/* --- 23.5 The ritual set, printed open ---------------------------------

   It was a shut <details> above the Add to cart button: a click in the
   way of the only question the panel asks. All five products are listed
   now, and the rows are tighter so the button does not get pushed off
   the fold to make room for them.                                       */

.bs-buy-options .bs-set,
.bs-buy-options .bs-set__head {
	cursor: default;
}

.bs-buy-options .bs-set {
	margin: 0;
	padding: var(--bs-space-1) var(--bs-space-1) 0;
}

.bs-set__head {
	display: block;
	margin: 0;
	padding: 0;
	max-width: none;
	font-size: var(--bs-text-xs);
	font-weight: var(--bs-weight-medium);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--bs-ink-soft);
}

.bs-set__head:hover {
	color: var(--bs-ink-soft);
}

.bs-set__list {
	padding: var(--bs-space-2) 0 0;
}

.bs-set__item {
	grid-template-columns: 36px minmax(0, 1fr) auto;
	gap: var(--bs-space-3);
	padding: var(--bs-space-1) 0;
}

.bs-set__media img {
	width: 36px;
	height: 36px;
}

.bs-set__item.is-current .bs-set__name {
	font-weight: var(--bs-weight-medium);
}


/* ==========================================================================
   24. Product page repairs, round two                             [v4.4.0]

   Section 23 aimed at the right four things and missed on three of them.
   What was actually wrong, and why the earlier fix could not have worked:

     24.1  The stars were coloured on the CONTAINER (.bs-social-proof
           .star-rating). WooCommerce colours them on the pseudo-element
           of the child (.star-rating span::before). A direct declaration
           always beats an inherited one, whatever the specificity, so the
           amber never reached the glyphs and WooCommerce purple won.

     24.2  The gallery was told margin-top: 0, but the offset was never a
           margin — so zeroing it changed nothing. Both columns are given
           an explicit grid area here instead, and anything else in the
           wrapper is sent to a row of its own below them.

     24.3  Seven ancestors were opened up for the sticky gallery. The
           document root and body were not among them, and overflow-x:
           hidden on either one creates a scroll container that cancels
           sticky silently. overflow-x: clip does the same job without
           creating one.

     24.4  The ritual list could not be moved inside the box by CSS,
           because the border was on the <label> and the list was the
           label's sibling. The markup now wraps both in one card and the
           frame moves to the card. See bs_buy_options() in functions.php.
   ========================================================================== */


/* --- 24.1 Stars: amber, never WooCommerce purple ------------------------

   The container rules stay where they are; these reach the parts that
   actually carry a colour of their own. The empty track keeps the
   hairline grey so a 3-star rating still reads as three out of five.  */

.star-rating,
.woocommerce .star-rating,
.woocommerce-page .star-rating {
	color: var(--bs-amber) !important;
}

/* The unfilled five behind the rating. */
.star-rating::before,
.woocommerce .star-rating::before,
.woocommerce-page .star-rating::before {
	color: var(--bs-line) !important;
}

/* The filled overlay — this is the one WooCommerce paints purple. */
.star-rating span::before,
.star-rating > span::before,
.woocommerce .star-rating span::before,
.woocommerce-page .star-rating span::before {
	color: var(--bs-amber) !important;
}

/* Ratings drawn inside WooCommerce Blocks markup. */
.wc-block-components-product-rating .star-rating,
.wc-block-components-product-rating__stars,
.wc-block-components-product-rating__stars span::before,
.wc-block-review-list-item__rating .star-rating span::before {
	color: var(--bs-amber) !important;
}

/* The five-star picker in the review form. Resting state stays quiet;
   only the stars WooCommerce fills in are coloured, and the trailing
   empties are put back to the hairline.

   Note the ::before on every one of these. WooCommerce colours the
   pseudo-element, so colouring the <a> only sets a value for the
   pseudo-element to inherit — and it never does, because it has a
   colour of its own. This is the same trap that made the rating stars
   purple; it has to be sprung in both places. */
.bs-reviews p.stars a::before,
#respond p.stars a::before,
p.stars a::before {
	color: var(--bs-line) !important;
}

p.stars:hover a::before,
p.stars.selected a.active::before,
p.stars.selected a:not(.active)::before {
	color: var(--bs-amber) !important;
}

p.stars.selected a.active ~ a::before {
	color: var(--bs-line) !important;
}

/* WooCommerce ships its brand purple as custom properties too, and some
   of its stylesheets read those rather than a literal colour. */
:root,
.woocommerce,
.woocommerce-page {
	--woocommerce:   var(--bs-amber);
	--wc-primary:    var(--bs-amber);
	--wc-highlight:  var(--bs-amber);
}


/* --- 24.2 Gallery and title start on the same line ----------------------

   Explicit grid areas, so an unexpected child of .bs-product-top cannot
   take the gallery's slot and push it down a row. Anything that is not
   one of the two columns, and is not the absolutely-positioned sale
   badge, lands on a row of its own underneath both of them.           */

@media (min-width: 900px) {

	.single-product .bs-product-top {
		display: grid;
		grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
		gap: var(--bs-space-12);
		align-items: start;
	}

	.single-product .bs-product-top > .woocommerce-product-gallery {
		grid-area: 1 / 1;
		align-self: start;
	}

	.single-product .bs-product-top > .summary,
	.single-product .bs-product-top > .entry-summary {
		grid-area: 1 / 2;
		align-self: start;
	}

	.single-product .bs-product-top > *:not(.woocommerce-product-gallery):not(.summary):not(.entry-summary):not(.onsale) {
		grid-column: 1 / -1;
		grid-row: 2;
	}
}

/* Neither column may carry a top margin into the row. */
.single-product .bs-product-top > .woocommerce-product-gallery,
.single-product .bs-product-top > .summary,
.single-product .bs-product-top > .entry-summary {
	margin-top: 0 !important;
}

.single-product .bs-product-top > .summary > *:first-child,
.single-product .bs-product-top > .entry-summary > *:first-child,
.single-product .product_title {
	margin-top: 0 !important;
	padding-top: 0 !important;
}

/* WooCommerce prints this wrapper whether or not there is a notice in it,
   and a whitespace-only wrapper does not match :empty. */
.single-product .bs-product-top > .woocommerce-notices-wrapper {
	margin: 0;
	padding: 0;
}


/* --- 24.3 The gallery pins, and stays pinned to the Details panel -------

   position: sticky dies inside ANY ancestor with a clipping overflow.
   overflow-x: clip on the root and body stops sideways scrolling exactly
   as hidden does, but does not create a scroll container, so the pin
   survives. functions.php walks the real ancestor chain at run time and
   opens anything this list has not anticipated.

   .bs-product-top ends where the Details panel begins, so the row is the
   pin's containing block and the photo releases at exactly the point
   asked for.                                                          */

@media (min-width: 900px) {

	/* Scoped to the product page, so no other template inherits a root
	   overflow it did not ask for. The :not() matters: the cart drawer
	   locks the page with body.bs-drawer-open { overflow: hidden }, which
	   has the same specificity as this rule and sits above it in the
	   file — without the guard, this would quietly beat it and the page
	   would scroll behind the open drawer.

	   Browsers without :has() drop the first selector; the ancestor walk
	   in functions.php covers them. */
	html:has(body.single-product),
	body.single-product:not(.bs-drawer-open) {
		overflow-x: clip;
		overflow-y: visible;
	}

	.single-product #page,
	.single-product .site,
	.single-product #content,
	.single-product .site-content,
	.single-product .site-content > .col-full,
	.single-product #primary,
	.single-product .content-area,
	.single-product #main,
	.single-product .site-main,
	.single-product div.product,
	.single-product .bs-product-top {
		overflow: visible !important;
	}

	.single-product .bs-product-top > .woocommerce-product-gallery {
		position: sticky !important;
		top: calc(var(--bs-header-h) + var(--bs-space-4));
		max-height: calc(100vh - var(--bs-header-h) - var(--bs-space-8));
		overflow-y: auto;
		scrollbar-width: none;
		z-index: 1;
	}

	/* A tall photo may scroll its own last pixels into view, but the wheel
	   must carry on to the page once it reaches the end — contain would
	   trap it over the gallery. */
	.single-product .bs-product-top > .woocommerce-product-gallery {
		overscroll-behavior-y: auto;
	}

	.single-product .bs-product-top > .woocommerce-product-gallery::-webkit-scrollbar {
		width: 0;
	}

	.admin-bar.single-product .bs-product-top > .woocommerce-product-gallery {
		top: calc(var(--bs-header-h) + var(--bs-space-4) + 32px);
		max-height: calc(100vh - var(--bs-header-h) - var(--bs-space-8) - 32px);
	}
}


/* --- 24.4 The ritual set, inside the ritual box -------------------------

   The card carries the frame. The label inside it is drawn flat so there
   is no second border around the header row, and the product list sits
   under a hairline within the same box.                               */

.bs-buy-option-card {
	position: relative;
	margin-top: var(--bs-space-2);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-lg);
	background-color: var(--bs-bg);
	cursor: pointer;
	transition:
		border-color var(--bs-duration) var(--bs-ease),
		background-color var(--bs-duration) var(--bs-ease);
}

.bs-buy-option-card:hover {
	border-color: var(--bs-accent);
}

.bs-buy-option-card.is-selected {
	border-color: var(--bs-accent);
	background-color: var(--bs-accent-tint);
	box-shadow: inset 0 0 0 1px var(--bs-accent);
}

/* The label keeps its grid, loses its frame. */
.bs-buy-options .bs-buy-option-card > .bs-buy-option--set,
.bs-buy-options .bs-buy-option-card > .bs-buy-option--set.is-selected,
.bs-buy-options .bs-buy-option-card > .bs-buy-option--set:hover {
	margin: 0;
	border: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
	padding-bottom: var(--bs-space-3);
}

/* The saving flag now belongs to the card's top edge. */
.bs-buy-option-card > .bs-buy-option--set .bs-buy-option__flag {
	top: 0;
	right: var(--bs-space-4);
	transform: translateY(-50%);
}

/* The list, inside the box. */
.bs-buy-options .bs-buy-option-card > .bs-set {
	margin: 0;
	padding: var(--bs-space-3) var(--bs-space-4) var(--bs-space-4);
	border-top: 1px solid var(--bs-line);
}

.bs-buy-option-card.is-selected > .bs-set {
	border-top-color: var(--bs-accent);
}

.bs-buy-options .bs-buy-option-card > .bs-set .bs-set__list {
	padding-top: var(--bs-space-2);
}

/* Product links inside the card must still read and behave as links. */
.bs-buy-option-card a.bs-set__name,
.bs-buy-option-card a.bs-set__media {
	cursor: pointer;
}

.bs-buy-option-card a.bs-set__name:hover {
	color: var(--bs-accent-dark);
	text-decoration: underline;
	text-underline-offset: 2px;
}

@media (max-width: 480px) {

	.bs-buy-options .bs-buy-option-card > .bs-set {
		padding: var(--bs-space-3);
	}

	.bs-buy-option-card > .bs-buy-option--set .bs-buy-option__flag {
		right: var(--bs-space-3);
	}
}


/* ==========================================================================
   25. Quantity stepper beside Add to cart                        [v4.5.0]
   ========================================================================== */

/* --- 25.1 The spinner comes back ---------------------------------------- */

/* Section 21 hid the quantity field whenever the buy-box radios were present,
   on the reasoning that the radios were the quantity control. They are not:
   they choose between one product and five different ones, which leaves
   "two of this one" — a normal request on a repeat-purchase category —
   with nowhere to go. The field is visible again, as a stepper.

   This overrides the clip() rule in 22.x rather than deleting it, so the old
   behaviour is one commented-out block away. */
.bs-has-buy-options.single-product form.cart .quantity,
.single-product form.cart:has(.bs-buy-options) .quantity {
	position: relative;
	width: auto;
	height: auto;
	overflow: visible;
	clip: auto;
	clip-path: none;
	white-space: nowrap;
}

/* The button shared the row with nothing, so it was set to the full width.
   It now shares the row with the stepper and flexes into what is left. */
.bs-has-buy-options.single-product form.cart .single_add_to_cart_button,
.single-product form.cart:has(.bs-buy-options) .single_add_to_cart_button {
	width: auto;
	flex: 1 1 240px;
}

/* --- 25.2 Rows inside the buy form -------------------------------------- */

/* form.cart is a wrapping flex row, so each block has to claim its own line.
   flex-basis of 100% forces the break; max-width: max-content then pulls the
   used width back to the content, which is what keeps the delivery badge a
   self-width pill instead of stretching it into a second button. */
.single-product form.cart .bs-buy-options {
	flex: 0 0 100%;
	max-width: 100%;
}

.single-product form.cart .bs-ship-nudge {
	flex: 0 0 100%;
	max-width: max-content;
}

/* --- 25.3 The stepper --------------------------------------------------- */

.single-product form.cart .quantity {
	display: inline-flex;
	align-items: center;
	flex: 0 0 auto;
	margin: 0;
	padding: 3px;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-button);
	transition: border-color var(--bs-duration) var(--bs-ease);
}

.single-product form.cart .quantity:focus-within {
	border-color: var(--bs-accent);
}

.single-product form.cart .quantity .bs-qty-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 38px;
	height: 38px;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background-color: transparent;
	color: var(--bs-ink);
	font-family: inherit;
	font-size: var(--bs-text-lg);
	font-weight: var(--bs-weight-medium);
	line-height: 1;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
	transition:
		background-color var(--bs-duration) var(--bs-ease),
		color var(--bs-duration) var(--bs-ease);
}

.single-product form.cart .quantity .bs-qty-btn:hover,
.single-product form.cart .quantity .bs-qty-btn:focus-visible {
	background-color: var(--bs-accent-tint);
	color: var(--bs-accent-dark);
}

/* Disabled means the stock ceiling or the floor of one has been reached.
   It stays visible and keeps its space — a control that disappears at the
   edge of its range reads as a bug. */
.single-product form.cart .quantity .bs-qty-btn:disabled {
	opacity: 0.3;
	cursor: default;
	background-color: transparent;
	color: var(--bs-ink);
}

/* The number itself: no chrome, no native arrows. The arrows are ~8px tall
   and the least tappable control WooCommerce ships. */
.single-product form.cart .quantity .qty {
	width: 42px;
	height: 38px;
	min-height: 0;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background-color: transparent;
	box-shadow: none;
	color: var(--bs-ink);
	font-size: var(--bs-text-base);
	font-weight: var(--bs-weight-medium);
	line-height: 38px;
	text-align: center;
	font-variant-numeric: tabular-nums;
	-moz-appearance: textfield;
	appearance: textfield;
}

.single-product form.cart .quantity .qty::-webkit-outer-spin-button,
.single-product form.cart .quantity .qty::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

.single-product form.cart .quantity .qty:focus,
.single-product form.cart .quantity .qty:focus-visible {
	outline: 0;
	box-shadow: none;
	background-color: transparent;
}

/* --- 25.4 The × N marker ------------------------------------------------ */

/* The stepper multiplies whichever option is selected, so every figure in the
   buy box moves with it — including the line prices, or the set would visibly
   stop adding up to its own total. These markers say out loud what the
   arithmetic is doing, and stay hidden at a quantity of one so the default
   state reads exactly as it did before. */
.bs-buy-option__multi {
	font-weight: var(--bs-weight-bold);
	color: var(--bs-accent-dark);
	white-space: nowrap;
}

.bs-buy-option__multi[hidden] {
	display: none;
}

/* --- 25.5 Narrow screens ------------------------------------------------ */

@media (max-width: 480px) {

	.single-product form.cart .quantity .bs-qty-btn {
		width: 36px;
		height: 36px;
	}

	.single-product form.cart .quantity .qty {
		width: 36px;
		height: 36px;
		line-height: 36px;
	}

	.bs-has-buy-options.single-product form.cart .single_add_to_cart_button,
	.single-product form.cart:has(.bs-buy-options) .single_add_to_cart_button,
	.single-product form.cart .single_add_to_cart_button {
		flex: 1 1 150px;
	}
}


/* ==========================================================================
   25. Product gallery: arrows, and a horizontal thumbnail rail on phones
       [NEW 4.5.0]

   Section 23 gave the gallery a vertical thumbnail rail beside the photo
   from 700px up. That is the right shape on a desktop and the wrong one on
   a phone, where the same rule left the thumbnails wrapping into a block of
   rows that pushed the price and the button off the first screen — and
   below 700px there was no rail at all, just a wrapped grid.

   Everything here is scoped to max-width: 899px or to the arrows, so the
   desktop two-column layout built in section 23 is untouched.
   ========================================================================== */

/* --- 25.1 Previous / next over the photo -------------------------------

   FlexSlider prints .flex-direction-nav; the fallback in functions.php
   prints .bs-gallery-nav with the same two positions. Both are drawn here
   so the control looks identical whether or not the slider initialised.

   The chevron is a rotated square built from two borders rather than an
   icon font: FlexSlider's default arrows use a font this theme does not
   load, which is why they would otherwise render as a stray letter.     */

.woocommerce-product-gallery {
	position: relative;
}

/* WooCommerce positions the nav list itself and reveals the arrows only on
   :hover, which on a touchscreen means never. The list and its items are
   flattened so the anchors position against the gallery box instead, and
   the visibility rules are forced — the core selectors carry more weight
   than these do, so specificity alone would not win. */
.single-product .flex-direction-nav,
.single-product .bs-gallery-nav {
	position: static !important;
	width: auto !important;
	height: auto !important;
	margin: 0;
	padding: 0;
	list-style: none;
}

.single-product .flex-direction-nav li {
	position: static !important;
	width: auto !important;
	margin: 0;
	padding: 0;
	list-style: none;
}

.single-product .flex-direction-nav a,
.single-product .bs-gallery-nav__btn {
	position: absolute !important;
	top: 50% !important;
	bottom: auto !important;
	z-index: 3;
	display: flex !important;
	align-items: center;
	justify-content: center;
	width: 44px !important;           /* 44px is the minimum comfortable tap target */
	height: 44px !important;
	margin: 0 !important;
	padding: 0;
	text-indent: 0 !important;
	visibility: visible !important;
	transform: translateY(-50%);
	border: 1px solid var(--bs-line);
	border-radius: 50%;
	background-color: rgba(255, 255, 255, 0.92);
	box-shadow: 0 1px 6px rgba(0, 0, 0, 0.10);
	color: var(--bs-ink);
	font-size: 0 !important;          /* kills FlexSlider's icon-font glyph */
	text-decoration: none;
	cursor: pointer;
	opacity: 1 !important;
	transition:
		background-color var(--bs-duration) var(--bs-ease),
		border-color var(--bs-duration) var(--bs-ease),
		transform var(--bs-duration) var(--bs-ease);
	-webkit-tap-highlight-color: transparent;
}

/* FlexSlider hides its arrows until the gallery is hovered, which on a
   touchscreen means never. */
.single-product .flex-direction-nav a {
	overflow: hidden;
}

.single-product .flex-direction-nav a::before,
.single-product .flex-direction-nav a::after {
	content: none !important;         /* the icon font glyph */
}

.single-product .flex-direction-nav .flex-prev,
.single-product .bs-gallery-nav__btn--prev {
	left: var(--bs-space-3);
}

.single-product .flex-direction-nav .flex-next,
.single-product .bs-gallery-nav__btn--next {
	right: var(--bs-space-3);
}

/* The chevron itself. */
.single-product .flex-direction-nav a > span,
.single-product .flex-direction-nav a::first-line {
	font-size: 0;
}

.single-product .bs-gallery-nav__btn::after,
.single-product .flex-direction-nav a::after {
	content: '' !important;
	display: block;
	width: 9px;
	height: 9px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	border-radius: 1px;
}

.single-product .bs-gallery-nav__btn--next::after,
.single-product .flex-direction-nav .flex-next::after {
	transform: translateX(-2px) rotate(-45deg);
}

.single-product .bs-gallery-nav__btn--prev::after,
.single-product .flex-direction-nav .flex-prev::after {
	transform: translateX(2px) rotate(135deg);
}

.single-product .flex-direction-nav a:hover,
.single-product .bs-gallery-nav__btn:hover {
	background-color: #fff;
	border-color: var(--bs-accent);
	color: var(--bs-accent);
}

.single-product .flex-direction-nav a:focus-visible,
.single-product .bs-gallery-nav__btn:focus-visible {
	outline: 2px solid var(--bs-accent);
	outline-offset: 2px;
}

.single-product .flex-direction-nav a:active,
.single-product .bs-gallery-nav__btn:active {
	transform: translateY(-50%) scale(0.94);
}

/* A single-image gallery has nothing to page through. FlexSlider marks the
   ends with .flex-disabled when looping is off; with one slide it disables
   both, which is the cue to take the whole control away. */
.single-product .flex-direction-nav .flex-disabled {
	opacity: 0 !important;
	pointer-events: none;
}

/* The zoom trigger sits top-right; nudge the next arrow clear of it only
   where they would actually collide. */
@media (min-width: 900px) {
	.single-product .woocommerce-product-gallery__trigger {
		z-index: 4;
	}
}

@media (prefers-reduced-motion: reduce) {
	.single-product .flex-direction-nav a,
	.single-product .bs-gallery-nav__btn {
		transition: none;
	}
}


/* --- 25.2 Phones and small tablets: thumbnails in one scrolling row -----

   This block has to undo the two-column grid from section 23, which starts
   at 700px and so was also catching landscape phones and small tablets.
   Below 900px the gallery is a plain block again: photo, then a single row
   of thumbnails that scrolls sideways.                                  */

@media (max-width: 899px) {

	.bs-has-gallery-thumbs.single-product div.product .woocommerce-product-gallery,
	.single-product div.product .woocommerce-product-gallery:has(.flex-control-thumbs) {
		display: block;
		grid-template-columns: none;
		gap: 0;
		padding: var(--bs-space-3);
	}

	.bs-has-gallery-thumbs.single-product .woocommerce-product-gallery > .flex-viewport,
	.bs-has-gallery-thumbs.single-product .woocommerce-product-gallery > .woocommerce-product-gallery__wrapper,
	.single-product .woocommerce-product-gallery:has(.flex-control-thumbs) > .flex-viewport,
	.single-product .woocommerce-product-gallery:has(.flex-control-thumbs) > .woocommerce-product-gallery__wrapper {
		grid-column: auto;
		grid-row: auto;
		width: 100%;
	}

	/* One row, scrolling sideways, snapping to each thumbnail. */
	.bs-has-gallery-thumbs.single-product .woocommerce-product-gallery .flex-control-thumbs,
	.single-product .woocommerce-product-gallery .flex-control-thumbs {
		display: flex;
		flex-direction: row;
		flex-wrap: nowrap;
		grid-column: auto;
		grid-row: auto;
		gap: var(--bs-space-2);
		max-height: none;
		margin: var(--bs-space-3) 0 0;
		padding: 2px 2px 6px;
		overflow-x: auto;
		overflow-y: hidden;
		scroll-snap-type: x proximity;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
		overscroll-behavior-x: contain;
	}

	.single-product .woocommerce-product-gallery .flex-control-thumbs::-webkit-scrollbar {
		width: 0;
		height: 0;
	}

	.single-product .woocommerce-product-gallery .flex-control-thumbs li {
		flex: 0 0 auto;
		width: auto !important;
		scroll-snap-align: start;
	}

	.bs-has-gallery-thumbs.single-product .woocommerce-product-gallery .flex-control-thumbs img,
	.single-product .woocommerce-product-gallery .flex-control-thumbs img {
		width: 64px;
		height: 64px;
		aspect-ratio: 1 / 1;
	}

	/* The active thumbnail needs to be obvious on a strip that runs off the
	   edge of the screen — a hairline colour change is not enough. */
	.single-product .flex-control-thumbs img.flex-active {
		border-color: var(--bs-accent);
		box-shadow: 0 0 0 1px var(--bs-accent);
	}

	/* Arrows sit inboard a little on a narrow screen so they do not cover
	   the edges of the photo itself. */
	.single-product .flex-direction-nav a,
	.single-product .bs-gallery-nav__btn {
		width: 38px !important;
		height: 38px !important;
	}

	.single-product .flex-direction-nav .flex-prev,
	.single-product .bs-gallery-nav__btn--prev {
		left: var(--bs-space-2);
	}

	.single-product .flex-direction-nav .flex-next,
	.single-product .bs-gallery-nav__btn--next {
		right: var(--bs-space-2);
	}
}


/* --- 25.3 Fallback when FlexSlider never runs --------------------------

   wc-single-product.js is deferred, and if it fails or is blocked the
   gallery stays as a raw stack of every image at full width — which is
   what a "broken gallery" usually turns out to be. functions.php detects
   that state and adds .bs-gallery--plain; the stack then becomes the same
   horizontal, snapping track the arrows already know how to drive.     */

.single-product .bs-gallery--plain .woocommerce-product-gallery__wrapper {
	display: flex;
	flex-wrap: nowrap;
	gap: 0;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
}

.single-product .bs-gallery--plain .woocommerce-product-gallery__wrapper::-webkit-scrollbar {
	width: 0;
	height: 0;
}

.single-product .bs-gallery--plain .woocommerce-product-gallery__image {
	flex: 0 0 100%;
	width: 100%;
	max-width: 100%;
	scroll-snap-align: center;
}

.single-product .bs-gallery--plain .bs-gallery-nav {
	position: static;
}


/* ==========================================================================
   22. Cart drawer: three-step reward rail, coupon chips, upsell rail
   Appended rather than folded into 19.2 / 21.2 so the earlier blocks stay
   readable and this whole feature can be lifted out in one piece.
   ========================================================================== */

/* --- 22.1 Reward rail: one hairline, three dots --------------------------

   Stripped back from the previous version: the 26px numbered/ticked circles
   and the separate amounts row above the track were doing the work of a
   dashboard on a component that only has to answer "how far along am I".
   What is left is one hairline, a small dot per milestone, and a single
   caption stack under each dot.

   Stops are spaced EVENLY, not proportionally. On a true 0–499 scale the
   AED 100 milestone lands at a fifth of the width and the most winnable step
   looks like the least reachable one. The fill still interpolates *within*
   each equal segment, so movement stays honest: a basket half way from 100
   to 299 fills half of segment two.
   ------------------------------------------------------------------------ */

.bs-rail {
	--bs-rail-edge: 8px;    /* breathing room for the end dot and its caption */
	--bs-rail-dot:  9px;

	/* Caption geometry as three numbers rather than a pile of min-heights.
	   --bs-rail-line is the exact height of one caption line, and it is used
	   both as the row's height and as the caption's line-height, so a row is
	   the text and nothing else. --bs-rail-gap is then the real, visible
	   distance from the track to the type — and because the same value feeds
	   both rows, the amount above the rail sits exactly as far from it as the
	   reward below. The old rows reserved 1rem above and 1.8rem below for
	   captions that never wrapped, which is where the dead band between the
	   thresholds and the track came from. */
	--bs-rail-cap:  0.6875rem;
	--bs-rail-line: 0.9375rem;
	--bs-rail-gap:  6px;

	margin-top: var(--bs-space-2);
}

.bs-rail__chart {
	position: relative;
	padding: 0 var(--bs-rail-edge);
}

/* How many stops the ladder has, for the caption slot maths below. Set from
   an attribute rather than an inline style: the server-rendered rail passes
   through wp_kses, which drops custom properties out of style="". Three is
   the shipped ladder; the rest are here so a filtered bs_reward_tiers does
   not silently fall back to the wrong geometry. */
.bs-rail__chart[data-steps="2"] { --bs-rail-steps: 2; }
.bs-rail__chart[data-steps="3"] { --bs-rail-steps: 3; }
.bs-rail__chart[data-steps="4"] { --bs-rail-steps: 4; }
.bs-rail__chart[data-steps="5"] { --bs-rail-steps: 5; }

/* --- the track ---------------------------------------------------------- */

.bs-rail__track {
	position: relative;
	height: 3px;
	border-radius: 999px;
	background-color: rgba(20, 32, 26, 0.14);
}

.bs-rail__fill {
	display: block;
	height: 100%;
	width: 0;
	border-radius: 999px;
	background-color: var(--bs-accent);
	transition: width 320ms cubic-bezier(0.32, 0.72, 0, 1);
}

.bs-rail.is-complete .bs-rail__fill {
	background-color: var(--bs-success);
}

/* --- the stops ----------------------------------------------------------

   Centred on the track, so the fill runs *through* each dot and colours it
   in on the way past. No numbers, no ticks: at this size the position of
   the dot relative to the fill already says done or not done. */

.bs-rail__stop {
	position: absolute;
	top: 50%;
	width: var(--bs-rail-dot);
	height: var(--bs-rail-dot);
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background-color: var(--bs-surface);
	box-shadow: inset 0 0 0 1.5px rgba(20, 32, 26, 0.18);
	transition: background-color var(--bs-duration) ease,
	            box-shadow var(--bs-duration) ease;
}

/* The one being worked towards: ringed, not filled. A filled dot would read
   as already earned. */
.bs-rail__stop.is-next {
	box-shadow: inset 0 0 0 2px var(--bs-accent);
}

.bs-rail__stop.is-done {
	background-color: var(--bs-accent);
	box-shadow: none;
}

.bs-rail.is-complete .bs-rail__stop.is-done {
	background-color: var(--bs-success);
}

/* --- the captions -------------------------------------------------------

   One column per stop, split across the track: the threshold sits above the
   dot, the reward it buys sits below it.

   Stacking both under the track put four lines of 11px type in a block and
   made the amount and the reward compete to be read first. Straddling the
   rail separates the two questions the shopper is actually asking — how much
   more, and for what — and the dot itself becomes the join between them. */

/* Each row is exactly one caption tall. height rather than min-height, and
   font-size/line-height zeroed, so the row can never pick up a stray line box
   from the markup or a reserve it does not use: whatever is left between the
   type and the track is --bs-rail-gap and only that. */
.bs-rail__steps {
	position: relative;
	height: var(--bs-rail-line);
	min-height: 0;
	margin: 0;
	font-size: 0;
	line-height: 0;
}

.bs-rail__steps--above {
	margin-bottom: var(--bs-rail-gap);
}

.bs-rail__steps--below {
	margin-top: var(--bs-rail-gap);
}

/* Amounts hang off the bottom of their row, rewards off the top of theirs, so
   both sit --bs-rail-gap from the track and the milestone reads as one column
   split by the dot. */
.bs-rail__steps--above .bs-rail__step {
	top: auto;
	bottom: 0;
}

.bs-rail__steps--below .bs-rail__step {
	top: 0;
	bottom: auto;
}

/* Each caption gets one slot of the track and no more. The old fixed 92px
   box was fine on the cart page and overlapped its neighbour inside the
   420px drawer, which is how "Extra 10% offAED 100 off" happened. Slots are
   a share of the track instead, so the rail cannot outgrow its own labels at
   any width. --bs-rail-steps is written onto .bs-rail__chart by whichever
   side rendered it. */
.bs-rail__step {
	position: absolute;
	display: block;
	margin: 0;
	padding: 0;
	width: calc(100% / var(--bs-rail-steps, 3));
	transform: translateX(-50%);
	text-align: center;
	font-size: var(--bs-rail-cap);
	line-height: var(--bs-rail-line);
	white-space: nowrap;
}

/* The last stop sits on the track's right edge, so it only has half a slot
   to its left before it runs into its neighbour. Pinned flush to the outer
   edge and given exactly that half, rather than hanging off the panel or
   sitting on top of the caption before it. Mirrored for a stop that ever
   lands at zero. */
.bs-rail__step.is-end {
	left: auto;
	right: calc(var(--bs-rail-edge) * -1);
	width: calc(50% / var(--bs-rail-steps, 3) + var(--bs-rail-edge));
	transform: none;
	text-align: right;
}

.bs-rail__step.is-start {
	left: calc(var(--bs-rail-edge) * -1);
	right: auto;
	width: calc(50% / var(--bs-rail-steps, 3) + var(--bs-rail-edge));
	transform: none;
	text-align: left;
}

/* Size and leading come from .bs-rail__step, so one variable moves the whole
   caption row and the row height cannot drift away from the type in it. */
.bs-rail__amount,
.bs-rail__label {
	display: block;
	margin: 0;
	font-size: inherit;
	line-height: inherit;
	color: var(--bs-ink-soft);
}

.bs-rail__amount {
	font-variant-numeric: tabular-nums;
}

.bs-rail__step.is-done .bs-rail__amount,
.bs-rail__step.is-next .bs-rail__amount {
	color: var(--bs-accent-dark);
}

.bs-rail__step.is-done .bs-rail__label,
.bs-rail__step.is-next .bs-rail__label {
	color: var(--bs-accent-dark);
	font-weight: var(--bs-weight-bold);
}


/* --- 22.1b The same rail on the cart and checkout pages ------------------
   Printed into the block checkout sidebar and above the classic cart table,
   replacing the free-delivery-only bar that used to live there. Same
   component, same numbers, so the drawer and the checkout cannot disagree.
   ------------------------------------------------------------------------ */

.bs-reward-panel {
	margin: 0 0 var(--bs-space-4);
	padding: var(--bs-space-3) var(--bs-space-4);
	background-color: var(--bs-accent-tint);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius);
}

/* Sentence on the left, the earned code on the right, both above the rail.
   The code used to sit at the bottom behind a dashed rule and an intro
   line, which put the one thing the shopper has to carry to the checkout
   at the very end of the panel. */
.bs-reward-panel__head,
.bs-tiers__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--bs-space-1) var(--bs-space-3);
	flex-wrap: wrap;
}

/* Once a code is earned the sentence is deliberately empty: a shopper holding
   ATC10 does not need to be told, in the same breath, how far they are from
   the next thing. An empty <p> would still take a line and reopen the gap the
   rest of this section closes, so it comes out of the flow entirely. */
.bs-reward-panel__message:empty,
.bs-tiers__message:empty {
	display: none;
}

/* With no sentence to sit opposite, the chip stops being a right-hand badge
   and becomes the content: chip first, then the one line saying where to put
   it, on a single left-aligned row. */
.bs-reward-panel__message:empty + .bs-codes,
.bs-tiers__message:empty + .bs-codes {
	flex-direction: row;
	align-items: center;
	gap: var(--bs-space-2);
	margin-right: auto;
}

.bs-reward-panel__message:empty + .bs-codes .bs-code__note,
.bs-tiers__message:empty + .bs-codes .bs-code__note {
	text-align: left;
}

.bs-reward-panel__message {
	flex: 1 1 auto;
	margin: 0;
	font-size: var(--bs-text-sm);
	line-height: 1.4;
	color: var(--bs-accent-dark);
	max-width: none;
}

.bs-reward-panel__message strong,
.bs-reward-panel__message span {
	font-weight: var(--bs-weight-bold);
}

/* Same head row in the drawer, where the sentence keeps its own type scale
   but loses the bottom margin it had as a standalone block. */
.bs-tiers__head .bs-tiers__message {
	flex: 1 1 auto;
	margin: 0;
}

/* The checkout sidebar is a narrow column and the panel is the first thing
   in it, so it carries the top margin the sidebar's own first child had. */
.wc-block-components-sidebar > .bs-reward-panel {
	margin-bottom: var(--bs-space-4);
}

.wp-block-woocommerce-cart .bs-reward-panel {
	margin-bottom: var(--bs-space-5);
}

/* Nothing to show until the totals have actually loaded. */
.bs-reward-panel:not([data-bs-stamp]) {
	display: none;
}


/* --- 22.2 The earned code -----------------------------------------------

   One code, never a row of them: a basket over 499 has cleared both coupon
   tiers, but only one can be applied at checkout, so offering both means
   one of them gets typed in and rejected. The chip is the code and nothing
   else — the word COPY next to it was labelling what the whole button
   already does.

   Shown only once the basket qualifies. A code offered early gets typed in,
   rejected at checkout, and read as bait. */

/* Chip on top, instruction under it. The chip alone reads as a receipt for a
   discount already applied — shoppers tap to copy, take the copying for the
   whole job, and walk past the coupon field. The line says where it goes. */
.bs-codes {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 2px;
	flex: none;
	margin: 0;
}

.bs-code__note {
	font-size: 0.625rem;
	line-height: 1.2;
	color: var(--bs-ink-soft);
	text-align: right;
}

.bs-code {
	appearance: none;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 10px;
	border: 1px dashed var(--bs-accent);
	border-radius: 999px;
	background-color: var(--bs-surface);
	color: var(--bs-accent-dark);
	line-height: 1;
	transition: background-color var(--bs-duration) ease,
	            border-color var(--bs-duration) ease;
}

.bs-code:hover,
.bs-code:focus-visible {
	background-color: var(--bs-accent-tint);
}

.bs-code__value {
	font-size: var(--bs-text-xs);
	font-weight: var(--bs-weight-bold);
	letter-spacing: 0.06em;
}

.bs-code__icon {
	display: block;
	flex: none;
	width: 13px;
	height: 13px;
	opacity: 0.5;
}

.bs-code__icon--done {
	display: none;
}

.bs-code.is-copied {
	border-style: solid;
	border-color: var(--bs-success);
	background-color: var(--bs-accent-tint);
}

.bs-code.is-copied .bs-code__icon--copy {
	display: none;
}

.bs-code.is-copied .bs-code__icon--done {
	display: block;
	opacity: 1;
	color: var(--bs-success);
}


/* --- 22.2b The gift set picker ------------------------------------------

   Sits directly under the reward rail on the cart and checkout, and only once
   the basket actually holds the gift. It is a swap control, not a claim form:
   the set is already in the cart by the time this appears, so the visual job
   is "which of these two", not "act now or lose it".

   Which is why it is deliberately quieter than the rail above it. The rail is
   selling the next threshold; this is settling a preference on a reward
   already banked, and dressing it up as a second offer would put two competing
   pieces of urgency in the same column of a checkout.
   ------------------------------------------------------------------------ */

.bs-giftpick {
	margin: 0 0 var(--bs-space-4);
	padding: var(--bs-space-3) var(--bs-space-4) var(--bs-space-4);
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius);
}

/* Nothing to show until the script has decided there is a gift to swap. */
.bs-giftpick:not([data-bs-state]) {
	display: none;
}

.bs-giftpick__head {
	margin-bottom: var(--bs-space-3);
}

.bs-giftpick__title {
	margin: 0;
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-bold);
	line-height: 1.3;
	color: var(--bs-ink);
}

.bs-giftpick__intro {
	margin: 2px 0 0;
	font-size: var(--bs-text-xs);
	line-height: 1.35;
	color: var(--bs-ink-soft);
	max-width: none;
}

/* Side by side where there is room, stacked in the checkout's narrow sidebar.
   Two cards squeezed into a 320px column stop being readable options and start
   being a pair of buttons with truncated labels. */
.bs-giftpick__options {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--bs-space-2);
}

@media (min-width: 900px) {

	.wp-block-woocommerce-cart .bs-giftpick__options {
		grid-template-columns: 1fr 1fr;
	}
}

.bs-giftpick__option {
	appearance: none;
	cursor: pointer;
	display: flex;
	align-items: flex-start;
	gap: var(--bs-space-3);
	width: 100%;
	margin: 0;
	padding: var(--bs-space-3);
	text-align: left;
	background-color: var(--bs-surface);
	border: 1px solid var(--bs-line);
	border-radius: var(--bs-radius-sm);
	color: var(--bs-ink);
	transition: border-color var(--bs-duration) var(--bs-ease),
	            background-color var(--bs-duration) var(--bs-ease);
}

.bs-giftpick__option:hover {
	border-color: var(--bs-accent);
}

.bs-giftpick__option:focus-visible {
	outline: 2px solid var(--bs-accent);
	outline-offset: 2px;
}

.bs-giftpick__option.is-chosen {
	border-color: var(--bs-accent);
	background-color: var(--bs-accent-tint);
}

/* The whole card is the control, so the dot is a state readout rather than a
   hit target — it carries no pointer events and no label of its own. */
.bs-giftpick__mark {
	flex: none;
	position: relative;
	width: 18px;
	height: 18px;
	margin-top: 1px;
	border: 1px solid var(--bs-line);
	border-radius: 50%;
	background-color: var(--bs-surface);
	transition: border-color var(--bs-duration) var(--bs-ease);
}

.bs-giftpick__option.is-chosen .bs-giftpick__mark {
	border-color: var(--bs-accent);
}

.bs-giftpick__option.is-chosen .bs-giftpick__mark::after {
	content: "";
	position: absolute;
	inset: 3px;
	border-radius: 50%;
	background-color: var(--bs-accent);
}

.bs-giftpick__body {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

.bs-giftpick__name {
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-medium);
	line-height: 1.3;
}

.bs-giftpick__option.is-chosen .bs-giftpick__name {
	color: var(--bs-accent-dark);
	font-weight: var(--bs-weight-bold);
}

.bs-giftpick__note {
	font-size: var(--bs-text-xs);
	line-height: 1.35;
	color: var(--bs-ink-soft);
}

/* The price the shopper is not paying. An unpriced free box is worth far less
   in the head than the same box with AED 150 struck through it, which is the
   whole argument for keeping these products in the catalogue at full price. */
.bs-giftpick__worth {
	margin-top: 2px;
	font-size: 0.6875rem;
	font-weight: var(--bs-weight-bold);
	line-height: 1.2;
	letter-spacing: 0.02em;
	color: var(--bs-accent);
}

.bs-giftpick__status {
	margin: var(--bs-space-2) 0 0;
	font-size: var(--bs-text-xs);
	line-height: 1.35;
	color: var(--bs-ink-soft);
}

/* Dimmed rather than removed while the swap is in flight: the cards keep their
   size, so the summary below does not jump while the cart refetches. */
.bs-giftpick.is-busy .bs-giftpick__options {
	opacity: 0.55;
}

.bs-giftpick.is-busy .bs-giftpick__option {
	cursor: progress;
}

@media (prefers-reduced-motion: reduce) {

	.bs-giftpick__option,
	.bs-giftpick__mark {
		transition: none;
	}
}


/* --- 22.3 Upsell rail ---------------------------------------------------
   Rides on the .bs-addon grid already defined in 19.3. Only the bits that
   block was never asked to handle are set here: a linked product name, and
   a placeholder for the occasional catalogue row with no image. */

.bs-addons__title {
	text-transform: none;
	letter-spacing: 0;
	font-size: var(--bs-text-sm);
	color: var(--bs-ink);
}

a.bs-addon__name {
	color: inherit;
	text-decoration: none;
}

a.bs-addon__name:hover,
a.bs-addon__name:focus-visible {
	text-decoration: underline;
}

span.bs-addon__image {
	display: block;
	background-color: var(--bs-surface-sunk);
	border: 1px solid var(--bs-line);
}


/* --- 22.4 Narrow screens ------------------------------------------------
   Three labels across a 320px drawer is the tight case. Shrink the type
   rather than dropping a step: a two-step rail misreports the ladder. */

@media (max-width: 420px) {

	/* The whole caption block is three variables now, so a narrow drawer is a
	   change of numbers rather than a second set of layout rules. */
	.bs-rail {
		--bs-rail-edge: 7px;
		--bs-rail-dot: 8px;
		--bs-rail-cap: 0.625rem;
		--bs-rail-line: 0.875rem;
		--bs-rail-gap: 5px;
	}

	.bs-code__note {
		font-size: 0.5625rem;
	}

	.bs-reward-panel {
		padding: var(--bs-space-3);
	}

	.bs-tiers {
		padding: var(--bs-space-3);
	}
}

@media (prefers-reduced-motion: reduce) {

	.bs-rail__fill,
	.bs-rail__stop {
		transition: none !important;
	}
}


/* ==========================================================================
   26. Product card: the rating and price block               [NEW in 4.7.0]

   The card had three separate problems stacked on top of each other, which
   is why it read as messy rather than as any one thing being wrong.

   26.1  The review count sat at the far right of the card, a whole column
         away from its stars. WooCommerce sets `margin: 0 auto .5em` on
         .star-rating inside a loop item. Inside the flex row that is
         .bs-rating, those auto margins absorb every pixel of free space and
         shove the count against the opposite edge. Section 19 already tried
         `.bs-rating .star-rating { margin: 0 }` — two classes against
         WooCommerce's four, so it never applied.

   26.2  Cards with a review were one row taller than cards without one, and
         cards whose size could not be parsed were one row shorter than the
         rest, so no two prices in a shelf landed at the same height. Both
         rows are now always printed, empty when there is nothing to say,
         with their height reserved here. See bs_loop_rating() and
         bs_loop_unit_price() in functions.php.

   26.3  The was-price printed before the now-price, because that is the
         order WooCommerce writes <del> and <ins>. The eye should land on
         what the thing costs, so the order is swapped visually and the
         was-price loses its currency symbol — it is the same currency as
         the number beside it, and repeating it is noise.

   Order in the block, top to bottom: stars, price, price per 100g.
   ========================================================================== */


/* --- 26.1 One block, one rhythm ---------------------------------------- */

.woocommerce ul.products li.product .bs-card-meta,
ul.products li.product .bs-card-meta {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--bs-space-2);
	width: 100%;
	margin: 0 0 var(--bs-space-4);
}

/* Every card in a row is as tall as the tallest, so `margin-top: auto` on
   the button has a common bottom edge to work from. */
.woocommerce ul.products,
ul.products {
	align-items: stretch;
}


/* --- 26.2 Stars and count, side by side --------------------------------- */

.woocommerce ul.products li.product .bs-rating,
ul.products li.product .bs-rating {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: var(--bs-space-2);
	margin: 0;
	line-height: 1;

	/* Held open on cards with no reviews too. */
	min-height: 1.15rem;
}

/* The auto margins described in 26.1. Marked important because WooCommerce's
   own stylesheet can be enqueued after the child theme's. */
.woocommerce ul.products li.product .bs-rating .star-rating,
ul.products li.product .bs-rating .star-rating {
	float: none;
	margin: 0 !important;
	font-size: 0.85rem;
	line-height: 1;
	height: 1em;
	color: var(--bs-amber);
}

.woocommerce ul.products li.product .bs-rating__count,
ul.products li.product .bs-rating__count {
	font-size: var(--bs-text-xs);
	font-weight: var(--bs-weight-normal);
	line-height: 1;
	color: var(--bs-ink-soft);
	font-variant-numeric: tabular-nums;
}


/* --- 26.3 Price --------------------------------------------------------- */

.woocommerce ul.products li.product .price,
ul.products li.product .price {
	display: flex;
	flex-direction: row;
	flex-wrap: nowrap;
	align-items: baseline;
	gap: var(--bs-space-2);
	margin: 0;
	font-size: var(--bs-text-lg);
	font-weight: var(--bs-weight-bold);
	line-height: 1.2;
	color: var(--bs-ink);
	font-variant-numeric: tabular-nums;

	/* The card titles are half Arabic. Isolating the price keeps its own
	   direction from being inherited from whatever ran before it. */
	direction: ltr;
	unicode-bidi: isolate;
	text-align: left;
}

/* Now-price first, was-price after it. */
.woocommerce ul.products li.product .price ins,
ul.products li.product .price ins {
	order: 0;
	background: none;
	text-decoration: none;
	font-weight: var(--bs-weight-bold);
	color: var(--bs-ink);

	/* Swap the two lines below for the warm sale colour instead:
	   color: var(--bs-amber);  */
}

.woocommerce ul.products li.product .price del,
ul.products li.product .price del {
	order: 1;
	margin: 0;
	opacity: 1;
	font-size: var(--bs-text-sm);
	font-weight: var(--bs-weight-normal);
	color: var(--bs-ink-soft);
	text-decoration: line-through;
	text-decoration-thickness: 1px;
}

/* One currency symbol per price line is enough. */
.woocommerce ul.products li.product .price del .woocommerce-Price-currencySymbol,
ul.products li.product .price del .woocommerce-Price-currencySymbol {
	display: none;
}

/* The format string in functions.php already supplies the space. */
.woocommerce ul.products li.product .price .woocommerce-Price-currencySymbol,
ul.products li.product .price .woocommerce-Price-currencySymbol {
	margin-inline-end: 0;
	font-weight: inherit;
}

/* Price ranges on variable products keep their en dash on one line. */
.woocommerce ul.products li.product .price .woocommerce-Price-amount,
ul.products li.product .price .woocommerce-Price-amount {
	white-space: nowrap;
}


/* --- 26.4 Price per 100g ------------------------------------------------ */

.woocommerce ul.products li.product .bs-unit-price,
ul.products li.product .bs-unit-price {
	display: block;
	margin: 0;
	font-size: var(--bs-text-xs);
	font-weight: var(--bs-weight-normal);
	line-height: 1;
	color: var(--bs-ink-soft);
	font-variant-numeric: tabular-nums;
	direction: ltr;
	unicode-bidi: isolate;

	/* Held open on cards with no parseable size. */
	min-height: 0.9rem;
}

/* Hide the per-100g line on cards and keep it on the product page:
   .woocommerce ul.products li.product .bs-unit-price { display: none; }  */


/* --- 26.5 Narrow screens ------------------------------------------------ */

@media (max-width: 480px) {

	.woocommerce ul.products li.product .price,
	ul.products li.product .price {
		font-size: var(--bs-text-base);
	}

	.woocommerce ul.products li.product .bs-card-meta,
	ul.products li.product .bs-card-meta {
		gap: var(--bs-space-1);
	}
}


/* ==========================================================================
   27. Product card: one column, one rhythm            [NEW in 4.8.0]
   --------------------------------------------------------------------------
   What was wrong, card by card, reading the shelf top to bottom:

   27.1  The card printed four stacked rows between the photo and the button —
         title, stars, price, price-per-100g — each holding its own height
         open. On a one-line title that came to roughly 40px of nothing
         between the name and the stars. The unit price is not a fourth
         thought; it is the price restated in comparable units, so it now
         shares the price's line and the card is one whole row shorter.
         See bs_loop_price_row_open() in functions.php.

   27.2  The price sat about 12px to the right of everything above it, so the
         card had two left edges: one for the title, the stars and the unit
         price, another for the number that matters most. The offset comes
         from outside this file — a padding, an auto margin or an indent in
         WooCommerce's own stylesheet, which is enqueued after the child
         theme — so it is reset from every direction below rather than
         guessed at.

   27.3  The title reserve stays, because it is the only thing keeping the
         prices on one line across a shelf without JavaScript, but it is now
         a token you can set: --bs-card-title-lines.

   Order in the block, top to bottom: title, stars + count, price + /100g.
   ========================================================================== */


/* --- 27.1 The one dial worth having ------------------------------------- */

:root {
	/* How many lines of product name a card holds open. Every card in a row
	   reserves the same height, which is what keeps the prices level.
	   Set it to 1 for a tighter shelf if your names are short. */
	--bs-card-title-lines: 2;
}


/* --- 27.2 Title: two lines at most, and no more space than it needs ------ */

.woocommerce ul.products li.product .woocommerce-loop-product__title,
ul.products li.product .woocommerce-loop-product__title {
	margin: 0 0 var(--bs-space-2);
	padding: 0;
	line-height: 1.35;

	-webkit-line-clamp: var(--bs-card-title-lines);
	line-clamp: var(--bs-card-title-lines);
	min-height: calc(var(--bs-card-title-lines) * 1.35em);
}


/* --- 27.3 The meta block: even gaps, nothing reserved twice -------------- */

.woocommerce ul.products li.product .bs-card-meta,
ul.products li.product .bs-card-meta {
	gap: var(--bs-space-2);
	margin: 0 0 var(--bs-space-3);
}

/* The stars row is held open on cards with no reviews, so that cards with
   and without them agree on where the price sits. One line, no more. */
.woocommerce ul.products li.product .bs-rating,
ul.products li.product .bs-rating {
	min-height: 1rem;
}


/* --- 27.4 Price and /100g, one line ------------------------------------- */

.woocommerce ul.products li.product .bs-price-row,
ul.products li.product .bs-price-row {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: flex-start;

	/* Room between the price and the unit price, less between the two when
	   a narrow card makes them wrap. */
	column-gap: var(--bs-space-3);
	row-gap: var(--bs-space-1);

	width: 100%;
	margin: 0;
	padding: 0;
}

/* Same font size as the price, normal weight, quiet colour — the template's
   treatment. It reads as part of the price, not as a footnote under it. */
.woocommerce ul.products li.product .bs-price-row .bs-unit-price,
ul.products li.product .bs-price-row .bs-unit-price {
	display: inline-block;
	min-height: 0;
	margin: 0;
	padding: 0;
	font-size: var(--bs-text-base);
	font-weight: var(--bs-weight-normal);
	line-height: 1.2;
	color: var(--bs-ink-soft);
	white-space: nowrap;
}


/* --- 27.5 One left edge for the whole card ------------------------------ */

/* Marked important where WooCommerce's stylesheet, enqueued after this one,
   sets its own margin on the same element. See the note in 27.2 above. */
.woocommerce ul.products li.product .price,
ul.products li.product .price {
	margin: 0 !important;
	padding: 0 !important;
	text-indent: 0;
	justify-content: flex-start;
	align-self: flex-start;
	max-width: 100%;
}

.woocommerce ul.products li.product .price::before,
ul.products li.product .price::before {
	content: none;
}

.woocommerce ul.products li.product .price > *:first-child,
ul.products li.product .price > *:first-child {
	margin-inline-start: 0 !important;
	padding-inline-start: 0;
}

/* And the three rows above it, so nothing can drift on its own. */
.woocommerce ul.products li.product .woocommerce-loop-product__title,
.woocommerce ul.products li.product .bs-rating,
.woocommerce ul.products li.product .bs-card-meta,
ul.products li.product .woocommerce-loop-product__title,
ul.products li.product .bs-rating,
ul.products li.product .bs-card-meta {
	padding-inline: 0;
	margin-inline: 0;
	text-indent: 0;
}

.woocommerce ul.products li.product .bs-rating .star-rating,
ul.products li.product .bs-rating .star-rating {
	margin-inline-start: 0 !important;
	padding-inline-start: 0;
}


/* --- 27.6 The grid itself ----------------------------------------------- */

/* Cards fill their track, so the buttons pinned with margin-top:auto share
   one bottom edge across the row. */
.woocommerce ul.products li.product,
ul.products li.product {
	height: 100%;
}

/* The photo is the loudest thing on the card and does not need a full
   space-4 below it as well as the title's own margin. */
.woocommerce ul.products li.product a img,
.woocommerce ul.products li.product img.woocommerce-placeholder,
ul.products li.product a img {
	margin-bottom: var(--bs-space-3);
}


/* --- 27.7 Narrow screens ------------------------------------------------ */

@media (max-width: 480px) {

	.woocommerce ul.products li.product .bs-card-meta,
	ul.products li.product .bs-card-meta {
		gap: var(--bs-space-1);
		margin-bottom: var(--bs-space-2);
	}

	/* Two columns of small cards: the unit price drops under the price
	   rather than squeezing it, and shrinks a step. */
	.woocommerce ul.products li.product .bs-price-row .bs-unit-price,
	ul.products li.product .bs-price-row .bs-unit-price {
		font-size: var(--bs-text-sm);
	}

	.woocommerce ul.products li.product .bs-price-row,
	ul.products li.product .bs-price-row {
		column-gap: var(--bs-space-2);
	}
}


/* --- 22.1c Keeping the last caption inside the panel ---------------------

   The layout above is unchanged: captions stay centred on their dots, the
   threshold above and the reward below. Only the final stop moves.

   It was pinned at right: -8px with half a slot to live in and set to
   nowrap, so "AED 150+ gift set" could not fit and ran left out of its slot
   instead. The fix for that is the wrapping below, not extra width: a full
   slot on the last stop reaches back to 66.7% of the track while the middle
   caption, centred on its own dot, still runs to 83.3% — the two sat on the
   same 16% of the rail, which is how "Extra 10% off" and "AED 150+ gift set"
   ended up printing as one string in the drawer.

   So the last stop gets exactly the half slot that is free between its
   neighbour's edge and the end of the rail, plus the chart's own edge
   padding, right-aligned. Wrapping does the rest. The slot gutter below
   then guarantees daylight between two captions that are both full.

   Deliberately last in the file, so it overrides section 22.1 without
   raising specificity.
   ------------------------------------------------------------------------ */

.bs-rail {
	/* Taken out of each slot rather than added between them, so a caption
	   column still lines up with the dot it belongs to. */
	--bs-rail-slot-gap: 6px;
}

.bs-rail__step {
	padding-left: var(--bs-rail-slot-gap);
	padding-right: var(--bs-rail-slot-gap);
}

.bs-rail__step.is-end {
	left: auto;
	right: calc(var(--bs-rail-edge) * -1);
	width: calc(50% / var(--bs-rail-steps, 3) + var(--bs-rail-edge));
	/* Gutter only on the side facing a neighbour. Padding the outer side
	   as well would pull the caption off the edge it is aligned to. */
	padding-right: 0;
	transform: none;
	text-align: right;
}

/* Mirrored, for a filtered ladder that ever puts a stop at zero. */
.bs-rail__step.is-start {
	left: calc(var(--bs-rail-edge) * -1);
	right: auto;
	width: calc(50% / var(--bs-rail-steps, 3) + var(--bs-rail-edge));
	padding-left: 0;
	transform: none;
	text-align: left;
}

@media (max-width: 420px) {

	.bs-rail {
		--bs-rail-slot-gap: 4px;
	}
}

/* Reward names wrap; thresholds do not. Three reward names side by side need
   about 253px of single-line type and the checkout sidebar's track is 221px,
   so on that column something has to give — and a name that must fit on one
   line is a name nobody is allowed to rewrite. Amounts stay on one line:
   they are short, tabular, and breaking "AED 499.00" reads as two numbers. */
.bs-rail__label {
	white-space: normal;
	overflow-wrap: break-word;
}

.bs-rail__amount {
	white-space: nowrap;
}

/* The captions are absolutely positioned, so the row cannot grow to fit a
   wrapped one — two lines are reserved. On a wide panel the second line is
   empty, which costs 15px and is what stops a wrapped name landing on the
   panel border. */
.bs-rail__steps--below {
	height: calc(var(--bs-rail-line) * 2);
}

/* Two lines are enough in the drawer and on the cart page. They are not on
   the 250px checkout sidebar, where "AED 150+" alone is wider than the slot
   and the name needs a third. That line has to be reserved on the column
   that needs it and nowhere else, so the test is the chart's own width
   rather than the viewport's.

   Two breakpoints because there are two caption sizes. Section 22.4 drops
   the caption from 11px to 10px below 420px of viewport, and a smaller
   caption fits the name into two lines on a narrower column — 330px of
   chart against 380px. Measured cutovers are about 300 and 345; each query
   sits above its own to leave room for a wider system font. A column just
   over the line reserves one empty line and costs 15px, where one just under
   would have put a caption on the panel border.

   Ordered after the rule above, since a container query carries no
   specificity of its own and would otherwise lose to it. */
.bs-rail__chart {
	container: bs-rail / inline-size;
}

@media (min-width: 421px) {

	@container bs-rail (max-width: 380px) {

		.bs-rail__steps--below {
			height: calc(var(--bs-rail-line) * 3);
		}
	}
}

@media (max-width: 420px) {

	@container bs-rail (max-width: 330px) {

		.bs-rail__steps--below {
			height: calc(var(--bs-rail-line) * 3);
		}
	}
}


/* ==========================================================================
   28. Product card: the same card on every shelf          [NEW in 4.9.0]
   --------------------------------------------------------------------------
   Three complaints about the homepage — categories with no picture, buttons
   at different heights, titles running to four lines — were one bug wearing
   three hats, plus one PHP change. The bug:

   Sections 5, 26 and 27 write most card rules twice, once as
   `.woocommerce ul.products li.product X` and once as the bare
   `ul.products li.product X`, because the homepage rows are printed by
   bs_render_products() into a plain <section>, and `.woocommerce` is a body
   class WooCommerce only adds on its own pages. Three rules were written
   only in the prefixed form, so on the homepage they never matched:

   28.1  The title's clamp. Section 5 sets `display: -webkit-box`,
         `-webkit-box-orient` and `overflow: hidden` under the prefixed
         selector only; section 27 then sets `-webkit-line-clamp` under both.
         A line-clamp without a -webkit-box to clamp does nothing, so on the
         homepage the name printed in full — four lines on the Nila Mix Soap
         — while the shop page clamped correctly at two.

   28.2  `margin-top: auto` and `width: 100%` on the loop button (section 5,
         line 1252). Without the auto margin the button sits directly under
         whatever the card happens to end with, so a card with a long title
         pushed its button a row and a half below its neighbours'.

   28.3  `align-items: stretch` on the grid (section 26.1), which is what
         gives that auto margin a common bottom edge to work from.

   Fixing the selectors rather than adding height overrides means the card is
   now defined in one place and behaves the same in the carousels, the shop
   grid, related products and upsells.
   ========================================================================== */


/* --- 28.1 The dials ------------------------------------------------------ */

:root {
	/* Kept in step with --bs-card-title-lines from section 27.1. */
	--bs-card-title-leading: 1.35;

	/* One height for every card button, so "Add to cart", "Select options"
	   and "Read more" cannot disagree about how tall a button is. */
	--bs-card-button-height: 44px;
}


/* --- 28.2 Title: two lines, always, everywhere --------------------------- */

.woocommerce ul.products li.product .woocommerce-loop-product__title,
ul.products li.product .woocommerce-loop-product__title {
	/* !important throughout this section.
	   ------------------------------------------------------------------
	   Normally a smell, and here a deliberate one. This child theme is
	   enqueued with array( 'storefront-style' ) as its only declared
	   dependency, so WooCommerce's own stylesheets, the block library and
	   any plugin that registers CSS without a dependency can all land
	   after it in the <head>. When they do, an equally specific rule of
	   theirs wins on source order alone and the card quietly reverts.
	   These few declarations are the ones that decide whether every card
	   in a row is the same shape, so they are not left to load order. */

	display: -webkit-box !important;
	-webkit-box-orient: vertical !important;
	-webkit-line-clamp: var(--bs-card-title-lines, 2) !important;
	line-clamp: var(--bs-card-title-lines, 2) !important;
	overflow: hidden !important;

	/* Restated from section 5, which sets these under the prefixed selector
	   only. The name is an <h2>, so without them the homepage card falls
	   back to whatever the parent theme gives a heading — 24px bold here,
	   14px medium on the shop page, from the same markup. Identical values
	   to section 5, so nothing changes where that rule already reached. */
	font-size: var(--bs-text-sm) !important;
	font-weight: var(--bs-weight-medium) !important;
	color: var(--bs-ink);
	line-height: var(--bs-card-title-leading) !important;

	/* Reserved and capped at the same number, so a one-line name holds the
	   row open and a six-line name cannot break it. The cap is what keeps
	   the card honest in any browser that ignores the clamp. */
	min-height: calc(var(--bs-card-title-lines, 2) * var(--bs-card-title-leading) * 1em) !important;
	max-height: calc(var(--bs-card-title-lines, 2) * var(--bs-card-title-leading) * 1em) !important;

	/* An unbroken token — a long SKU, an Arabic compound — should be cut,
	   not allowed to widen the card. */
	overflow-wrap: anywhere;
}


/* --- 28.3 One bottom edge for every button ------------------------------- */

.woocommerce ul.products,
ul.products {
	align-items: stretch !important;
}

.woocommerce ul.products li.product,
ul.products li.product {
	display: flex !important;
	flex-direction: column !important;
	height: 100%;
}

.woocommerce ul.products li.product .button,
.woocommerce ul.products li.product a.button,
.woocommerce ul.products li.product button.button,
ul.products li.product .button,
ul.products li.product a.button,
ul.products li.product button.button {
	display: flex !important;
	align-items: center;
	justify-content: center;

	/* The pin. Every card is as tall as the tallest in its row, so the free
	   space collects above the button instead of under it. */
	margin-top: auto !important;

	width: 100% !important;
	box-sizing: border-box;
	min-height: var(--bs-card-button-height) !important;
	height: auto;
	padding-block: 0 !important;

	font-size: var(--bs-text-sm);
	line-height: 1.2;
	text-align: center;

	/* A two-word label that wraps makes one button taller than the rest,
	   which is the thing this section exists to prevent. */
	white-space: nowrap;
}

/* The price block sits directly under the stars rather than stretching to
   fill the card, so the slack collects in one place — above the button —
   instead of being shared out between the rows. */
.woocommerce ul.products li.product .bs-card-meta,
ul.products li.product .bs-card-meta {
	flex: 0 0 auto;
}


/* --- 28.4 The second button --------------------------------------------- */

/* After an AJAX add, WooCommerce appends a "View cart" link below the button
   it was clicked on. This theme opens the cart drawer on add — the drawer has
   its own View cart — so the link says nothing new, and it appears on one card
   out of four, making that card taller than its neighbours for the rest of the
   session. That is the extra button under the Nila Mix Soap in the snapshot.

   Hidden rather than removed, so the markup WooCommerce's own scripts look
   for is still there. Delete this block to bring the link back. */
.woocommerce ul.products li.product .added_to_cart,
ul.products li.product .added_to_cart {
	display: none !important;
}


/* --- 28.5 Narrow screens ------------------------------------------------- */

@media (max-width: 480px) {

	/* Two columns of small cards: "Add to cart" still fits on one line at
	   this size, but the taller touch target is not needed once the button
	   is the full width of a half-column card. */
	.woocommerce ul.products li.product .button,
	ul.products li.product .button {
		min-height: 40px;
		padding-inline: var(--bs-space-3);
	}
}


/* ==========================================================================
   Storefront handheld footer bar — removed
   The PHP hook is unhooked in functions.php; this is a fallback in case a
   plugin or cached page still prints it, and it drops the space Storefront
   reserves for the bar at the bottom of the page.
   ========================================================================== */

.storefront-handheld-footer-bar {
	display: none !important;
}

@media (max-width: 66.4989378333em) {
	.site-footer {
		padding-bottom: var(--bs-space-10);
	}
}
