/**
 * Theme Name: Blocksy Child
 * Description: Blocksy Child theme
 * Author: Creative Themes
 * Template: blocksy
 * Text Domain: blocksy
 * Version: 1.0.0
 */

/* ==========================================================================
   1. Design tokens
   ========================================================================== */
:root {
	--ecb-plum: #4A1834;
	--ecb-gold: #C5A060;
	--ecb-ivory: #FBF8F3;
	--ecb-rose: #D6B2B1;
	--ecb-charcoal: #211E20;

	--ecb-muted: #75606A;
	/* Sale red. Not a brand colour: it is reserved exclusively for the
	   discount badge, where the job is to catch the eye. A vivid red reads as
	   a genuine markdown; the deeper maroon shades look like brand furniture
	   and get ignored. White on this red measures 4.9:1, so it still clears
	   WCAG AA at badge sizes. */
	--ecb-sale: #E01B24;
	--ecb-border: rgba(74, 24, 52, 0.16);
	--ecb-border-strong: rgba(74, 24, 52, 0.30);
	--ecb-surface: #ffffff;

	/* Cormorant is the branding / display voice; Rubik carries the interface. */
	--ecb-font-heading: "Cormorant Garamond", Georgia, "Times New Roman", serif;
	--ecb-font-body: "Rubik", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
	--ecb-font-bangla: "Noto Sans Bengali", "Rubik", sans-serif;

	/* Motion system */
	--ecb-t-color: 260ms;
	--ecb-t-button: 240ms;
	--ecb-t-image: 480ms;
	--ecb-t-slide: 600ms;
	--ecb-t-reveal: 600ms;
	--ecb-ease: cubic-bezier(0.22, 0.61, 0.36, 1);

	--ecb-space-1: 4px;
	--ecb-space-2: 8px;
	--ecb-space-3: 16px;
	--ecb-space-4: 24px;
	--ecb-space-5: 32px;
	--ecb-space-6: 48px;
	--ecb-space-7: 64px;
	--ecb-space-8: 96px;
	--ecb-space-9: 128px;

	--ecb-radius: 4px;
	--ecb-radius-sm: 3px;

	/* Container widths track Blocksy's own so ECB bands line up with theme
	   content instead of sitting 10px narrower. */
	--ecb-container: 1290px;
	--ecb-container-narrow: 750px;

	--ecb-transition: 150ms ease;

	/* ----------------------------------------------------------------------
	   M6 — Premium visual system
	   Everything below is a token. Components reference these; they do not
	   re-declare raw values. Adding a page-specific colour or size here is
	   the wrong move — extend the scale instead.
	   ---------------------------------------------------------------------- */

	/* Surfaces. The page ground is warm cream, not white: white next to the
	   plum reads cold and screen-like. White is reserved for raised cards so
	   they lift off the cream rather than needing a shadow to do it. */
	--ecb-page: #FBF8F3;
	--ecb-surface-raised: #ffffff;
	--ecb-surface-sunken: #F4EFE7;
	--ecb-surface-plum: #4A1834;

	/* Ink. Pure black is never used — charcoal carries the warmth of the
	   cream ground, and the muted plum-taupe keeps secondary copy in family. */
	--ecb-ink: #211E20;
	--ecb-ink-muted: #75606A;
	--ecb-ink-inverse: #FBF8F3;

	/* Type scale — fluid between a 360px phone and a 1440px desktop, so
	   headings stop stepping at breakpoints. The anchors are the sizes the
	   customizer was already using, which keeps the change a smoothing rather
	   than a resize. */
	--ecb-fs-display: clamp(2.125rem, 1.667rem + 2.04vw, 3.5rem);   /* 34 -> 56 */
	--ecb-fs-h2: clamp(1.3125rem, 1.229rem + 0.37vw, 1.5625rem);    /* 21 -> 25 */
	--ecb-fs-h3: clamp(1.125rem, 1.083rem + 0.19vw, 1.25rem);       /* 18 -> 20 */
	--ecb-fs-h4: clamp(1rem, 0.958rem + 0.19vw, 1.125rem);          /* 16 -> 18 */
	--ecb-fs-body: clamp(0.9375rem, 0.906rem + 0.14vw, 1rem);       /* 15 -> 16 */
	--ecb-fs-sm: 0.875rem;
	--ecb-fs-xs: 0.8125rem;
	--ecb-fs-eyebrow: 0.75rem;

	/* Weights. Body 400, interface 500, emphasis 600. Nothing heavier: the
	   self-hosted variable faces are cut to 400-600 and a 700 request would
	   only be synthesised. */
	--ecb-fw-body: 400;
	--ecb-fw-ui: 500;
	--ecb-fw-emphasis: 600;

	--ecb-lh-display: 1.1;
	--ecb-lh-heading: 1.3;
	--ecb-lh-body: 1.7;
	--ecb-lh-tight: 1.45;

	/* Tracking. Display type is large enough to need pulling in; uppercase
	   micro-labels need opening out. Body sits at the font's own default. */
	--ecb-ls-display: -0.01em;
	--ecb-ls-body: 0;
	--ecb-ls-ui: 0.02em;
	--ecb-ls-caps: 0.12em;
	--ecb-ls-caps-wide: 0.16em;

	/* Elevation. Two steps only, both barely there. A third step is a sign
	   the layout is doing the work a border should. */
	--ecb-shadow-sm: 0 1px 2px rgba(33, 30, 32, 0.05);
	--ecb-shadow-md: 0 4px 16px rgba(74, 24, 52, 0.07);

	/* Focus. Gold on cream measured ~2:1, which is not a visible focus ring.
	   Plum on cream is ~13:1. The ring colour is a token so plum-ground
	   surfaces (header, footer) can flip it to cream without new selectors. */
	--ecb-focus-ring: #4A1834;
	--ecb-focus-halo: rgba(197, 160, 96, 0.35);
	--ecb-focus-width: 2px;
	--ecb-focus-offset: 2px;

	/* Radii. One ladder: 4px controls stood beside 16px cards, which is the
	   kind of mismatch that reads as assembled rather than designed. The plugin
	   defers to these, keeping its own values only as standalone fallbacks. */
	--ecb-radius-card: 8px;
	--ecb-radius-ctl: 6px;

	/* Minimum comfortable pointer target. */
	--ecb-tap: 44px;

	/* Vertical rhythm — one ladder for every band on the site. */
	--ecb-section-y: clamp(2.25rem, 1.5rem + 3.3vw, 3.25rem);       /* 36 -> 52 */
	--ecb-section-y-tight: clamp(1.5rem, 1.1rem + 1.8vw, 2.25rem);  /* 24 -> 36 */
	--ecb-section-seam: clamp(1.625rem, 1.25rem + 1.7vw, 2.25rem);  /* 26 -> 36 */
}

/* ==========================================================================
   2. Base
   ========================================================================== */
.ecb-eyebrow {
	display: block;
	font-family: var(--ecb-font-body);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--ecb-plum);
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
.wp-block-button__link:focus-visible,
.ct-menu-link:focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		scroll-behavior: auto !important;
	}
}

/* ==========================================================================
   2b. Mobile header — prevent the cart price text overflowing into the
   centered brand name. The mobile header's three grid columns (trigger /
   logo / cart) don't shrink their content below its natural width, so once
   an item is in the cart the price text can overlap the site title. The
   icon and count badge alone are enough at this width; the price shows on
   the cart page itself.
   ========================================================================== */
@media (max-width: 689px) {
	.ct-header-cart .ct-label {
		display: none;
	}
}

/* ==========================================================================
   3. Section rhythm & containers
   ========================================================================== */
/* Section rhythm. 96/96 left ~190px of dead space between bands, which read as
   unfinished rather than spacious. 52/52 keeps the editorial feel while letting
   the next section signal itself above the fold. */
.ecb-section {
	padding-top: 52px;
	padding-bottom: 52px;
}

/* Two neighbouring sections on the same ground double their padding into one
   large void. Pull the seam in where the background does not change. */
.ecb-section + .ecb-section:not(.ecb-section--surface),
.ecb-section--surface + .ecb-section--surface {
	padding-top: 36px;
}

.ecb-section--tight {
	padding-top: var(--ecb-space-6);
	padding-bottom: var(--ecb-space-6);
}

.ecb-section--bordered {
	border-top: 1px solid var(--ecb-border);
}

.ecb-section--surface {
	background-color: var(--ecb-ivory);
}

.ecb-section-head {
	max-width: var(--ecb-container-narrow);
	margin: 0 0 var(--ecb-space-5);
}

.ecb-section-head .ecb-eyebrow {
	margin-bottom: var(--ecb-space-2);
}

.ecb-section-head h2 {
	margin: 0;
}

.ecb-section-head p {
	margin: var(--ecb-space-2) 0 0;
	color: var(--ecb-muted);
}

.ecb-narrow {
	max-width: var(--ecb-container-narrow);
	margin-left: auto;
	margin-right: auto;
}

@media (max-width: 999px) {
	.ecb-section { padding-top: 44px; padding-bottom: 44px; }
	.ecb-section + .ecb-section:not(.ecb-section--surface),
	.ecb-section--surface + .ecb-section--surface { padding-top: 30px; }
}

@media (max-width: 689px) {
	.ecb-section { padding-top: 36px; padding-bottom: 36px; }
	.ecb-section + .ecb-section:not(.ecb-section--surface),
	.ecb-section--surface + .ecb-section--surface { padding-top: 26px; }
	.ecb-section--tight {
		padding-top: var(--ecb-space-4);
		padding-bottom: var(--ecb-space-4);
	}
}

/* ==========================================================================
   3b. Header dropdown — Blocksy ships a near-black panel, which collides with
   the ivory header and made the first row read as missing. Bring it onto the
   brand: ivory panel, gold hairline, plum on hover.
   ========================================================================== */
.header-menu-1 .sub-menu,
.header-menu-2 .sub-menu,
[data-id="menu"] .sub-menu {
	background-color: var(--ecb-surface) !important;
	border-top: 2px solid var(--ecb-gold);
	border-radius: 0 0 var(--ecb-radius-sm) var(--ecb-radius-sm);
	box-shadow: 0 12px 28px rgba(33, 30, 32, 0.10);
	padding: var(--ecb-space-2) 0;
	min-width: 210px;
}

/* Blocksy sets --theme-link-initial-color to the ivory palette colour on
   dropdown links, which is correct only over its own dark panel. Since the
   panel above is ivory, every one of these selectors has to be repainted —
   including .header-menu-2, whose dropdowns are NOT covered by the
   [data-id="menu"] selector (Menu 2 renders as [data-id="menu-secondary"]).
   Missing it leaves the category dropdown ivory-on-ivory: the labels vanish
   and only the chevrons appear to render. */
.header-menu-1 .sub-menu .ct-menu-link,
.header-menu-2 .sub-menu .ct-menu-link,
[data-id="menu"] .sub-menu .ct-menu-link,
[data-id="menu-secondary"] .sub-menu .ct-menu-link {
	--theme-link-initial-color: var(--ecb-charcoal);
	color: var(--ecb-charcoal) !important;
	font-family: var(--ecb-font-body);
	font-size: 13px;
	font-weight: 400;
	letter-spacing: 0.04em;
	text-transform: none;
	padding: 9px var(--ecb-space-4);
	min-height: 40px;
	display: flex;
	align-items: center;
	transition: background-color var(--ecb-t-color) var(--ecb-ease),
	            color var(--ecb-t-color) var(--ecb-ease);
}

.header-menu-1 .sub-menu .ct-menu-link:hover,
.header-menu-2 .sub-menu .ct-menu-link:hover,
[data-id="menu"] .sub-menu .ct-menu-link:hover,
[data-id="menu-secondary"] .sub-menu .ct-menu-link:hover {
	background-color: var(--ecb-ivory);
	color: var(--ecb-plum) !important;
}

/* Blocksy draws dashed dividers between dropdown rows; too busy at this size. */
.header-menu-1 .sub-menu li,
.header-menu-2 .sub-menu li,
[data-id="menu"] .sub-menu li,
[data-id="menu-secondary"] .sub-menu li {
	--dropdown-divider: none;
}

/* Brand lockup should never break across two lines. */
.site-title {
	white-space: nowrap;
}

@media (max-width: 480px) {
	.site-title { font-size: 19px !important; }
}

/* ==========================================================================
   4. Hero
   ========================================================================== */
.ecb-hero {
	border-bottom: 1px solid var(--ecb-border);
	background-color: var(--ecb-ivory);
}

.ecb-hero__inner {
	max-width: var(--ecb-container-narrow);
	padding-top: var(--ecb-space-8);
	padding-bottom: var(--ecb-space-8);
}

.ecb-hero .ecb-eyebrow {
	margin-bottom: var(--ecb-space-3);
}

.ecb-hero h1 {
	margin: 0 0 var(--ecb-space-4);
	max-width: 16ch;
}

.ecb-hero p {
	max-width: 52ch;
	font-size: 17px;
	color: var(--ecb-charcoal);
	margin: 0 0 var(--ecb-space-5);
}

.ecb-hero .wp-block-buttons {
	margin: 0;
}

@media (max-width: 689px) {
	.ecb-hero__inner {
		padding-top: var(--ecb-space-6);
		padding-bottom: var(--ecb-space-6);
	}
}

/* ==========================================================================
   5. Category grid
   ========================================================================== */
.ecb-category-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1px;
	background-color: var(--ecb-border);
	border: 1px solid var(--ecb-border);
}

.ecb-category-card {
	position: relative;
	display: block;
	background-color: var(--ecb-surface);
	padding: var(--ecb-space-6) var(--ecb-space-4);
	text-decoration: none;
	min-height: 220px;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	transition: background-color var(--ecb-transition);
}

.ecb-category-card:hover {
	background-color: var(--ecb-ivory);
}

.ecb-category-card__rule {
	width: 32px;
	height: 1px;
	background-color: var(--ecb-gold);
	margin-bottom: var(--ecb-space-3);
}

.ecb-category-card h3 {
	margin: 0 0 var(--ecb-space-1);
	color: var(--ecb-plum);
}

.ecb-category-card span.ecb-category-card__cta {
	font-family: var(--ecb-font-body);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ecb-charcoal);
}

@media (max-width: 999px) {
	.ecb-category-grid {
		grid-template-columns: 1fr 1fr;
	}
}

@media (max-width: 689px) {
	.ecb-category-grid {
		grid-template-columns: 1fr;
	}

	.ecb-category-card {
		min-height: 160px;
		padding: var(--ecb-space-5) var(--ecb-space-4);
	}
}

/* ==========================================================================
   6. Trust / benefits band
   ========================================================================== */
.ecb-trust-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--ecb-space-5);
}

.ecb-trust-item {
	border-top: 1px solid var(--ecb-gold);
	padding-top: var(--ecb-space-3);
}

.ecb-trust-item h3 {
	font-family: var(--ecb-font-body);
	font-size: 15px;
	font-weight: 600;
	color: var(--ecb-plum);
	margin: 0 0 var(--ecb-space-1);
}

.ecb-trust-item p {
	margin: 0;
	font-size: 14.5px;
	color: var(--ecb-muted);
}

@media (max-width: 689px) {
	.ecb-trust-grid {
		grid-template-columns: 1fr;
		gap: var(--ecb-space-4);
	}
}

/* ==========================================================================
   7. Shopping-help CTA band
   ========================================================================== */
.ecb-cta-band {
	background-color: var(--ecb-plum);
	color: var(--ecb-ivory);
}

.ecb-cta-band h2,
.ecb-cta-band p {
	color: var(--ecb-ivory);
}

.ecb-cta-band a.wp-block-button__link {
	background-color: var(--ecb-ivory) !important;
	color: var(--ecb-plum) !important;
}

.ecb-cta-band a.wp-block-button__link:hover {
	background-color: var(--ecb-gold) !important;
	color: var(--ecb-plum) !important;
}

/* ==========================================================================
   8. Product loop sections (shortcode-rendered: New Arrivals / Featured / Best Sellers)
   ========================================================================== */
.ecb-product-shortcode ul.products {
	display: grid !important;
	grid-template-columns: repeat(4, 1fr);
	align-items: start;
	gap: var(--ecb-space-4);
	list-style: none;
	margin: 0;
	padding: 0;
}

.ecb-product-shortcode ul.products li.product {
	width: auto !important;
	margin: 0 !important;
	float: none !important;
}

@media (max-width: 999px) {
	.ecb-product-shortcode ul.products {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (max-width: 689px) {
	.ecb-product-shortcode ul.products {
		grid-template-columns: repeat(2, 1fr);
		gap: var(--ecb-space-3);
	}
}

/* ==========================================================================
   9. WooCommerce — product cards (shop archive, category archive, shortcodes)
   ========================================================================== */
.woocommerce ul.products li.product {
	background: none;
	border: none;
}

.woocommerce ul.products li.product .woocommerce-loop-product__link {
	display: block;
	text-decoration: none;
	color: inherit;
}

.woocommerce ul.products li.product .ct-media-container {
	aspect-ratio: 4 / 5;
	overflow: hidden;
	border-radius: var(--ecb-radius-sm);
	border: 1px solid var(--ecb-border);
	background-color: var(--ecb-ivory);
	margin-bottom: var(--ecb-space-2);
}

.woocommerce ul.products li.product img {
	aspect-ratio: 4 / 5;
	object-fit: cover;
	width: 100%;
	height: 100%;
	display: block;
}

.woocommerce ul.products li.product .woocommerce-loop-product__title {
	font-family: var(--ecb-font-body);
	font-size: 15px;
	font-weight: 500;
	color: var(--ecb-charcoal);
	margin: var(--ecb-space-1) 0 var(--ecb-space-1);
}

.woocommerce ul.products li.product .price {
	font-family: var(--ecb-font-body);
	font-size: 15px;
	font-weight: 600;
	color: var(--ecb-plum);
	font-variant-numeric: tabular-nums;
}

.woocommerce ul.products li.product .price del {
	color: var(--ecb-muted);
	opacity: 1;
	font-weight: 400;
	margin-right: var(--ecb-space-1);
}

.woocommerce ul.products li.product .price ins {
	text-decoration: none;
}

.woocommerce ul.products li.product .onsale {
	position: absolute;
	top: var(--ecb-space-2);
	left: var(--ecb-space-2);
	background: none;
	color: var(--ecb-plum);
	font-family: var(--ecb-font-body);
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	padding: 0;
	min-height: 0;
	min-width: 0;
	border-radius: 0;
}

.woocommerce ul.products li.product {
	position: relative;
}

.woocommerce span.onsale {
	left: 0;
}

.woocommerce ul.products li.product .button {
	margin-top: var(--ecb-space-2);
}

/* Out of stock / stock messaging */
.woocommerce p.stock.out-of-stock,
.woocommerce .stock.out-of-stock {
	color: var(--ecb-charcoal);
	background: none;
	font-size: 13px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.woocommerce p.stock.in-stock,
.woocommerce .stock.in-stock {
	color: #2F6B4F;
	font-size: 13px;
}

/* ==========================================================================
   10. WooCommerce — single product
   ========================================================================== */
.woocommerce div.product .woocommerce-product-gallery__image img,
.woocommerce div.product div.images img {
	border-radius: var(--ecb-radius-sm);
	border: 1px solid var(--ecb-border);
}

.woocommerce div.product .product_title {
	font-family: var(--ecb-font-heading);
}

.woocommerce div.product p.price,
.woocommerce div.product span.price {
	color: var(--ecb-plum);
	font-family: var(--ecb-font-body);
	font-weight: 600;
	font-size: 22px;
	font-variant-numeric: tabular-nums;
}

.woocommerce div.product .woocommerce-product-details__short-description {
	color: var(--ecb-charcoal);
}

/* The rule that divides the description from the purchase controls.

   This used to carry 24px of margin above the border and 24px of padding
   below it, and the first `Size` label added another 20px of its own — 69px
   of empty column between the SKU line and the first thing you can click.
   On a laptop that pushed Add to Cart under the fold on a product whose
   photograph was already doing the selling. Halved above and below; the
   border still does the separating, which is what a rule is for. */
.woocommerce div.product form.cart {
	border-top: 1px solid var(--ecb-border);
	padding-top: 14px;
	margin-top: 14px;
}

.woocommerce div.product form.cart .variations td.label {
	font-family: var(--ecb-font-body);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ecb-charcoal);
}

.woocommerce div.product .woocommerce-variation-add-to-cart .button,
.woocommerce div.product form.cart .button {
	min-height: 48px;
}

.woocommerce div.product .quantity .qty {
	min-height: 48px;
	border-radius: var(--ecb-radius-sm);
	border: 1px solid var(--ecb-border-strong);
	text-align: center;
}

.woocommerce div.product .product_meta {
	font-size: 13px;
	color: var(--ecb-muted);
	border-top: 1px solid var(--ecb-border);
	margin-top: var(--ecb-space-4);
	padding-top: var(--ecb-space-3);
}

/* Product tabs */
.woocommerce div.product .woocommerce-tabs ul.tabs {
	border-bottom: 1px solid var(--ecb-border);
	padding-left: 0;
	margin: var(--ecb-space-6) 0 0;
}

.woocommerce div.product .woocommerce-tabs ul.tabs li {
	background: none;
	border: none;
	border-radius: 0;
	margin: 0 var(--ecb-space-4) 0 0;
}

.woocommerce div.product .woocommerce-tabs ul.tabs li a {
	font-family: var(--ecb-font-body);
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--ecb-muted);
	padding: var(--ecb-space-2) 0;
}

.woocommerce div.product .woocommerce-tabs ul.tabs li.active a {
	color: var(--ecb-plum);
	box-shadow: inset 0 -2px 0 var(--ecb-plum);
}

.woocommerce div.product .woocommerce-tabs .panel {
	padding-top: var(--ecb-space-4);
}

/* Related products */
.woocommerce div.product .related.products {
	border-top: 1px solid var(--ecb-border);
	margin-top: var(--ecb-space-8);
	padding-top: var(--ecb-space-6);
}

.woocommerce div.product .related.products > h2 {
	margin-bottom: var(--ecb-space-4);
}

/* ==========================================================================
   11. Variation Swatches for WooCommerce — brand theming via the plugin's own CSS vars
   ========================================================================== */
.woo-variation-swatches {
	--wvs-item-background-color: #ffffff;
	--wvs-item-text-color: var(--ecb-charcoal);
	--wvs-item-box-shadow: inset 0 0 0 1px var(--ecb-border-strong);
	--wvs-hover-item-background-color: var(--ecb-ivory);
	--wvs-hover-item-text-color: var(--ecb-charcoal);
	--wvs-hover-item-box-shadow: inset 0 0 0 1px var(--ecb-plum);
	--wvs-selected-item-background-color: var(--ecb-plum);
	--wvs-selected-item-text-color: var(--ecb-ivory);
	--wvs-selected-item-box-shadow: inset 0 0 0 1px var(--ecb-plum);
	--wvs-tooltip-background-color: var(--ecb-charcoal);
	--wvs-tooltip-text-color: var(--ecb-ivory);
}

.woo-variation-swatches .variable-item {
	border-radius: var(--ecb-radius-sm) !important;
	transition: box-shadow var(--ecb-transition), background-color var(--ecb-transition);
}

.woo-variation-swatches .variable-item:focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: 2px;
}

/* ==========================================================================
   12. Buttons — brand extras on top of Blocksy's global button controls
   ========================================================================== */
.wp-block-button.is-style-outline .wp-block-button__link {
	border: 1px solid var(--ecb-plum);
	color: var(--ecb-plum);
	background: none;
	min-height: 48px;
	border-radius: var(--ecb-radius);
}

.wp-block-button.is-style-outline .wp-block-button__link:hover {
	background-color: var(--ecb-plum);
	color: var(--ecb-ivory);
}

.ecb-cta-band .wp-block-button.is-style-outline .wp-block-button__link {
	border-color: var(--ecb-ivory);
	color: var(--ecb-ivory);
}

.ecb-cta-band .wp-block-button.is-style-outline .wp-block-button__link:hover {
	background-color: var(--ecb-ivory);
	color: var(--ecb-plum);
}

/* ==========================================================================
   13. Forms
   ========================================================================== */
.woocommerce form .form-row label,
.woocommerce-page form .form-row label {
	font-family: var(--ecb-font-body);
	font-size: 13px;
	font-weight: 500;
	color: var(--ecb-charcoal);
}

.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.woocommerce-page form .form-row input.input-text,
.woocommerce-page form .form-row textarea,
.woocommerce-page form .form-row select {
	min-height: 44px;
	border-radius: var(--ecb-radius-sm);
	border: 1px solid var(--ecb-border-strong);
	font-family: var(--ecb-font-body);
}

.woocommerce form .form-row input.input-text:focus,
.woocommerce form .form-row textarea:focus,
.woocommerce form .form-row select:focus {
	border-color: var(--ecb-plum);
	outline: 2px solid var(--ecb-gold);
	outline-offset: 1px;
}

/* ==========================================================================
   14. Tables (cart totals, order tracking, order details)
   ========================================================================== */
.woocommerce table.shop_table,
.woocommerce-page table.shop_table {
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-sm);
	border-collapse: separate;
	border-spacing: 0;
}

.woocommerce table.shop_table th {
	font-family: var(--ecb-font-body);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ecb-muted);
	background-color: var(--ecb-ivory);
	border-bottom: 1px solid var(--ecb-border);
}

.woocommerce table.shop_table td,
.woocommerce table.shop_table th {
	border-top: none;
	border-bottom: 1px solid var(--ecb-border);
}

.woocommerce table.shop_table .product-name,
.woocommerce table.shop_table .amount,
.woocommerce table.shop_table .woocommerce-Price-amount {
	font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   15. Breadcrumbs
   ========================================================================== */
.woocommerce-breadcrumb,
.ct-breadcrumbs {
	font-size: 13px;
	color: var(--ecb-muted);
}

.woocommerce-breadcrumb a,
.ct-breadcrumbs a {
	color: var(--ecb-muted);
	text-decoration: none;
	border-bottom: 1px solid var(--ecb-border-strong);
}

.woocommerce-breadcrumb a:hover,
.ct-breadcrumbs a:hover {
	color: var(--ecb-plum);
	border-color: var(--ecb-plum);
}

/* ==========================================================================
   16. Notices & validation
   ========================================================================== */
.woocommerce-message,
.woocommerce-info,
.woocommerce-error,
.woocommerce-noreviews,
p.no-comments {
	border-top-color: var(--ecb-plum);
	border-radius: var(--ecb-radius-sm);
	font-family: var(--ecb-font-body);
	font-size: 14.5px;
}

.woocommerce-message::before {
	color: var(--ecb-plum);
}

.woocommerce-error {
	border-top-color: #9B2C2C;
}

.woocommerce-error::before {
	color: #9B2C2C;
}

.woocommerce form .woocommerce-invalid input.input-text,
.woocommerce form .woocommerce-invalid select {
	border-color: #9B2C2C;
}

/* ==========================================================================
   17. My Account
   ========================================================================== */
.woocommerce-account .woocommerce-MyAccount-navigation ul {
	list-style: none;
	margin: 0;
	padding: 0;
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-sm);
	overflow: hidden;
}

.woocommerce-account .woocommerce-MyAccount-navigation li {
	border-bottom: 1px solid var(--ecb-border);
}

.woocommerce-account .woocommerce-MyAccount-navigation li:last-child {
	border-bottom: none;
}

.woocommerce-account .woocommerce-MyAccount-navigation li a {
	display: block;
	padding: var(--ecb-space-3);
	font-family: var(--ecb-font-body);
	font-size: 14px;
	font-weight: 500;
	color: var(--ecb-charcoal);
	text-decoration: none;
	min-height: 44px;
	box-sizing: border-box;
}

.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a {
	color: var(--ecb-plum);
	background-color: var(--ecb-ivory);
	box-shadow: inset 3px 0 0 var(--ecb-plum);
}

/* ==========================================================================
   18. Order tracking
   ========================================================================== */
.woocommerce-order-tracking .form-row {
	max-width: 420px;
}

/* ==========================================================================
   19. Callout (informational-page notices: blockers, in-progress details)
   ========================================================================== */
.ecb-callout {
	border-left: 2px solid var(--ecb-gold);
	background-color: var(--ecb-ivory);
	padding: var(--ecb-space-3) var(--ecb-space-4);
}

.ecb-callout p {
	margin: 0;
	color: var(--ecb-charcoal);
	font-size: 14.5px;
}

/* ==========================================================================
   20. Bangla language support
   ========================================================================== */
/* .ecb-policy is included so Bengali policy copy still gets the right family
   even if the lang attribute is ever stripped by an editor or caching layer. */
:lang(bn),
[lang="bn"],
.ecb-policy {
	font-family: var(--ecb-font-bangla);
	font-size: 1.06em;
	line-height: 1.85;
}

:lang(bn) h1,
:lang(bn) h2,
:lang(bn) h3,
:lang(bn) h4,
:lang(bn) h5,
:lang(bn) h6,
.ecb-policy h2,
.ecb-policy h3 {
	font-family: var(--ecb-font-bangla);
}

/* ==========================================================================
   21. Phase H — motion system
   ========================================================================== */
.ecb-reveal-armed {
	opacity: 0;
	transform: translateY(16px);
}

.ecb-reveal-armed.is-revealed,
[data-ecb-reveal].is-revealed {
	opacity: 1;
	transform: none;
	transition: opacity var(--ecb-t-reveal) var(--ecb-ease),
	            transform var(--ecb-t-reveal) var(--ecb-ease);
}

@media (prefers-reduced-motion: reduce) {
	.ecb-reveal-armed {
		opacity: 1 !important;
		transform: none !important;
	}
}

/* ==========================================================================
   22. Phase H — shared button
   ========================================================================== */
.ecb-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 48px;
	padding: 0 28px;
	border-radius: var(--ecb-radius);
	font-family: var(--ecb-font-body);
	font-size: 15px;
	font-weight: 500;
	letter-spacing: 0.02em;
	text-decoration: none;
	background-color: var(--ecb-plum);
	color: var(--ecb-ivory);
	border: 1px solid var(--ecb-plum);
	transition: background-color var(--ecb-t-button) var(--ecb-ease),
	            border-color var(--ecb-t-button) var(--ecb-ease),
	            color var(--ecb-t-button) var(--ecb-ease);
}

.ecb-btn:hover {
	background-color: var(--ecb-charcoal);
	border-color: var(--ecb-charcoal);
	color: var(--ecb-ivory);
}

.ecb-btn--light {
	background-color: var(--ecb-ivory);
	border-color: var(--ecb-ivory);
	color: var(--ecb-plum);
}

.ecb-btn--light:hover {
	background-color: var(--ecb-gold);
	border-color: var(--ecb-gold);
	color: var(--ecb-charcoal);
}

/* ==========================================================================
   23. Phase H — announcement rotator
   ========================================================================== */
.ecb-rotator {
	position: relative;
	display: block;
	line-height: 1.4;
}

.ecb-rotator__item {
	display: block;
}

/* Once enhanced the items stack and cross-fade; without JS they simply list,
   which keeps every message readable with scripting disabled. */
.ecb-rotator.is-enhanced {
	min-height: 1.4em;
}

/* The outgoing and incoming messages must NOT animate at the same time. Both
   sit in the same centred box, so a simultaneous cross-fade renders two
   different-length strings on top of each other for the whole transition —
   which reads as broken text, not as a fade. The outgoing message therefore
   fades out first and the incoming one waits for it to clear. */
.ecb-rotator.is-enhanced .ecb-rotator__item {
	position: absolute;
	inset: 0;
	opacity: 0;
	visibility: hidden;
	transition: opacity 260ms var(--ecb-ease), visibility 0s linear 260ms;
}

.ecb-rotator.is-enhanced .ecb-rotator__item.is-active {
	position: relative;
	opacity: 1;
	visibility: visible;
	transition: opacity 260ms var(--ecb-ease) 260ms, visibility 0s;
}

@media (prefers-reduced-motion: reduce) {
	.ecb-rotator.is-enhanced .ecb-rotator__item {
		transition: none;
	}
}

/* ==========================================================================
   24. Phase H — hero carousel
   ========================================================================== */
.ecb-hero-carousel {
	position: relative;
	overflow: hidden;
	background-color: var(--ecb-charcoal);
}

.ecb-hero-carousel__viewport {
	position: relative;
}

.ecb-hero-slide {
	position: relative;
	min-height: 560px;
	display: grid;
	align-items: end;
}

/* Before JS runs, only the first slide is shown so there is no stacked flash. */
.ecb-hero-carousel:not(.is-enhanced) .ecb-hero-slide:not(.is-active) {
	display: none;
}

.ecb-hero-carousel.is-enhanced .ecb-hero-slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	visibility: hidden;
	transition: opacity var(--ecb-t-slide) var(--ecb-ease),
	            visibility var(--ecb-t-slide) var(--ecb-ease);
}

.ecb-hero-carousel.is-enhanced .ecb-hero-slide.is-active {
	position: relative;
	opacity: 1;
	visibility: visible;
}

.ecb-hero-slide__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 22%;
}

.ecb-hero-slide__scrim {
	position: absolute;
	inset: 0;
	background: linear-gradient(
		to top,
		rgba(33, 30, 32, 0.78) 0%,
		rgba(33, 30, 32, 0.45) 42%,
		rgba(33, 30, 32, 0.12) 100%
	);
}

/* The carousel controls are positioned from the viewport edge (left/right:16px)
   while the hero text is positioned from the centred 1280px container. Those
   are two different coordinate systems, so as soon as the viewport stops being
   wider than the container + control band, the text column slides underneath
   the arrows — at 1280px the prev arrow overlapped the heading by 36px.

   Rather than nudging anything with a negative margin, the text column reserves
   the control band directly: 16px offset + 44px control + 16px separation.
   max() means the reservation only applies once the centring gutter is no
   longer wide enough to provide it, so the wide-viewport layout is unchanged. */
:root {
	--ecb-hero-control-clear: 76px;
}

.ecb-hero-slide__inner {
	position: relative;
	max-width: var(--ecb-container);
	width: 100%;
	margin: 0 auto;
	padding-block: var(--ecb-space-7) var(--ecb-space-8);
	padding-inline: max(
		var(--ecb-space-4),
		calc(var(--ecb-hero-control-clear) - max(0px, (100vw - var(--ecb-container)) / 2))
	);
	color: var(--ecb-ivory);
}

.ecb-hero-slide__kicker {
	font-family: var(--ecb-font-body);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--ecb-gold);
	margin: 0 0 var(--ecb-space-3);
}

.ecb-hero-slide__title {
	font-family: var(--ecb-font-heading);
	font-weight: 600;
	font-size: clamp(34px, 4.4vw, 56px);
	line-height: 1.08;
	color: var(--ecb-ivory);
	margin: 0 0 var(--ecb-space-3);
	max-width: 18ch;
}

.ecb-hero-slide__text {
	font-family: var(--ecb-font-body);
	font-size: 16px;
	line-height: 1.65;
	color: rgba(251, 248, 243, 0.92);
	margin: 0 0 var(--ecb-space-5);
	max-width: 46ch;
}

.ecb-hero-nav {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 3;
	width: 44px;
	height: 44px;
	display: none;
	align-items: center;
	justify-content: center;
	border: 1px solid rgba(251, 248, 243, 0.5);
	border-radius: var(--ecb-radius-sm);
	background: rgba(33, 30, 32, 0.35);
	color: var(--ecb-ivory);
	font-size: 22px;
	line-height: 1;
	cursor: pointer;
	transition: background-color var(--ecb-t-color) var(--ecb-ease),
	            border-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-hero-carousel.is-enhanced .ecb-hero-nav {
	display: flex;
}

.ecb-hero-nav:hover {
	background: rgba(74, 24, 52, 0.85);
	border-color: var(--ecb-gold);
}

.ecb-hero-nav--prev { left: 16px; }
.ecb-hero-nav--next { right: 16px; }

.ecb-hero-dots {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 18px;
	z-index: 3;
	display: none;
	justify-content: center;
	gap: 10px;
}

.ecb-hero-carousel.is-enhanced .ecb-hero-dots {
	display: flex;
}

.ecb-hero-dot {
	width: 34px;
	height: 3px;
	padding: 10px 0;
	background: none;
	border: 0;
	cursor: pointer;
	position: relative;
}

.ecb-hero-dot::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	height: 3px;
	transform: translateY(-50%);
	background: rgba(251, 248, 243, 0.45);
	transition: background-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-hero-dot.is-active::after {
	background: var(--ecb-gold);
}

@media (max-width: 999px) {
	.ecb-hero-slide { min-height: 460px; }
}

@media (max-width: 689px) {
	.ecb-hero-slide {
		min-height: 480px;
	}
	/* Portrait sources: bias the crop upward so faces are not cut. */
	.ecb-hero-slide__img {
		object-position: center 18%;
	}
	/* Controls are hidden below this width, so the reservation is released
	   and the text gets the full column back. */
	.ecb-hero-slide__inner {
		padding-block: var(--ecb-space-6) var(--ecb-space-7);
		padding-inline: var(--ecb-space-4);
	}
	.ecb-hero-nav { display: none !important; }
}

/* ==========================================================================
   25. Phase H — category cards
   ========================================================================== */
.ecb-cat-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--ecb-space-4);
}

.ecb-cat-card {
	position: relative; /* the caption block is positioned against this */
	display: block;
	text-decoration: none;
	color: inherit;
}

.ecb-cat-card__media {
	position: relative;
	display: block;
	aspect-ratio: 4 / 5;
	overflow: hidden;
	border-radius: var(--ecb-radius-sm);
	background-color: var(--ecb-ivory);
}

.ecb-cat-card__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform var(--ecb-t-image) var(--ecb-ease);
}

.ecb-cat-card:hover .ecb-cat-card__img,
.ecb-cat-card:focus-visible .ecb-cat-card__img {
	transform: scale(1.035);
}

.ecb-cat-card__scrim {
	position: absolute;
	inset: 0;
	/* Strong enough under the whole caption block to hold AA contrast against
	   any real product photo, not just an average one. */
	background: linear-gradient(to top, rgba(33,30,32,0.82) 0%, rgba(33,30,32,0.5) 50%, rgba(33,30,32,0.05) 100%);
	transition: opacity var(--ecb-t-image) var(--ecb-ease);
}

.ecb-cat-card:hover .ecb-cat-card__scrim {
	opacity: 0.82;
}

.ecb-cat-card__body {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: var(--ecb-space-4);
	color: var(--ecb-ivory);
	display: block;
}

.ecb-cat-card__media { position: relative; }

.ecb-cat-card__title {
	display: block;
	font-family: var(--ecb-font-body);
	font-size: 22px;
	font-weight: 400;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ecb-ivory);
}

.ecb-cat-card__text {
	display: block;
	font-size: 14px;
	color: rgba(251, 248, 243, 0.86);
	margin-top: 4px;
}

.ecb-cat-card__cta {
	display: inline-block;
	margin-top: var(--ecb-space-2);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	/* Gold text over a variable photograph can't guarantee AA contrast the way
	   it can on a solid Plum/Charcoal ground, so the label stays ivory and gold
	   is kept as a decorative underline only. */
	color: var(--ecb-ivory);
	border-bottom: 1px solid var(--ecb-gold);
	padding-bottom: 2px;
}

@media (max-width: 999px) {
	.ecb-cat-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 689px) {
	.ecb-cat-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   26. Phase H — Trending Looks video row
   ========================================================================== */
.ecb-trending {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--ecb-space-4);
}

.ecb-trending__item {
	margin: 0;
	position: relative;
}

.ecb-trending__video {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	border-radius: var(--ecb-radius-sm);
	background-color: var(--ecb-surface-sunken, #f2ece6);
	border: 1px solid var(--ecb-border);
}

.ecb-trending__caption {
	margin-top: var(--ecb-space-2);
	font-family: var(--ecb-font-body);
	font-size: 13px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ecb-muted);
}

@media (max-width: 689px) {
	.ecb-trending {
		grid-auto-flow: column;
		grid-auto-columns: 72%;
		grid-template-columns: none;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		padding-bottom: var(--ecb-space-2);
	}
	.ecb-trending__item { scroll-snap-align: start; }
}

/* ==========================================================================
   27. Phase H — Editor's Picks
   ========================================================================== */
.ecb-picks {
	display: grid;
	grid-template-columns: 1.15fr 0.85fr;
	gap: var(--ecb-space-4);
}

.ecb-pick {
	position: relative;
	overflow: hidden;
	border-radius: var(--ecb-radius-sm);
	min-height: 380px;
	display: flex;
	align-items: flex-end;
}

.ecb-pick__media {
	position: absolute;
	inset: 0;
	display: block;
}

.ecb-pick__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform var(--ecb-t-image) var(--ecb-ease);
}

.ecb-pick:hover .ecb-pick__img {
	transform: scale(1.03);
}

.ecb-pick__scrim {
	position: absolute;
	inset: 0;
	/* Strong enough under the whole caption block to hold AA contrast against
	   any real product photo, not just an average one. */
	background: linear-gradient(to top, rgba(33,30,32,0.85) 0%, rgba(33,30,32,0.55) 55%, rgba(33,30,32,0.08) 100%);
}

.ecb-pick__body {
	position: relative;
	padding: var(--ecb-space-5);
	color: var(--ecb-ivory);
}

.ecb-pick__kicker {
	font-size: 11px;
	font-weight: 500;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	/* Gold text over a variable photograph can't guarantee AA contrast, so the
	   kicker stays ivory with a short gold rule as the decorative accent. */
	color: var(--ecb-ivory);
	margin: 0 0 var(--ecb-space-2);
	padding-left: 14px;
	position: relative;
}

.ecb-pick__kicker::before {
	content: "";
	position: absolute;
	left: 0;
	top: 50%;
	transform: translateY(-50%);
	width: 8px;
	height: 1px;
	background: var(--ecb-gold);
}

.ecb-pick__title {
	font-family: var(--ecb-font-heading);
	font-weight: 600;
	font-size: 30px;
	line-height: 1.15;
	color: var(--ecb-ivory);
	margin: 0 0 var(--ecb-space-2);
}

.ecb-pick__text {
	font-size: 15px;
	color: rgba(251, 248, 243, 0.9);
	margin: 0 0 var(--ecb-space-4);
	max-width: 34ch;
}

@media (max-width: 899px) {
	.ecb-picks { grid-template-columns: 1fr; }
	.ecb-pick { min-height: 320px; }
}

/* ==========================================================================
   28. Phase H — shop grid refinement + card motion
   ========================================================================== */
.woocommerce ul.products,
.ecb-product-shortcode ul.products {
	column-gap: 32px;
	row-gap: 40px;
}

.woocommerce ul.products li.product .ct-media-container,
.ecb-product-shortcode ul.products li.product .ct-media-container {
	overflow: hidden;
}

.woocommerce ul.products li.product img {
	transition: transform var(--ecb-t-image) var(--ecb-ease);
}

.woocommerce ul.products li.product:hover img {
	transform: scale(1.028);
}

@media (prefers-reduced-motion: reduce) {
	.woocommerce ul.products li.product:hover img,
	.ecb-cat-card:hover .ecb-cat-card__img,
	.ecb-pick:hover .ecb-pick__img {
		transform: none;
	}
}

.ecb-soldout-note {
	display: inline-block;
	margin-top: var(--ecb-space-2);
	font-family: var(--ecb-font-body);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ecb-muted);
}

/* ==========================================================================
   29. Phase 1 — product page completeness
   ========================================================================== */

/* Percentage-off figure, beside the price */
.ecb-off {
	display: inline-block;
	margin-left: var(--ecb-space-1);
	font-family: var(--ecb-font-body);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.04em;
	color: #9B2C2C;
	vertical-align: middle;
	white-space: nowrap;
}

.woocommerce ul.products li.product .ecb-off {
	font-size: 11px;
}

/* Delivery expectation */
.ecb-delivery-estimate {
	display: flex;
	align-items: flex-start;
	gap: var(--ecb-space-2);
	margin: var(--ecb-space-4) 0 0;
	padding: var(--ecb-space-3);
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-sm);
	background-color: var(--ecb-ivory);
	font-size: 14px;
	line-height: 1.55;
	color: var(--ecb-charcoal);
}

.ecb-delivery-estimate__icon {
	color: var(--ecb-plum);
	flex: 0 0 auto;
	margin-top: 1px;
}

.ecb-delivery-estimate strong { font-weight: 500; color: var(--ecb-plum); }

.ecb-delivery-estimate em {
	display: block;
	font-style: normal;
	font-size: 13px;
	color: var(--ecb-muted);
	margin-top: 2px;
}

/* Reassurance strip */
.ecb-assure {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--ecb-space-3);
	list-style: none;
	margin: var(--ecb-space-4) 0 0;
	padding: var(--ecb-space-4) 0 0;
	border-top: 1px solid var(--ecb-border);
}

.ecb-assure__item { display: block; }

.ecb-assure__t {
	display: block;
	font-family: var(--ecb-font-body);
	font-size: 13px;
	font-weight: 500;
	color: var(--ecb-plum);
}

.ecb-assure__d {
	display: block;
	font-size: 12.5px;
	color: var(--ecb-muted);
	line-height: 1.45;
}

/* Details accordion */
.ecb-acc {
	margin-top: var(--ecb-space-4);
	border-top: 1px solid var(--ecb-border);
}

.ecb-acc__item { border-bottom: 1px solid var(--ecb-border); }

.ecb-acc__head {
	cursor: pointer;
	list-style: none;
	padding: var(--ecb-space-3) 0;
	font-family: var(--ecb-font-body);
	font-size: 13px;
	font-weight: 500;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ecb-charcoal);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--ecb-space-3);
	min-height: 44px;
	box-sizing: border-box;
}

.ecb-acc__head::-webkit-details-marker { display: none; }

.ecb-acc__head::after {
	content: "+";
	font-size: 17px;
	line-height: 1;
	color: var(--ecb-muted);
	flex: 0 0 auto;
}

.ecb-acc__item[open] > .ecb-acc__head::after { content: "\2212"; }

.ecb-acc__head:focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: 2px;
}

.ecb-acc__body {
	padding: 0 0 var(--ecb-space-4);
	font-size: 14.5px;
	color: var(--ecb-charcoal);
}

.ecb-acc__body p { margin: 0 0 var(--ecb-space-2); }
.ecb-acc__body p:last-child { margin-bottom: 0; }

/* Spec list inside the accordion */
.ecb-spec {
	display: grid;
	grid-template-columns: minmax(110px, auto) 1fr;
	gap: var(--ecb-space-2) var(--ecb-space-4);
	margin: 0;
}

.ecb-spec dt {
	font-size: 12.5px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--ecb-muted);
}

.ecb-spec dd {
	margin: 0;
	font-size: 14.5px;
	color: var(--ecb-charcoal);
}

/* Share row */
.ecb-share {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--ecb-space-2);
	margin-top: var(--ecb-space-4);
	padding-top: var(--ecb-space-3);
	border-top: 1px solid var(--ecb-border);
}

.ecb-share__label {
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--ecb-muted);
	margin-right: var(--ecb-space-1);
}

.ecb-share__link {
	appearance: none;
	background: none;
	border: 1px solid var(--ecb-border-strong);
	border-radius: var(--ecb-radius-sm);
	padding: 7px 14px;
	font-family: var(--ecb-font-body);
	font-size: 12.5px;
	font-weight: 400;
	color: var(--ecb-charcoal);
	text-decoration: none;
	cursor: pointer;
	transition: border-color var(--ecb-t-color) var(--ecb-ease),
	            color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-share__link:hover {
	border-color: var(--ecb-plum);
	color: var(--ecb-plum);
}

@media (max-width: 689px) {
	.ecb-assure { grid-template-columns: 1fr; gap: var(--ecb-space-2); }
}

/* ==========================================================================
   30. Phase 2 — product card badges
   ========================================================================== */
.ecb-card-flags {
	position: absolute;
	top: var(--ecb-space-2);
	left: var(--ecb-space-2);
	right: var(--ecb-space-2);
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--ecb-space-2);
	pointer-events: none;
	z-index: 2;
}

.ecb-flag {
	display: inline-block;
	padding: 4px 9px;
	border-radius: 2px;
	font-family: var(--ecb-font-body);
	font-size: 10.5px;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	line-height: 1.4;
}

.ecb-flag--off {
	background-color: var(--ecb-sale);
	color: #fff;
	font-weight: 600;
}

.ecb-flag--oos {
	background-color: rgba(33, 30, 32, 0.86);
	color: var(--ecb-ivory);
	margin-left: auto;
}

/* WooCommerce's own sale ribbon is replaced by the flag above. */
.woocommerce ul.products li.product .onsale { display: none; }

/* ==========================================================================
   32. Phase 4 — footer contact / social + contact page
   ========================================================================== */
.ecb-foot-brand {
	font-family: var(--ecb-font-heading);
	font-size: 21px;
	font-weight: 600;
	color: var(--ecb-ivory);
	margin: 0 0 var(--ecb-space-2);
}

.ecb-foot-desc {
	font-size: 13.5px;
	line-height: 1.5;
	color: rgba(251, 248, 243, 0.72);
	margin: 0 0 var(--ecb-space-3);
	max-width: 32ch;
}

.ecb-foot-tag {
	font-size: 14px;
	color: rgba(251, 248, 243, 0.82);
	margin: 0;
	max-width: 30ch;
}

.ecb-foot-contact,
.ecb-foot-social {
	list-style: none;
	margin: 0;
	padding: 0;
	font-size: 14px;
}

.ecb-foot-contact li,
.ecb-foot-social li { margin-bottom: 6px; }

.ecb-foot-address a {
	display: block;
	max-width: 26ch;
	line-height: 1.5;
	font-size: 13px;
}

.ecb-foot-contact a,
.ecb-foot-social a {
	color: rgba(251, 248, 243, 0.9);
	text-decoration: none;
	border-bottom: 1px solid transparent;
	transition: color var(--ecb-t-color) var(--ecb-ease),
	            border-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-foot-contact a:hover,
.ecb-foot-social a:hover {
	color: var(--ecb-gold);
	border-bottom-color: var(--ecb-gold);
}

/* --------------------------------------------------------------------------
   Footer structure.
   Blocksy renders widget titles in the body heading colour (Charcoal), which on
   the Deep Plum footer measured ~1.6:1 — effectively invisible. The footer menu
   also inherits a wrapping flex row, so seven policy links wrapped raggedly
   across the column instead of listing.

   IMPORTANT: Blocksy uses data-row="middle" for the HEADER's middle row as well
   as the footer's, so every rule below must stay scoped to .ct-footer. An
   unscoped [data-row="middle"] turns the header nav into a vertical column and
   paints its links ivory-on-ivory.
   -------------------------------------------------------------------------- */
.ct-footer .widget-title,
.ct-footer .ct-widget-title,
.ct-footer [data-row="middle"] .widget-title,
.ct-footer [data-row="middle"] h3 {
	color: var(--ecb-gold) !important;
	font-family: var(--ecb-font-body);
	font-size: 11.5px;
	font-weight: 500;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	margin: 0 0 var(--ecb-space-3);
}

/* Footer navigation: a column, not a wrapping row. */
.ct-footer [data-id="menu"] > ul,
.ct-footer .footer-menu-1,
.ct-footer [data-row="middle"] [data-id="menu"] > ul {
	display: flex !important;
	flex-direction: column !important;
	align-items: flex-start !important;
	gap: 9px !important;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ct-footer [data-id="menu"] > ul > li,
.ct-footer [data-row="middle"] [data-id="menu"] > ul > li {
	margin: 0 !important;
	width: 100%;
}

/* Blocksy makes each menu link a full-width flex box with
   justify-content:center. In a horizontal bar that is invisible; in this
   vertical footer column it centred every policy link while the sibling
   Contact and Follow columns stayed left-aligned. */
.ct-footer [data-id="menu"] .ct-menu-link,
.ct-footer [data-row="middle"] [data-id="menu"] .ct-menu-link {
	font-size: 13px !important;
	font-weight: 400 !important;
	letter-spacing: 0.04em !important;
	text-transform: none !important;
	padding: 0 !important;
	justify-content: flex-start !important;
	text-align: left;
	color: rgba(251, 248, 243, 0.88);
	transition: color var(--ecb-t-color) var(--ecb-ease);
}

.ct-footer [data-id="menu"] .ct-menu-link:hover,
.ct-footer [data-row="middle"] [data-id="menu"] .ct-menu-link:hover {
	color: var(--ecb-gold);
}

/* Give the footer columns a consistent top alignment and sane rhythm. */
.ct-footer [data-row="middle"] .ct-container {
	align-items: start;
}

.ecb-foot-brand {
	margin-top: -4px; /* optically align the serif lockup with the column labels */
}

/* Footer bottom bar sits tight to the columns above it. */
.ct-footer [data-row="bottom"] {
	--container-spacing: 18px;
}

/* Footer reassurance strip */
.ecb-footstrip {
	background-color: var(--ecb-charcoal);
	color: rgba(251, 248, 243, 0.9);
	border-top: 1px solid rgba(197, 160, 96, 0.25);
}

.ecb-footstrip__inner {
	max-width: var(--ecb-container);
	margin: 0 auto;
	padding: var(--ecb-space-3) var(--ecb-space-4);
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: var(--ecb-space-2) var(--ecb-space-3);
	font-family: var(--ecb-font-body);
	font-size: 12.5px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-align: center;
}

.ecb-footstrip__sep { color: var(--ecb-gold); }

.ecb-footstrip__link {
	color: var(--ecb-gold);
	text-decoration: none;
	border-bottom: 1px solid transparent;
	transition: border-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-footstrip__link:hover { border-bottom-color: var(--ecb-gold); }

@media (max-width: 689px) {
	.ecb-footstrip__inner { font-size: 11.5px; letter-spacing: 0.04em; }
	.ecb-footstrip__sep { display: none; }
	.ecb-footstrip__inner { flex-direction: column; gap: 6px; }
}

/* Contact page cards */
.ecb-contact-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: var(--ecb-space-3);
	margin: var(--ecb-space-5) 0;
}

.ecb-contact-card {
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: var(--ecb-space-4);
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-sm);
	background-color: var(--ecb-surface);
}

.ecb-contact-card__label {
	font-size: 11px;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--ecb-muted);
}

.ecb-contact-card__value {
	font-family: var(--ecb-font-body);
	font-size: 16px;
	font-weight: 500;
	color: var(--ecb-plum);
	text-decoration: none;
	border-bottom: 1px solid transparent;
	align-self: flex-start;
	transition: border-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-contact-card__value:hover { border-bottom-color: var(--ecb-plum); }

.ecb-contact-card__note {
	font-size: 13px;
	color: var(--ecb-muted);
}

.ecb-contact-card__cta {
	align-self: flex-start;
	margin-top: var(--ecb-space-2);
	padding: 9px 16px;
	border-radius: var(--ecb-radius-sm);
	background-color: var(--ecb-plum);
	color: var(--ecb-ivory);
	font-size: 13px;
	font-weight: 500;
	text-decoration: none;
	min-height: 44px;
	display: inline-flex;
	align-items: center;
	transition: background-color var(--ecb-t-button) var(--ecb-ease);
}

.ecb-contact-card__cta:hover { background-color: var(--ecb-charcoal); color: var(--ecb-ivory); }

/* ==========================================================================
   31. Phase 2 — shop filter panel
   ========================================================================== */
.ecb-filters {
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-sm);
	margin-bottom: var(--ecb-space-5);
	background-color: var(--ecb-surface);
}

.ecb-filters__toggle {
	cursor: pointer;
	list-style: none;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--ecb-space-2);
	padding: var(--ecb-space-3) var(--ecb-space-4);
	min-height: 48px;
	box-sizing: border-box;
	font-family: var(--ecb-font-body);
	font-size: 13px;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ecb-charcoal);
}

.ecb-filters__toggle::-webkit-details-marker { display: none; }

.ecb-filters__toggle:focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: -2px;
}

.ecb-filters__chev { color: var(--ecb-muted); display: inline-flex; }

.ecb-filters[open] .ecb-filters__toggle {
	border-bottom: 1px solid var(--ecb-border);
}

.ecb-filters__panel {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
	gap: var(--ecb-space-5);
	padding: var(--ecb-space-4);
}

.ecb-filter-widget__title {
	font-family: var(--ecb-font-body);
	font-size: 11.5px;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--ecb-muted);
	margin: 0 0 var(--ecb-space-2);
}

.ecb-filters__panel ul {
	list-style: none;
	margin: 0;
	padding: 0;
	font-size: 14px;
}

.ecb-filters__panel li { margin-bottom: 5px; }

.ecb-filters__panel li a {
	color: var(--ecb-charcoal);
	text-decoration: none;
	border-bottom: 1px solid transparent;
	transition: color var(--ecb-t-color) var(--ecb-ease),
	            border-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-filters__panel li a:hover {
	color: var(--ecb-plum);
	border-bottom-color: var(--ecb-plum);
}

.ecb-filters__panel li.chosen > a,
.ecb-filters__panel li.current-cat > a {
	color: var(--ecb-plum);
	font-weight: 500;
}

.ecb-filters__panel .count {
	color: var(--ecb-muted);
	font-size: 12.5px;
}

/* WooCommerce price slider inside the panel */
.ecb-filters__panel .price_slider_wrapper { margin-top: var(--ecb-space-2); }

.ecb-filters__panel .ui-slider {
	background-color: var(--ecb-border);
	height: 3px;
	border-radius: 0;
	border: 0;
}

.ecb-filters__panel .ui-slider .ui-slider-range { background-color: var(--ecb-plum); }

.ecb-filters__panel .ui-slider .ui-slider-handle {
	background-color: var(--ecb-plum);
	border: 0;
	width: 14px;
	height: 14px;
	border-radius: 50%;
	top: -6px;
}

.ecb-filters__panel .price_slider_amount .button {
	min-height: 40px;
	font-size: 13px;
}

.ecb-filters__panel .price_label {
	font-size: 13px;
	color: var(--ecb-muted);
}

/* Active filter chips */
.ecb-filters__panel .woocommerce-widget-layered-nav-list__item--chosen a,
.ecb-filters__panel .wc-block-active-filters li a {
	color: var(--ecb-plum);
}

@media (max-width: 689px) {
	.ecb-filters__panel {
		grid-template-columns: 1fr;
		gap: var(--ecb-space-4);
	}
}

/* Shop archive grid ladder: 4 across on desktop, 3 on small desktop / large
   tablet, 2 from tablet down. Four columns below ~1200px squeezes the 4:5
   imagery too far for a fashion catalogue. */
.woocommerce ul.products {
	display: grid;
}

.woocommerce ul.products li.product {
	width: auto !important;
	margin: 0 !important;
	float: none !important;
}

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

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

@media (max-width: 899.98px) {
	.woocommerce ul.products {
		grid-template-columns: repeat(2, 1fr);
		column-gap: 16px;
		row-gap: 28px;
	}
}

/* ==========================================================================
   33. Phase I — shop archive parity (breadcrumb, category quick-nav, and a
   tighter page-title band). Scoped to body.woocommerce so informational
   pages (About, Contact, policies) keep their current spacing.
   ========================================================================== */
/* Blocksy's page-title hero sets both the 50px/50px padding AND a 250px
   min-height on the same inner element ([class*="ct-container"], which here
   is .entry-header) — the min-height has to be overridden too, or it alone
   keeps the band at 250px regardless of the padding. */
body.woocommerce .hero-section .entry-header,
body.woocommerce-page .hero-section .entry-header {
	min-height: 0;
	padding-top: 28px;
	padding-bottom: 20px;
}

.ecb-archive-crumb {
	max-width: var(--ecb-container);
	margin: 0 auto;
	padding: 0 var(--ecb-space-4) var(--ecb-space-2);
	text-align: center;
}

.ecb-archive-crumb .ct-breadcrumbs {
	font-size: 12px;
	letter-spacing: 0.04em;
}

.ecb-cat-quicknav {
	display: flex;
	justify-content: center;
	flex-wrap: wrap;
	gap: var(--ecb-space-2) var(--ecb-space-5);
	margin: 0 0 var(--ecb-space-5);
	padding-bottom: var(--ecb-space-4);
	border-bottom: 1px solid var(--ecb-border);
}

.ecb-cat-quicknav__link {
	font-family: var(--ecb-font-body);
	font-size: 13px;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ecb-muted);
	text-decoration: none;
	padding-bottom: 4px;
	border-bottom: 2px solid transparent;
	transition: color var(--ecb-t-color) var(--ecb-ease),
	            border-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-cat-quicknav__link:hover,
.ecb-cat-quicknav__link:focus-visible {
	color: var(--ecb-plum);
}

.ecb-cat-quicknav__link.is-active {
	color: var(--ecb-plum);
	border-bottom-color: var(--ecb-gold);
}

@media (max-width: 599px) {
	.ecb-cat-quicknav {
		gap: var(--ecb-space-2) var(--ecb-space-4);
	}
}

/* ==========================================================================
   34. Phase J — two-layer header
   Row 1 carries the evergreen nav and the account/cart actions; row 2 is a
   quieter category bar. The two must not read as equal weight, so row 2 is
   set smaller, wider-tracked and in the muted tone, with the plum reserved
   for hover and the current section.
   ========================================================================== */
.ct-header [data-row="bottom"] {
	border-top: 1px solid rgba(74, 24, 52, 0.08);
}

.ct-header [data-row="bottom"] [data-id="menu-secondary"] > ul {
	gap: 0;
}

/* Row 2 must read quieter than row 1. Blocksy drives menu link colour through
   --theme-link-initial-color from a compiled selector that outspecifies a
   plain .header-menu-2 rule, so match its shape to win the cascade. */
.ct-header [data-id="menu-secondary"] > ul > li > .ct-menu-link {
	--theme-link-initial-color: var(--ecb-muted);
	color: var(--ecb-muted);
	padding-left: 18px;
	padding-right: 18px;
	transition: color var(--ecb-t-color) var(--ecb-ease);
}

.ct-header [data-id="menu-secondary"] > ul > li > .ct-menu-link:hover,
.ct-header [data-id="menu-secondary"] > ul > li.current-menu-item > .ct-menu-link,
.ct-header [data-id="menu-secondary"] > ul > li.current-menu-ancestor > .ct-menu-link {
	--theme-link-initial-color: var(--ecb-plum);
	color: var(--ecb-plum);
}

/* The gold underline marks the section you are actually in. */
.header-menu-2 > li.current-menu-item > .ct-menu-link::after,
.header-menu-2 > li.current-menu-ancestor > .ct-menu-link::after {
	content: "";
	position: absolute;
	left: 18px;
	right: 18px;
	bottom: 10px;
	height: 1px;
	background-color: var(--ecb-gold);
}

.header-menu-2 > li > .ct-menu-link {
	position: relative;
}

/* "Sign In" reads as a label, not a nav item. */
[data-id="account"] .ct-label {
	font-family: var(--ecb-font-body);
	font-size: 11.5px;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

/* ==========================================================================
   35. Phase J — logo lockup
   The mark is wordmark-plus-symbol and much wider than it is tall, so it is
   constrained by height and allowed to find its own width. Capping the height
   keeps row 1 from growing when the file is swapped for a larger export.
   ========================================================================== */
.site-logo-container .site-logo,
.ct-header [data-id="logo"] img {
	height: auto;
	max-height: 62px;
	width: auto;
	max-width: 260px;
	object-fit: contain;
}

@media (max-width: 999.98px) {
	.site-logo-container .site-logo,
	.ct-header [data-id="logo"] img { max-height: 46px; max-width: 190px; }
}

@media (max-width: 689.98px) {
	.site-logo-container .site-logo,
	.ct-header [data-id="logo"] img { max-height: 40px; max-width: 165px; }
}

/* ==========================================================================
   36. Phase J — share buttons
   Outlined circles that fill with each network's own colour on hover. Always-on
   brand colours would put five saturated hues next to the price and pull the
   eye away from Add to Cart; the resting state stays quiet on purpose.
   ========================================================================== */
.ecb-share {
	display: flex;
	align-items: center;
	gap: var(--ecb-space-3);
	flex-wrap: wrap;
	margin-top: var(--ecb-space-4);
	padding-top: var(--ecb-space-4);
	border-top: 1px solid var(--ecb-border);
}

.ecb-share__label {
	font-size: 11px;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--ecb-muted);
}

.ecb-share__set {
	display: flex;
	align-items: center;
	gap: 10px;
}

.ecb-share__btn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 38px;
	height: 38px;
	padding: 0;
	border: 1px solid var(--ecb-border-strong);
	border-radius: 50%;
	background-color: transparent;
	color: var(--ecb-charcoal);
	cursor: pointer;
	transition: color var(--ecb-t-color) var(--ecb-ease),
	            background-color var(--ecb-t-color) var(--ecb-ease),
	            border-color var(--ecb-t-color) var(--ecb-ease),
	            transform var(--ecb-t-button) var(--ecb-ease);
}

.ecb-share__btn:hover {
	color: #fff;
	transform: translateY(-2px);
}

.ecb-share__btn--whatsapp:hover  { background-color: #25D366; border-color: #25D366; }
.ecb-share__btn--facebook:hover  { background-color: #1877F2; border-color: #1877F2; }
.ecb-share__btn--pinterest:hover { background-color: #E60023; border-color: #E60023; }
.ecb-share__btn--telegram:hover  { background-color: #229ED9; border-color: #229ED9; }
.ecb-share__btn--copy:hover      { background-color: var(--ecb-plum); border-color: var(--ecb-plum); }

.ecb-share__btn:focus-visible {
	outline: 2px solid var(--ecb-plum);
	outline-offset: 2px;
}

/* Copy confirmation, driven by the data attribute ecb-ui.js sets. */
.ecb-share__btn[data-ecb-copied]::after {
	content: attr(data-ecb-copied);
	position: absolute;
	bottom: calc(100% + 8px);
	left: 50%;
	transform: translateX(-50%);
	white-space: nowrap;
	background-color: var(--ecb-charcoal);
	color: var(--ecb-ivory);
	font-size: 11px;
	letter-spacing: 0.04em;
	padding: 5px 9px;
	border-radius: var(--ecb-radius-sm);
	pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
	.ecb-share__btn:hover { transform: none; }
}

/* ==========================================================================
   37. Phase J — account: sign in, create account, forgot password
   WooCommerce already emits both forms side by side once registration is on;
   what it does not do is give them equal visual weight or explain why an
   account is worth making. Both panels get the same card treatment so neither
   reads as the afterthought.
   ========================================================================== */
.woocommerce-account .woocommerce {
	max-width: var(--ecb-container);
	margin: 0 auto;
}

#customer_login.u-columns {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--ecb-space-5);
	margin: 0;
}

#customer_login .u-column1,
#customer_login .u-column2 {
	float: none !important;
	width: auto !important;
	margin: 0 !important;
	padding: var(--ecb-space-5);
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-sm);
	background-color: var(--ecb-surface);
}

#customer_login h2 {
	font-family: var(--ecb-font-heading);
	font-size: 26px;
	font-weight: 600;
	color: var(--ecb-plum);
	margin: 0 0 var(--ecb-space-2);
	padding-bottom: var(--ecb-space-3);
	border-bottom: 1px solid var(--ecb-gold);
}

.woocommerce-account .woocommerce-form-row label,
.woocommerce-account .woocommerce-form__label-for-checkbox {
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ecb-muted);
}

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

.woocommerce-account .woocommerce-form-login__rememberme {
	display: block;
	margin: var(--ecb-space-3) 0;
	text-transform: none;
	letter-spacing: 0;
}

.woocommerce-account .woocommerce-form-login__submit,
.woocommerce-account .woocommerce-form-register__submit {
	width: 100%;
	justify-content: center;
}

.woocommerce-LostPassword {
	margin: var(--ecb-space-3) 0 0;
	font-size: 13px;
}

.woocommerce-LostPassword a {
	color: var(--ecb-muted);
	text-decoration: none;
	border-bottom: 1px solid var(--ecb-border-strong);
}

.woocommerce-LostPassword a:hover {
	color: var(--ecb-plum);
	border-bottom-color: var(--ecb-plum);
}

/* Aligned left to sit under the page title, which Blocksy renders left on
   pages (hero type-1) — a centred intro under a left-aligned H1 reads as a
   mistake rather than a choice. */
.ecb-account-intro {
	max-width: 68ch;
	margin: 0 0 var(--ecb-space-5);
	font-size: 15px;
	color: var(--ecb-muted);
}

/* Reasons to register, rendered under the Create Account form. */
.ecb-account-why {
	list-style: none;
	margin: var(--ecb-space-4) 0 0;
	padding: var(--ecb-space-4) 0 0;
	border-top: 1px solid var(--ecb-border);
	font-size: 13.5px;
	color: var(--ecb-muted);
}

.ecb-account-why li {
	position: relative;
	padding-left: 22px;
	margin-bottom: 8px;
}

.ecb-account-why li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 7px;
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background-color: var(--ecb-gold);
}

.ecb-account-why li:last-child { margin-bottom: 0; }

/* Lost-password page reads as one focused task, not a stray form. */
.woocommerce-account .woocommerce-ResetPassword {
	max-width: 480px;
	margin: 0 auto;
	padding: var(--ecb-space-5);
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-sm);
	background-color: var(--ecb-surface);
}

.woocommerce-account .woocommerce-ResetPassword .woocommerce-form__label {
	text-transform: none;
	letter-spacing: 0;
}

/* Logged-in dashboard */
.woocommerce-account .woocommerce-MyAccount-navigation ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

.woocommerce-account .woocommerce-MyAccount-navigation li {
	margin: 0;
	border-bottom: 1px solid var(--ecb-border);
}

.woocommerce-account .woocommerce-MyAccount-navigation li a {
	display: block;
	padding: 11px 0;
	font-size: 13px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ecb-muted);
	text-decoration: none;
	transition: color var(--ecb-t-color) var(--ecb-ease);
}

.woocommerce-account .woocommerce-MyAccount-navigation li a:hover,
.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a {
	color: var(--ecb-plum);
}

@media (max-width: 899.98px) {
	#customer_login.u-columns {
		grid-template-columns: 1fr;
		gap: var(--ecb-space-4);
	}
}

/* ==========================================================================
   38. Phase K — direct-order routes, ETA, SKU, floating contact
   ========================================================================== */

/* Estimated arrival — a concrete date does more for confidence than a range. */
.ecb-eta {
	display: flex;
	align-items: center;
	gap: 9px;
	margin: var(--ecb-space-3) 0 0;
	font-size: 13.5px;
	color: var(--ecb-charcoal);
}

.ecb-eta__icon {
	display: inline-flex;
	color: var(--ecb-plum);
	flex-shrink: 0;
}

.ecb-eta__text strong { font-weight: 600; }

.ecb-sku {
	margin: 6px 0 0;
	font-size: 12px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ecb-muted);
}

.ecb-sku span { color: var(--ecb-charcoal); }

/* Blocksy wraps the quantity picker and Add to Cart in .ct-cart-actions and
   lets Add to Cart fill the row, so an appended Buy Now wraps onto its own
   line. Re-laying the row as a grid puts the two actions side by side:
   quantity | Add to Cart on the first row, Buy Now spanning underneath. */
.woocommerce div.product form.cart .ct-cart-actions {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 10px;
	align-items: stretch;
}

/* Buy Now is the outlined, secondary-weight action: same size, quieter fill,
   so the primary path stays unambiguous. */
/* Sizing and colour for Buy Now live in section 42, where the whole purchase
   area is defined together. */

/* WhatsApp / phone ordering */
.ecb-direct {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 10px;
	margin-top: var(--ecb-space-4);
}

.ecb-direct__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 9px;
	min-height: 48px;
	padding: 0 16px;
	border-radius: var(--ecb-radius-sm);
	font-family: var(--ecb-font-body);
	font-size: 13.5px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-decoration: none;
	border: 1px solid transparent;
	transition: background-color var(--ecb-t-color) var(--ecb-ease),
	            border-color var(--ecb-t-color) var(--ecb-ease),
	            color var(--ecb-t-color) var(--ecb-ease);
}

/* WhatsApp keeps its own green — shoppers scan for that colour. It is the one
   place on the page where an off-palette hue earns its keep. */
.ecb-direct__btn--wa {
	background-color: #25D366;
	color: #0B3D22;
}

.ecb-direct__btn--wa:hover {
	background-color: #1EBE5A;
	color: #062D18;
}

.ecb-direct__btn--call {
	background-color: transparent;
	color: var(--ecb-plum);
	border-color: var(--ecb-border-strong);
}

.ecb-direct__btn--call:hover {
	background-color: var(--ecb-plum);
	border-color: var(--ecb-plum);
	color: var(--ecb-ivory);
}

@media (max-width: 480px) {
	.ecb-direct { grid-template-columns: 1fr; }
}

/* Floating contact launcher — <details>, so it needs no JavaScript. */
.ecb-fab {
	position: fixed;
	right: 18px;
	bottom: 18px;
	z-index: 90;
}

.ecb-fab__toggle {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	margin-left: auto;
	border-radius: 50%;
	background-color: var(--ecb-plum);
	color: var(--ecb-ivory);
	cursor: pointer;
	list-style: none;
	box-shadow: 0 6px 20px rgba(33, 30, 32, 0.22);
	transition: background-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-fab__toggle::-webkit-details-marker { display: none; }
.ecb-fab__toggle:hover { background-color: var(--ecb-charcoal); }

.ecb-fab__ico-close { display: none; }
.ecb-fab[open] .ecb-fab__ico-open { display: none; }
.ecb-fab[open] .ecb-fab__ico-close { display: block; }

.ecb-fab__panel {
	position: absolute;
	right: 0;
	bottom: 62px;
	width: 232px;
	padding: var(--ecb-space-4);
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-sm);
	background-color: var(--ecb-surface);
	box-shadow: 0 14px 34px rgba(33, 30, 32, 0.16);
}

.ecb-fab__title {
	margin: 0 0 var(--ecb-space-3);
	font-size: 11px;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--ecb-muted);
}

.ecb-fab__link {
	display: block;
	padding: 10px 12px;
	margin-bottom: 7px;
	border-radius: var(--ecb-radius-sm);
	border: 1px solid var(--ecb-border);
	font-size: 13.5px;
	font-weight: 500;
	color: var(--ecb-charcoal);
	text-decoration: none;
	transition: background-color var(--ecb-t-color) var(--ecb-ease),
	            border-color var(--ecb-t-color) var(--ecb-ease),
	            color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-fab__link:last-child { margin-bottom: 0; }

.ecb-fab__link--wa:hover {
	background-color: #25D366;
	border-color: #25D366;
	color: #062D18;
}

.ecb-fab__link--call:hover,
.ecb-fab__link--fb:hover {
	background-color: var(--ecb-plum);
	border-color: var(--ecb-plum);
	color: var(--ecb-ivory);
}

@media (max-width: 689px) {
	.ecb-fab { right: 14px; bottom: 14px; }
	.ecb-fab__toggle { width: 48px; height: 48px; }
}

@media print {
	.ecb-fab { display: none; }
}

/* ==========================================================================
   39. Phase 6A — compact editorial header
   Row heights come from Blocksy theme_mods (27 / 70 / 43 desktop = 140px of
   rows). Everything here is alignment, rhythm and interaction only.
   ========================================================================== */
.ct-header [data-row] > div {
	max-width: var(--ecb-container);
	margin-inline: auto;
}

/* Vertical centring in every row, including the announcement. */
.ct-header [data-row="top"] [data-id="text"] {
	display: flex;
	align-items: center;
	justify-content: center;
	line-height: 1.2;
}

.ct-header [data-row="top"] [data-id="text"] .ecb-rotator {
	line-height: 1.2;
}

/* Wordmark: sized so it reads as a lockup, not a heading. Kept until a real
   image logo is assigned — no substitute mark is invented here. */
.ct-header .site-title {
	line-height: 1.1;
	margin: 0;
}

.ct-header [data-id="logo"] .site-logo-container {
	display: flex;
	align-items: center;
}

/* Primary nav: 240ms colour move with a gold underline that grows from the
   centre. No bounce, no glow. */
.ct-header [data-id="menu"] > ul > li > .ct-menu-link {
	position: relative;
	transition: color 240ms var(--ecb-ease);
}

.ct-header [data-id="menu"] > ul > li > .ct-menu-link::after {
	content: "";
	position: absolute;
	left: 50%;
	right: 50%;
	bottom: 22px;
	height: 1px;
	background-color: var(--ecb-gold);
	transition: left 260ms var(--ecb-ease), right 260ms var(--ecb-ease);
}

.ct-header [data-id="menu"] > ul > li > .ct-menu-link:hover::after,
.ct-header [data-id="menu"] > ul > li.current-menu-item > .ct-menu-link::after,
.ct-header [data-id="menu"] > ul > li.current-menu-ancestor > .ct-menu-link::after {
	left: 14px;
	right: 14px;
}

/* Dropdowns: 200ms opacity + 6px rise. */
.header-menu-1 .sub-menu,
.header-menu-2 .sub-menu,
[data-id="menu"] .sub-menu,
[data-id="menu-secondary"] .sub-menu {
	transition: opacity 200ms var(--ecb-ease),
	            transform 200ms var(--ecb-ease),
	            visibility 200ms var(--ecb-ease);
	transform: translateY(6px);
}

li:hover > .sub-menu,
li:focus-within > .sub-menu {
	transform: translateY(0);
}

/* Cart count badge in Champagne Gold. */
.ct-header [data-id="cart"] .ct-cart-item .ct-dynamic-count,
.ct-header [data-id="cart"] .ct-cart-count,
.ct-header [data-id="cart"] [data-count]::after {
	background-color: var(--ecb-gold) !important;
	color: var(--ecb-charcoal) !important;
	font-weight: 600;
}

/* Category row: even spacing, hairlines top and bottom. */
.ct-header [data-row="bottom"] [data-id="menu-secondary"] > ul {
	display: flex;
	justify-content: center;
	align-items: center;
	gap: 0;
}

.ct-header [data-row="bottom"] {
	border-top: 1px solid rgba(74, 24, 52, 0.08);
	border-bottom: 1px solid rgba(74, 24, 52, 0.08);
}

@media (max-width: 999.98px) {
	/* The category row is desktop-only; the drawer carries the full tree. */
	.ct-header [data-row="bottom"] { display: none; }
}

/* ==========================================================================
   40. Phase 6B — editorial product gallery
   Blocksy's own flexy gallery is reused as-is; this is presentation only, so
   there is no second gallery or lightbox initialisation.
   ========================================================================== */
/* Blocksy spaces the two columns with `margin-inline-start: 40px` on
   .entry-summary, not a flex gap — a gap on the parent would stack on top of
   it (40 + 32 = 72). It must be overridden as the same logical property:
   woocommerce.min.css is enqueued after the child stylesheet, so it wins on
   load order despite the child selector being more specific. */
.woocommerce div.product .entry-summary {
	margin-inline-start: 32px !important;
}

.woocommerce div.product .woocommerce-product-gallery,
.woocommerce div.product .entry-summary {
	min-width: 0;
}

/* The SALE flag belongs over the main image, not over the thumbnail rail. */
.woocommerce div.product .woocommerce-product-gallery .onsale {
	left: auto;
	right: 14px;
	top: 14px;
	z-index: 3;
}

/* Main image sits on a very light ground and is never cropped. Single-image
   products render without a .flexy-view wrapper, so both cases are covered
   here — scoping to .flexy-view alone left those images on object-fit:cover
   and silently cropped them. The thumbnail rail is excluded: small squares
   read better filled. */
.woocommerce-product-gallery .flexy-view .ct-media-container img,
.woocommerce-product-gallery > .ct-product-gallery-container > .ct-media-container img {
	object-fit: contain !important;
	background-color: var(--ecb-ivory);
}

.woocommerce-product-gallery .flexy-view,
.woocommerce-product-gallery > .ct-product-gallery-container > .ct-media-container {
	background-color: var(--ecb-ivory);
	border: 1px solid var(--ecb-border);
}

/* Thumbnail rail — 90px wide (theme_mod), 10px gaps. */
.woocommerce-product-gallery .flexy-pills [data-flexy-pills] > *,
.woocommerce-product-gallery .flexy-pills ul {
	gap: 10px;
}

.woocommerce-product-gallery .flexy-pills figure,
.woocommerce-product-gallery .flexy-pills .ct-media-container {
	border: 1px solid var(--ecb-border);
	background-color: var(--ecb-ivory);
	cursor: pointer;
	transition: border-color 240ms var(--ecb-ease);
}

.woocommerce-product-gallery .flexy-pills [class*="active"] figure,
.woocommerce-product-gallery .flexy-pills .active .ct-media-container,
.woocommerce-product-gallery .flexy-pills li.active figure {
	border: 2px solid var(--ecb-plum);
}

.woocommerce-product-gallery .flexy-pills figure:hover {
	border-color: var(--ecb-gold);
}

/* Kill any UA blue focus ring on gallery controls; replace with gold. */
.woocommerce-product-gallery :focus {
	outline-color: var(--ecb-gold);
}

.woocommerce-product-gallery :focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: 2px;
}

/* Arrows: ~36px visual mark inside a ~68px transparent hit target. */
.woocommerce-product-gallery .flexy-arrow-prev,
.woocommerce-product-gallery .flexy-arrow-next {
	width: 68px;
	height: 68px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: transparent;
	border: 0;
	opacity: 0;
	transition: opacity 240ms var(--ecb-ease);
}

.woocommerce-product-gallery:hover .flexy-arrow-prev,
.woocommerce-product-gallery:hover .flexy-arrow-next,
.woocommerce-product-gallery .flexy-arrow-prev:focus-visible,
.woocommerce-product-gallery .flexy-arrow-next:focus-visible {
	opacity: 1;
}

.woocommerce-product-gallery .flexy-arrow-prev svg,
.woocommerce-product-gallery .flexy-arrow-next svg {
	width: 36px;
	height: 36px;
	padding: 9px;
	border-radius: 50%;
	background-color: rgba(255, 255, 255, 0.92);
	color: var(--ecb-charcoal);
	box-shadow: 0 2px 10px rgba(33, 30, 32, 0.14);
	transition: color 240ms var(--ecb-ease),
	            background-color 240ms var(--ecb-ease),
	            transform 240ms var(--ecb-ease);
}

.woocommerce-product-gallery .flexy-arrow-prev:hover svg { color: var(--ecb-plum); transform: translateX(-2px); }
.woocommerce-product-gallery .flexy-arrow-next:hover svg { color: var(--ecb-plum); transform: translateX(2px); }

/* Slide/crossfade between frames. */
.woocommerce-product-gallery .flexy-items {
	transition: transform 450ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Touch: no hover arrows, tap opens Blocksy's own lightbox. */
@media (hover: none) {
	.woocommerce-product-gallery .flexy-arrow-prev,
	.woocommerce-product-gallery .flexy-arrow-next { opacity: 1; }
}

/* Mobile: gallery full width, and the vertical thumbnail rail becomes a
   horizontal strip beneath the image. Blocksy lays the rail out as a 90px
   block beside the view, so the wrapper is turned into a flex column with the
   view first and the rail second. */
@media (max-width: 999.98px) {
	.woocommerce div.product .woocommerce-product-gallery { width: 100%; }

	/* The rail is an absolutely-positioned child of .flexy-container (not of
	   .flexy, which only wraps the view), so the container is the element that
	   has to become the column and the rail has to leave the absolute flow. */
	.woocommerce-product-gallery .flexy-container {
		display: flex;
		flex-direction: column;
		gap: 12px;
	}

	/* Vertical style reserves the rail's width with margin-inline-start on
	   .flexy; once the rail moves below, that reservation must go or the
	   image sits 105px off-centre and overhangs the right edge. */
	.woocommerce-product-gallery .flexy {
		order: 1;
		width: 100%;
		margin-inline-start: 0 !important;
	}

	.woocommerce-product-gallery .flexy-pills {
		position: static !important;
		order: 2;
		width: 100% !important;
		max-width: none !important;
		height: auto !important;
	}

	.woocommerce-product-gallery .flexy-pills ol {
		flex-direction: row;
		overflow-x: auto;
		scrollbar-width: thin;
		-webkit-overflow-scrolling: touch;
		padding-bottom: 4px;
	}

	.woocommerce-product-gallery .flexy-pills ol > li {
		flex: 0 0 74px;
		width: 74px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.woocommerce-product-gallery .flexy-items { transition: none; }
	.woocommerce-product-gallery .flexy-arrow-prev:hover svg,
	.woocommerce-product-gallery .flexy-arrow-next:hover svg { transform: none; }
}

/* ==========================================================================
   41. Phase 6C — product information hierarchy
   Flat and typographic: no cards, no shadows around information.
   ========================================================================== */
.woocommerce div.product .entry-summary .entry-title,
.woocommerce div.product .entry-summary h1.product_title {
	font-family: var(--ecb-font-body) !important;
	font-size: 24px !important;
	font-weight: 500 !important;
	letter-spacing: 0.005em;
	line-height: 1.3;
	color: var(--ecb-charcoal);
	margin-bottom: var(--ecb-space-2);
}

.woocommerce div.product .entry-summary .price {
	font-family: var(--ecb-font-body) !important;
	font-size: 20px !important;
	font-weight: 600 !important;
	color: var(--ecb-plum);
}

.woocommerce div.product .entry-summary .price del {
	font-size: 15px;
	font-weight: 400;
	color: var(--ecb-muted);
	opacity: 1;
	margin-right: 6px;
}

.woocommerce div.product .entry-summary .price ins {
	text-decoration: none;
	background: transparent;
}

.ecb-off {
	display: inline-block;
	margin-left: 8px;
	padding: 3px 8px;
	border: 0;
	border-radius: 2px;
	background-color: var(--ecb-sale);
	color: #fff;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.06em;
	line-height: 1.5;
	vertical-align: middle;
	white-space: nowrap;
}

.ecb-sku { font-size: 13px; }

.woocommerce div.product .stock {
	font-size: 13.5px;
	font-weight: 500;
}

.woocommerce div.product .stock.in-stock { color: #1F6B3F; }
.woocommerce div.product .stock.out-of-stock { color: #A2302B; }

/* Variation swatches: 36px with an unmistakable selected state. */
.woo-variation-swatches .variable-items-wrapper .variable-item:not(.radio-variable-item) {
	width: 36px !important;
	height: 36px !important;
	min-width: 36px;
	box-shadow: none !important;
	border: 1px solid var(--ecb-border-strong) !important;
	transition: border-color 240ms var(--ecb-ease), box-shadow 240ms var(--ecb-ease);
}

.woo-variation-swatches .variable-items-wrapper .variable-item.selected:not(.radio-variable-item),
.woo-variation-swatches .variable-items-wrapper .variable-item:hover:not(.radio-variable-item) {
	border-color: var(--ecb-plum) !important;
	box-shadow: 0 0 0 2px var(--ecb-plum) !important;
}

.woo-variation-swatches .variable-items-wrapper .button-variable-item {
	min-width: 46px !important;
	width: auto !important;
	padding: 0 12px;
}

/* ==========================================================================
   42. Phase 6D — purchase area
   Quantity ~30% / Add to Cart ~70% on one row, Buy Now full width beneath,
   then the two quieter direct-order routes.
   ========================================================================== */
.woocommerce div.product form.cart .ct-cart-actions {
	display: grid;
	grid-template-columns: 30% minmax(0, 1fr);
	gap: 10px;
	align-items: stretch;
}

.woocommerce div.product form.cart .quantity,
.woocommerce div.product form.cart .ct-cart-actions .quantity {
	width: 100% !important;
	max-width: none !important;
	height: 52px;
}

/* Add to Cart: outlined by default, with a Deep Plum sweep on hover. The
   sweep is a pseudo-element behind the label, so the text never reflows and
   nothing intercepts the click. */
.woocommerce div.product form.cart .single_add_to_cart_button {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	min-height: 52px !important;
	background-color: var(--ecb-surface) !important;
	color: var(--ecb-plum) !important;
	border: 1px solid var(--ecb-plum) !important;
	transition: color 400ms var(--ecb-ease);
}

.woocommerce div.product form.cart .single_add_to_cart_button::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: var(--ecb-plum);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform 400ms var(--ecb-ease);
	pointer-events: none;
}

.woocommerce div.product form.cart .single_add_to_cart_button:hover:not(:disabled),
.woocommerce div.product form.cart .single_add_to_cart_button:focus-visible:not(:disabled) {
	color: var(--ecb-ivory) !important;
}

.woocommerce div.product form.cart .single_add_to_cart_button:hover:not(:disabled)::before,
.woocommerce div.product form.cart .single_add_to_cart_button:focus-visible:not(:disabled)::before {
	transform: scaleX(1);
}

/* Buy Now: filled by default, darkening to Charcoal. Blocksy drives button
   height through --theme-button-min-height, so that variable is set too —
   min-height alone loses to the theme's own .button rule. */
.woocommerce div.product form.cart .ecb-buynow,
.ecb-buynow {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	grid-column: 1 / -1;
	--theme-button-min-height: 52px;
	min-height: 52px !important;
	background-color: var(--ecb-plum) !important;
	color: var(--ecb-ivory) !important;
	border: 1px solid var(--ecb-plum) !important;
	transition: border-color 350ms var(--ecb-ease);
}

.woocommerce div.product form.cart .single_add_to_cart_button {
	--theme-button-min-height: 52px;
	min-height: 52px !important;
}

.ecb-buynow::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: var(--ecb-charcoal);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform 350ms var(--ecb-ease);
	pointer-events: none;
}

.ecb-buynow:hover::before,
.ecb-buynow:focus-visible::before { transform: scaleX(1); }
.ecb-buynow:hover, .ecb-buynow:focus-visible { border-color: var(--ecb-charcoal) !important; }

/* Champagne Gold keyboard focus on both primary actions. */
.woocommerce div.product form.cart .single_add_to_cart_button:focus-visible,
.ecb-buynow:focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: 2px;
}

/* Unmistakable disabled / out-of-stock state. */
.woocommerce div.product form.cart .single_add_to_cart_button:disabled,
.woocommerce div.product form.cart .single_add_to_cart_button.disabled,
.ecb-buynow:disabled {
	background-color: #EDE7EA !important;
	color: var(--ecb-muted) !important;
	border-color: var(--ecb-border) !important;
	cursor: not-allowed;
	opacity: 1 !important;
}

.woocommerce div.product form.cart .single_add_to_cart_button:disabled::before,
.ecb-buynow:disabled::before { display: none; }

/* Direct-order routes are deliberately quieter than the two CTAs above. */
.ecb-direct__btn {
	min-height: 44px;
	font-size: 13px;
	font-weight: 500;
}

.ecb-direct__btn--wa {
	background-color: transparent;
	color: #10643A;
	border-color: rgba(16, 100, 58, 0.35);
}

.ecb-direct__btn--wa:hover {
	background-color: #10643A;
	border-color: #10643A;
	color: #fff;
}

.ecb-direct__btn:focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.woocommerce div.product form.cart .single_add_to_cart_button::before,
	.ecb-buynow::before { transition: none; }
}

/* Card buttons across shop/category: same language, smaller and quieter. */
.woocommerce ul.products li.product .button {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	min-height: 40px;
	font-size: 12.5px;
	background-color: transparent !important;
	color: var(--ecb-plum) !important;
	border: 1px solid var(--ecb-border-strong) !important;
	transition: color 320ms var(--ecb-ease), border-color 320ms var(--ecb-ease);
}

.woocommerce ul.products li.product .button::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: var(--ecb-plum);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform 320ms var(--ecb-ease);
	pointer-events: none;
}

.woocommerce ul.products li.product .button:hover {
	color: var(--ecb-ivory) !important;
	border-color: var(--ecb-plum) !important;
}

.woocommerce ul.products li.product .button:hover::before { transform: scaleX(1); }

@media (max-width: 689px) {
	.woocommerce div.product form.cart .ct-cart-actions {
		grid-template-columns: 32% minmax(0, 1fr);
	}
	.ecb-direct__btn,
	.woocommerce ul.products li.product .button { min-height: 44px; }
}

/* ==========================================================================
   43. Phase 6E — trust, details and share
   ========================================================================== */
.ecb-assure {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 0;
	list-style: none;
	margin: var(--ecb-space-4) 0 0;
	padding: 0;
	border-top: 1px solid var(--ecb-border);
}

.ecb-assure__item {
	display: flex;
	flex-direction: column;
	gap: 2px;
	padding: 14px 16px 14px 0;
	border-bottom: 1px solid var(--ecb-border);
}

.ecb-assure__item:nth-child(odd) { border-right: 1px solid var(--ecb-border); padding-right: 20px; }
.ecb-assure__item:nth-child(even) { padding-left: 20px; }

.ecb-assure__t {
	font-size: 13px;
	font-weight: 600;
	color: var(--ecb-charcoal);
}

.ecb-assure__d {
	font-size: 12.5px;
	color: var(--ecb-muted);
	line-height: 1.45;
}

/* Accordion rows ~66px, animated open and close where the browser supports
   ::details-content; elsewhere they toggle instantly, which is still correct. */
:root { interpolate-size: allow-keywords; }

.ecb-acc__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--ecb-space-3);
	min-height: 66px;
	padding: 0;
	cursor: pointer;
	list-style: none;
	font-size: 13.5px;
	font-weight: 600;
	letter-spacing: 0.03em;
	color: var(--ecb-charcoal);
}

.ecb-acc__head::-webkit-details-marker { display: none; }

.ecb-acc__item { border-bottom: 1px solid var(--ecb-border); }
.ecb-acc__item:first-child { border-top: 1px solid var(--ecb-border); }

.ecb-acc__chev {
	display: inline-flex;
	color: var(--ecb-muted);
	transition: transform 240ms var(--ecb-ease), color 240ms var(--ecb-ease);
}

.ecb-acc__item[open] .ecb-acc__chev { transform: rotate(180deg); color: var(--ecb-plum); }
.ecb-acc__head:hover .ecb-acc__chev { color: var(--ecb-plum); }

.ecb-acc__head:focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: 2px;
}

.ecb-acc__body { padding-bottom: var(--ecb-space-4); }

.ecb-acc__item::details-content {
	block-size: 0;
	overflow: hidden;
	transition: block-size 240ms var(--ecb-ease), content-visibility 240ms allow-discrete;
}

.ecb-acc__item[open]::details-content { block-size: auto; }

@media (prefers-reduced-motion: reduce) {
	.ecb-acc__item::details-content { transition: none; }
	.ecb-acc__chev { transition: none; }
}

/* Share icons stay smaller than the purchase CTAs. */
.ecb-share__btn { width: 34px; height: 34px; }
.ecb-share__btn svg { width: 15px; height: 15px; }

@media (max-width: 689px) {
	.ecb-assure { grid-template-columns: 1fr; }
	.ecb-assure__item:nth-child(odd) { border-right: 0; padding-right: 0; }
	.ecb-assure__item:nth-child(even) { padding-left: 0; }
	.ecb-share__btn { width: 44px; height: 44px; }
}

/* ==========================================================================
   44. Homepage — content area top spacing
   Blocksy pads the main content container with
   --theme-content-vertical-spacing (60px), applied as padding-top AND
   padding-bottom on .ct-container-full. On the homepage the first block is
   the full-bleed hero, so that 60px rendered as a band of Warm Ivory between
   the category row and the hero image.

   Only the TOP padding is removed, and only on the front page: the bottom
   60px still separates the last section from the footer, and every other
   page keeps Blocksy's global spacing untouched. Scoped rather than changing
   the Customizer value, which is global and would restyle the whole site.
   ========================================================================== */
body.home .site-main > [class*="ct-container"] {
	padding-top: 0;
}

/* ==========================================================================
   45. Phase 7 — mobile sticky purchase bar
   Phones only: on desktop the purchase area stays in view long enough that a
   fixed bar would just cover the page.
   ========================================================================== */
.ecb-stickybar {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 95;
	background-color: var(--ecb-surface);
	border-top: 1px solid var(--ecb-border);
	box-shadow: 0 -6px 20px rgba(33, 30, 32, 0.10);
	transform: translateY(100%);
	transition: transform 260ms var(--ecb-ease);
	padding-bottom: env(safe-area-inset-bottom, 0);
}

.ecb-stickybar.is-visible { transform: translateY(0); }

.ecb-stickybar__inner {
	display: flex;
	align-items: center;
	gap: var(--ecb-space-3);
	padding: 10px 14px;
}

.ecb-stickybar__info {
	display: flex;
	flex-direction: column;
	min-width: 0;
	flex: 1 1 auto;
}

.ecb-stickybar__name {
	font-size: 12px;
	color: var(--ecb-muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.ecb-stickybar__price {
	font-size: 15px;
	font-weight: 600;
	color: var(--ecb-plum);
	line-height: 1.3;
}

.ecb-stickybar__price del { display: none; }
.ecb-stickybar__price ins { text-decoration: none; background: transparent; }
.ecb-stickybar__price .ecb-off { display: none; }

.ecb-stickybar__btn {
	flex: 0 0 auto;
	min-height: 46px;
	padding: 0 22px;
	border: 1px solid var(--ecb-plum);
	border-radius: var(--ecb-radius-sm);
	background-color: var(--ecb-plum);
	color: var(--ecb-ivory);
	font-family: var(--ecb-font-body);
	font-size: 13.5px;
	font-weight: 600;
	letter-spacing: 0.04em;
	cursor: pointer;
	transition: background-color 260ms var(--ecb-ease);
}

.ecb-stickybar__btn:hover { background-color: var(--ecb-charcoal); border-color: var(--ecb-charcoal); }

.ecb-stickybar__btn:focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: 2px;
}

/* The floating contact button must not sit under the bar. */
.ecb-stickybar.is-visible ~ .ecb-fab { bottom: 78px; }

@media (min-width: 1000px) {
	.ecb-stickybar { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	.ecb-stickybar { transition: none; }
}

/* ==========================================================================
   46. Phase 7 — empty states
   A dead end costs a sale, so each one offers a route onward.
   ========================================================================== */
.ecb-empty {
	max-width: 46ch;
	margin: var(--ecb-space-6) auto;
	text-align: center;
}

.ecb-empty__lead {
	font-family: var(--ecb-font-heading);
	font-size: 26px;
	font-weight: 600;
	color: var(--ecb-plum);
	margin: 0 0 var(--ecb-space-2);
}

.ecb-empty__text {
	font-size: 15px;
	color: var(--ecb-muted);
	margin: 0 0 var(--ecb-space-5);
}

.ecb-empty__links {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 10px;
}

.ecb-empty__link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 18px;
	border: 1px solid var(--ecb-border-strong);
	border-radius: var(--ecb-radius-sm);
	font-size: 12.5px;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ecb-plum);
	text-decoration: none;
	transition: background-color 260ms var(--ecb-ease),
	            border-color 260ms var(--ecb-ease),
	            color 260ms var(--ecb-ease);
}

.ecb-empty__link:hover {
	background-color: var(--ecb-plum);
	border-color: var(--ecb-plum);
	color: var(--ecb-ivory);
}

.ecb-empty__link:focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: 2px;
}

/* ==========================================================================
   47. Phase 7 — skip link
   Blocksy already renders `.skip-link.screen-reader-text` pointing at #main,
   so only its appearance is changed here. A second custom link was removed
   rather than styled, to keep exactly one in the tab order.
   ========================================================================== */
.skip-link.screen-reader-text:focus {
	position: absolute;
	left: 0;
	top: 0;
	z-index: 200;
	width: auto;
	height: auto;
	clip: auto;
	clip-path: none;
	padding: 12px 20px;
	background-color: var(--ecb-plum);
	color: var(--ecb-ivory);
	font-family: var(--ecb-font-body);
	font-size: 14px;
	font-weight: 500;
	text-decoration: none;
	border-radius: 0 0 var(--ecb-radius-sm) 0;
	outline: 2px solid var(--ecb-gold);
	outline-offset: -4px;
}

/* The empty-cart block is emitted once per cart render, and Blocksy renders
   two header mini-carts in addition to the page's own cart — all from the
   same WooCommerce template, so they cannot be separated in PHP. The header
   copies are suppressed here; those dropdowns keep WooCommerce's own short
   empty message, which suits their size better than a full block. */
.ct-header .ecb-empty { display: none; }
/* inc/ecb-suggest.php: the header mini-carts must never grow a product row,
   and a 404's row needs the room above the footer the page's own spacing gives. */
.ct-header .ecb-suggest { display: none; }
.ecb-suggest-404 { padding-bottom: var(--theme-content-vertical-spacing, 32px); }

/* ==========================================================================
   48. Phase A — Exchange & Return policy page
   Editorial and flat: one accent rule, no cards-within-cards, no gradients.
   Bengali type comes from the [lang="bn"] rules in section 20, so no second
   font family is loaded here.
   ========================================================================== */
/* No max-width here on purpose. WordPress's constrained layout centres every
   child with `margin-inline: auto !important` and caps it at
   --wp--style--global--content-size. Anything narrower than that cap gets
   auto-centred, which indented this paragraph ~49px from the headings around
   it, and the !important makes it unwinnable from the theme sheet. Letting the
   lead take the same width as its siblings keeps the left edge flush. */
.ecb-policy > .ecb-policy__lead {
	font-size: 1.05em;
	color: var(--ecb-charcoal);
}

/* Compact summary — the four facts a customer checks before reading on. */
.ecb-policy-summary {
	margin: var(--ecb-space-5) 0;
	padding: var(--ecb-space-4) var(--ecb-space-5);
	background-color: var(--ecb-surface);
	border: 1px solid var(--ecb-border);
	border-top: 2px solid var(--ecb-gold);
}

.ecb-policy-summary__title {
	margin: 0 0 var(--ecb-space-3);
	font-family: var(--ecb-font-body);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	/* Plum, not Gold: Gold on this near-ivory surface fails contrast. */
	color: var(--ecb-plum);
}

.ecb-policy-summary ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

.ecb-policy-summary li {
	position: relative;
	padding-left: 18px;
	margin-bottom: 10px;
	font-size: 14.5px;
	line-height: 1.7;
	color: var(--ecb-charcoal);
}

.ecb-policy-summary li:last-child { margin-bottom: 0; }

.ecb-policy-summary li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.75em;
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background-color: var(--ecb-gold);
}

.ecb-policy-summary strong { color: var(--ecb-plum); font-weight: 600; }

/* Section rhythm: a hairline above each heading keeps the long document
   scannable without boxing every section. */
.ecb-policy h3 {
	margin-top: var(--ecb-space-6);
	padding-top: var(--ecb-space-4);
	border-top: 1px solid var(--ecb-border);
}

.ecb-policy h2 + p,
.ecb-policy h3 + p { margin-top: var(--ecb-space-2); }

.ecb-policy ul li,
.ecb-policy ol li { margin-bottom: 8px; }

/* Inline links only. Without the :not() the two-class selector here (0,2,0)
   outranks .ecb-policy-cta__btn--primary (0,1,0) and paints plum text on the
   plum button, making the CTA label invisible — and adds an underline border
   to both buttons. */
.ecb-policy a:not(.ecb-policy-cta__btn) {
	color: var(--ecb-plum);
	text-decoration: none;
	border-bottom: 1px solid var(--ecb-border-strong);
	transition: border-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-policy a:not(.ecb-policy-cta__btn):hover { border-bottom-color: var(--ecb-plum); }

/* Request CTA */
.ecb-policy-cta {
	margin-top: var(--ecb-space-6);
	padding-top: var(--ecb-space-5);
	border-top: 1px solid var(--ecb-border);
}

.ecb-policy-cta__text {
	margin: 0 0 var(--ecb-space-4);
	font-size: 14.5px;
	color: var(--ecb-muted);
}

.ecb-policy-cta__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
}

.ecb-policy-cta__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 48px;
	padding: 0 22px;
	border: 1px solid var(--ecb-border-strong);
	border-radius: var(--ecb-radius-sm);
	font-family: var(--ecb-font-body);
	font-size: 14px;
	font-weight: 500;
	color: var(--ecb-plum);
	text-decoration: none;
	transition: background-color var(--ecb-t-color) var(--ecb-ease),
	            border-color var(--ecb-t-color) var(--ecb-ease),
	            color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-policy-cta__btn:hover {
	background-color: var(--ecb-plum);
	border-color: var(--ecb-plum);
	color: var(--ecb-ivory);
}

.ecb-policy-cta__btn--primary {
	background-color: var(--ecb-plum);
	border-color: var(--ecb-plum);
	color: var(--ecb-ivory);
}

.ecb-policy-cta__btn--primary:hover {
	background-color: var(--ecb-charcoal);
	border-color: var(--ecb-charcoal);
}

.ecb-policy-cta__btn:focus-visible {
	outline: 2px solid var(--ecb-gold);
	outline-offset: 2px;
}

@media (max-width: 480px) {
	.ecb-policy-cta__actions { flex-direction: column; }
	.ecb-policy-cta__btn { width: 100%; }
	.ecb-policy-summary { padding: var(--ecb-space-4); }
}

/* ==========================================================================
   41. Phase M — new collections band (Western / Jewellery)
   ========================================================================== */

.ecb-collections {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
	gap: clamp(1rem, 2.5vw, 1.75rem);
	margin-block: clamp(1.5rem, 4vw, 2.5rem);
}

.ecb-collection {
	position: relative;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border: 1px solid rgba(74, 24, 52, .14);
	border-radius: 12px;
	background: var(--ecb-ivory, #FBF8F3);
	text-decoration: none;
	color: inherit;
	transition: transform .35s ease, box-shadow .35s ease, border-color .35s ease;
}

.ecb-collection:hover,
.ecb-collection:focus-visible {
	transform: translateY(-4px);
	border-color: var(--ecb-gold, #C5A060);
	box-shadow: 0 14px 34px rgba(33, 30, 32, .12);
}

.ecb-collection__media {
	display: block;
	aspect-ratio: 4 / 5;
	overflow: hidden;
	background: rgba(74, 24, 52, .06);
}

.ecb-collection__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform .6s ease;
}

.ecb-collection:hover .ecb-collection__img { transform: scale(1.04); }

.ecb-collection__body {
	display: flex;
	flex-direction: column;
	gap: .4rem;
	padding: clamp(1.1rem, 2.5vw, 1.5rem);
}

.ecb-collection__title {
	font-family: var(--ecb-font-heading);
	font-size: clamp(1.15rem, 2vw, 1.4rem);
	color: var(--ecb-plum, #4A1834);
	letter-spacing: .01em;
}

.ecb-collection__text {
	color: var(--ecb-muted, #75606A);
	font-size: .95rem;
	line-height: 1.5;
}

.ecb-collection__cta {
	margin-top: .35rem;
	font-size: .82rem;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--ecb-plum, #4A1834);
	border-bottom: 1px solid var(--ecb-gold, #C5A060);
	align-self: flex-start;
	padding-bottom: 2px;
}

/* A category with nothing in it yet says so, rather than pretending. */
.ecb-collection--soon .ecb-collection__cta {
	color: var(--ecb-muted, #75606A);
	border-bottom-style: dashed;
}

.ecb-collection--soon::after {
	content: "New";
	position: absolute;
	inset-block-start: .75rem;
	inset-inline-end: .75rem;
	padding: .2rem .6rem;
	font-size: .7rem;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: #fff;
	background: var(--ecb-plum, #4A1834);
	border-radius: 999px;
}

@media (prefers-reduced-motion: reduce) {
	.ecb-collection,
	.ecb-collection__img { transition: none; }
	.ecb-collection:hover { transform: none; }
	.ecb-collection:hover .ecb-collection__img { transform: none; }
}

/* ==========================================================================
   42. Phase M2 — category quick-nav with five categories
   Six chips (All + five) wrap awkwardly on narrow phones. A single scrolling
   row reads as deliberate where a ragged second line does not.
   ========================================================================== */

@media (max-width: 599px) {
	.ecb-cat-quicknav {
		flex-wrap: nowrap;
		justify-content: flex-start;
		overflow-x: auto;
		overscroll-behavior-x: contain;
		scroll-snap-type: x proximity;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		padding-inline: var(--ecb-space-3, 12px);
		margin-inline: calc(-1 * var(--ecb-space-3, 12px));
	}

	.ecb-cat-quicknav::-webkit-scrollbar { display: none; }

	.ecb-cat-quicknav__link {
		flex: 0 0 auto;
		scroll-snap-align: start;
		white-space: nowrap;
	}
}

/* ==========================================================================
   43. Phase M3 — per-category homepage sections
   ========================================================================== */

.ecb-cat-soon {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--ecb-space-2, 8px);
	min-height: 220px;
	padding: clamp(1.75rem, 5vw, 3rem);
	text-align: center;
	border: 1px dashed rgba(74, 24, 52, .22);
	border-radius: 12px;
	background: var(--ecb-ivory, #FBF8F3);
}

.ecb-cat-soon__label {
	margin: 0;
	font-size: 12px;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--ecb-gold, #C5A060);
}

.ecb-cat-soon__text {
	margin: 0;
	max-width: 46ch;
	color: var(--ecb-muted, #75606A);
	line-height: 1.6;
}

.ecb-cat-soon__bn {
	margin: 0;
	color: var(--ecb-muted, #75606A);
	font-size: .92rem;
}

.ecb-cat-more {
	margin: var(--ecb-space-4, 20px) 0 0;
	text-align: center;
}

.ecb-cat-more__link {
	display: inline-block;
	font-family: var(--ecb-font-body);
	font-size: 13px;
	font-weight: 500;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--ecb-plum, #4A1834);
	text-decoration: none;
	padding-bottom: 3px;
	border-bottom: 1px solid var(--ecb-gold, #C5A060);
	transition: color var(--ecb-t-color, .2s) var(--ecb-ease, ease),
	            border-color var(--ecb-t-color, .2s) var(--ecb-ease, ease);
}

.ecb-cat-more__link:hover,
.ecb-cat-more__link:focus-visible {
	color: var(--ecb-gold, #C5A060);
	border-bottom-color: var(--ecb-plum, #4A1834);
}

/* ==========================================================================
   44. Phase M3 — shipping row alignment in cart & checkout totals

   Blocksy replaces WooCommerce's two-cell shipping row with a single
   <td colspan="2"> holding a .ct-shipping-heading block above the method list.
   With several couriers to choose between that reads correctly, but this shop
   offers exactly one delivery method, so the label and its amount ended up on
   separate lines while every neighbouring row was label-left / amount-right.

   The :has() guard applies the single-line treatment only when there is one
   method to show. If more are ever offered — or the browser lacks :has() —
   the row falls back to Blocksy's stacked list, which is the right shape for
   a genuine choice.
   ========================================================================== */

.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child) {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--ecb-space-4, 20px);
}

.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child)
	.ct-shipping-heading {
	flex: 1 1 auto;
	margin: 0;
	/* match the neighbouring <th> cells */
	font-weight: 500;
	color: var(--ecb-charcoal, #211E20);
}

.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child)
	ul#shipping_method {
	flex: 0 0 auto;
	margin: 0;
	padding: 0;
	list-style: none;
	text-align: right;
}

.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child)
	ul#shipping_method li {
	margin: 0;
	padding: 0;
}

/* The single method needs no radio affordance — there is nothing to choose. */
.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child)
	ul#shipping_method label {
	margin: 0;
	font-weight: 400;
	white-space: nowrap;
}

/* Very narrow screens: let it stack again rather than squeeze. */
@media (max-width: 380px) {
	.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child) {
		display: block;
	}
	.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child)
		ul#shipping_method {
		text-align: left;
		margin-top: .25rem;
	}
}

/* ==========================================================================
   45. Phase M4 — shipping row fallback for engines without :has()

   Section 44 uses :has() to apply the single-line treatment only when one
   delivery method is offered. Where :has() is unavailable the row would fall
   back to Blocksy's stacked layout, which is what M4 set out to fix — so give
   those engines the same label-left / amount-right result unconditionally.
   The shop offers exactly one method, so nothing is lost by doing so.
   ========================================================================== */

@supports not (selector(:has(*))) {
	.woocommerce-shipping-totals > td {
		display: flex;
		align-items: baseline;
		justify-content: space-between;
		gap: var(--ecb-space-4, 20px);
	}

	.woocommerce-shipping-totals > td .ct-shipping-heading {
		flex: 1 1 auto;
		margin: 0;
		font-weight: 500;
		color: var(--ecb-charcoal, #211E20);
	}

	.woocommerce-shipping-totals > td ul#shipping_method {
		flex: 0 0 auto;
		margin: 0;
		padding: 0;
		list-style: none;
		text-align: right;
	}

	.woocommerce-shipping-totals > td ul#shipping_method li { margin: 0; padding: 0; }
	.woocommerce-shipping-totals > td ul#shipping_method label { margin: 0; font-weight: 400; white-space: nowrap; }
}

/* The shipping row spans both columns, so its inner amount needs the same
   tabular alignment the neighbouring value cells get. */
.woocommerce-shipping-totals ul#shipping_method label {
	font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   49. Phase M6 — Premium visual system
   --------------------------------------------------------------------------
   One system layer, applied through the tokens in section 1. Everything here
   is deliberately written against selectors that already exist in Blocksy,
   WooCommerce or ECB Commerce Core markup — nothing invents a wrapper.

   Sections 2-48 stay where they are: they are working, and rewriting 4,000
   lines that cannot be visually verified from a shell would trade a real site
   for a tidier file. What M6 does instead is normalise the *system* — type,
   weight, tracking, focus, rhythm, radii — so those older rules inherit the
   corrected values rather than each carrying its own.
   ========================================================================== */

/* --------------------------------------------------------------------------
   49.1 Typography — fluid scale, restrained weights
   Blocksy compiles customizer typography into `--theme-*` custom properties at
   low specificity in uploads/blocksy/css/global.css, which loads before this
   file. Redeclaring the same properties here therefore wins on source order
   without a single !important, and keeps the customizer as the fallback.
   -------------------------------------------------------------------------- */
:root {
	--theme-font-size: var(--ecb-fs-body);
	--theme-line-height: var(--ecb-lh-body);
	--theme-font-family: var(--ecb-font-body);
}

h1,
.entry-title,
.ecb-display {
	--theme-font-family: var(--ecb-font-heading);
	--theme-font-size: var(--ecb-fs-display);
	--theme-font-weight: var(--ecb-fw-emphasis);
	--theme-line-height: var(--ecb-lh-display);
	--theme-letter-spacing: var(--ecb-ls-display);
}

h2 {
	--theme-font-size: var(--ecb-fs-h2);
	--theme-font-weight: var(--ecb-fw-ui);
	--theme-line-height: var(--ecb-lh-heading);
}

h3 {
	--theme-font-size: var(--ecb-fs-h3);
	--theme-font-weight: var(--ecb-fw-ui);
	--theme-line-height: var(--ecb-lh-heading);
}

h4 {
	--theme-font-size: var(--ecb-fs-h4);
	--theme-font-weight: var(--ecb-fw-ui);
	--theme-line-height: var(--ecb-lh-heading);
}

/* Bengali never falls back to a system face. The Bengali block also carries
   U+09F3 (৳), so this governs every price on the site as well as Bangla copy. */
:lang(bn),
.ecb-bkash__bn,
.ecb-card__sentence-bn,
.ecb-bkash__status-bn {
	font-family: var(--ecb-font-bangla);
}

/* Long labels stay sentence case. Uppercase is allowed only where the label is
   short by construction: eyebrows, nav items and compact badges. Section 14's
   `table.shop_table th` rule was written for the PRODUCT / SUBTOTAL column
   headings but also caught the totals labels, which is why "PRODUCTS SUBTOTAL"
   shouted; M5.1 corrected that and this keeps the rule from creeping back. */
.woocommerce table.shop_table tfoot th,
.woocommerce table.shop_table tfoot td,
.cart_totals table.shop_table th,
.woocommerce-checkout-review-order-table tfoot th {
	text-transform: none;
	letter-spacing: var(--ecb-ls-body);
	font-weight: var(--ecb-fw-ui);
	font-size: var(--ecb-fs-sm);
}

.ecb-eyebrow {
	font-size: var(--ecb-fs-eyebrow);
	font-weight: var(--ecb-fw-emphasis);
	letter-spacing: var(--ecb-ls-caps-wide);
}

/* --------------------------------------------------------------------------
   49.2 Surfaces and focus
   -------------------------------------------------------------------------- */
body {
	background-color: var(--ecb-page);
	color: var(--ecb-ink);
	/* `clip` rather than `hidden`: it contains a stray wide child without
	   creating a scroll container, so position:sticky keeps working. */
	overflow-x: clip;
}

/* Nothing may push the page sideways at any width. */
img,
video,
iframe,
table {
	max-width: 100%;
}

/* One focus treatment for the whole site: a plum ring plus a soft gold halo.
   Contrast against the cream ground is ~13:1, against the plum header the
   ring flips to cream. Both are token swaps, not new selectors. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
.wp-block-button__link:focus-visible,
.ct-menu-link:focus-visible {
	outline: var(--ecb-focus-width) solid var(--ecb-focus-ring);
	outline-offset: var(--ecb-focus-offset);
	box-shadow: 0 0 0 calc(var(--ecb-focus-width) + var(--ecb-focus-offset) + 2px) var(--ecb-focus-halo);
	border-radius: var(--ecb-radius-sm);
}

/* Plum grounds: the ring inverts so it stays visible. */
.ct-header [data-row="top"],
.ct-header [data-row="middle"],
.ct-footer,
.ecb-section--plum {
	--ecb-focus-ring: var(--ecb-ink-inverse);
	--ecb-focus-halo: rgba(251, 248, 243, 0.28);
}

/* --------------------------------------------------------------------------
   49.3 Header and navigation
   The two rows previously read as two unrelated bars. They are now bound by a
   single hairline in the brand tone, with row 2 quieter than row 1 — hierarchy
   by weight and tone, not by adding chrome.
   -------------------------------------------------------------------------- */

/* Announcement bar: slim and calm. */
.ct-header [data-row="top"] .ecb-rotator {
	font-size: var(--ecb-fs-xs);
	font-weight: var(--ecb-fw-body);
	letter-spacing: var(--ecb-ls-ui);
}

/* Navigation labels are short, so uppercase is appropriate — at 500, because
   uppercase at 400 goes thin and ragged once it is tracked out. */
.ct-header .ct-menu-link {
	font-weight: var(--ecb-fw-ui);
}

/* Hover marks the item with the same underline the current section uses, so
   the two read as one language. Opacity, never height: an underline that
   appears on hover by changing box size shifts the row. */
.header-menu-1 > li > .ct-menu-link,
.header-menu-2 > li > .ct-menu-link {
	position: relative;
}

.header-menu-1 > li > .ct-menu-link::after,
.header-menu-2 > li > .ct-menu-link::after {
	content: "";
	position: absolute;
	left: 18px;
	right: 18px;
	bottom: 10px;
	height: 1px;
	background-color: var(--ecb-gold);
	opacity: 0;
	transition: opacity var(--ecb-t-color) var(--ecb-ease);
}

.header-menu-1 > li > .ct-menu-link:hover::after,
.header-menu-2 > li > .ct-menu-link:hover::after,
.header-menu-1 > li.current-menu-item > .ct-menu-link::after,
.header-menu-1 > li.current-menu-ancestor > .ct-menu-link::after,
.header-menu-2 > li.current-menu-item > .ct-menu-link::after,
.header-menu-2 > li.current-menu-ancestor > .ct-menu-link::after {
	opacity: 1;
}

/* The category row belongs to the header, not under it. */
.ct-header [data-row="bottom"] {
	border-top: 1px solid var(--ecb-border);
	background-color: var(--ecb-page);
}

/* Header actions must stay comfortably tappable on a phone. */
.ct-header [data-id="cart"] > a,
.ct-header [data-id="account"] > a,
.ct-header [data-id="search"] > *,
.ct-header [data-id="trigger"] {
	min-height: var(--ecb-tap);
	min-width: var(--ecb-tap);
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

/* --------------------------------------------------------------------------
   49.4 Homepage — one section family
   Every band inherits the same rhythm ladder, so New Arrivals, Featured, Best
   Sellers, Western and Jewellery stay visibly separate sections while sharing
   one spine.
   -------------------------------------------------------------------------- */
.ecb-section {
	padding-top: var(--ecb-section-y);
	padding-bottom: var(--ecb-section-y);
}

.ecb-section + .ecb-section:not(.ecb-section--surface),
.ecb-section--surface + .ecb-section--surface {
	padding-top: var(--ecb-section-seam);
}

.ecb-section--tight {
	padding-top: var(--ecb-section-y-tight);
	padding-bottom: var(--ecb-section-y-tight);
}

.ecb-section-head h2 {
	font-family: var(--ecb-font-body);
	letter-spacing: var(--ecb-ls-body);
}

.ecb-section-head p {
	font-size: var(--ecb-fs-sm);
	line-height: var(--ecb-lh-tight);
	color: var(--ecb-ink-muted);
	max-width: 60ch;
}

/* --------------------------------------------------------------------------
   49.5 Product cards and archives
   Cards previously sized to their own content, so a two-line product name in
   one column pushed its price a line below its neighbour's. The grid item is
   now a column: media, then a name block that reserves its space, then the
   price pinned to the bottom. Prices line up across the row at every width.
   -------------------------------------------------------------------------- */
.woocommerce ul.products li.product {
	display: flex;
	flex-direction: column;
}

.woocommerce ul.products li.product > .woocommerce-loop-product__link {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}

.woocommerce ul.products li.product .woocommerce-loop-product__title {
	font-size: var(--ecb-fs-sm);
	font-weight: var(--ecb-fw-ui);
	line-height: var(--ecb-lh-tight);
	letter-spacing: var(--ecb-ls-body);
	/* Two lines reserved, so the price baseline is the same across the row
	   whether the name wraps or not. */
	min-height: calc(2 * var(--ecb-lh-tight) * var(--ecb-fs-sm));
}

.woocommerce ul.products li.product .price {
	margin-top: auto;
	font-size: var(--ecb-fs-sm);
	font-weight: var(--ecb-fw-emphasis);
	letter-spacing: var(--ecb-ls-body);
	font-variant-numeric: tabular-nums;
}

/* Sale price stays encouraging, not loud: the old figure recedes, the new one
   carries the brand colour, and neither is shouted. */
.woocommerce ul.products li.product .price del,
.woocommerce ul.products li.product .price del .amount {
	font-weight: var(--ecb-fw-body);
	color: var(--ecb-ink-muted);
	font-size: 0.92em;
}

.woocommerce ul.products li.product .onsale {
	font-weight: var(--ecb-fw-emphasis);
	letter-spacing: var(--ecb-ls-caps);
}

/* Add to cart in a grid is a real pointer target. */
.woocommerce ul.products li.product .button {
	min-height: var(--ecb-tap);
	font-weight: var(--ecb-fw-ui);
	letter-spacing: var(--ecb-ls-ui);
}

/* Hover lift only where there is media to lift, and only for pointer devices
   that can actually hover. */
@media (hover: hover) and (pointer: fine) {
	.woocommerce ul.products li.product .ct-media-container img {
		transition: transform var(--ecb-t-image) var(--ecb-ease);
	}

	.woocommerce ul.products li.product:hover .ct-media-container img {
		transform: scale(1.03);
	}
}

/* --------------------------------------------------------------------------
   49.6 Single product
   Sections 40-43 already lay this page out. M6 only normalises its type so it
   belongs to the same family as everything else.
   -------------------------------------------------------------------------- */
.single-product div.product .product_title {
	font-family: var(--ecb-font-heading);
	font-weight: var(--ecb-fw-emphasis);
	line-height: var(--ecb-lh-display);
	letter-spacing: var(--ecb-ls-display);
}

.single-product div.product p.price,
.single-product div.product span.price {
	font-weight: var(--ecb-fw-emphasis);
	font-variant-numeric: tabular-nums;
	letter-spacing: var(--ecb-ls-body);
}

.single-product div.product p.price del {
	font-weight: var(--ecb-fw-body);
	color: var(--ecb-ink-muted);
}

/* Selectors, quantity and Add to Cart all clear the tap minimum. */
.single-product div.product .variations select,
.single-product div.product .quantity input.qty,
.single-product div.product button.single_add_to_cart_button,
.single-product div.product .variable-items-wrapper .variable-item {
	min-height: var(--ecb-tap);
}

.single-product div.product button.single_add_to_cart_button {
	font-weight: var(--ecb-fw-ui);
	letter-spacing: var(--ecb-ls-ui);
}

/* A swatch that is merely "not selected" must not look disabled, and the
   selected state is carried by border + check, never by colour alone. */
.variable-items-wrapper .variable-item.selected,
.variable-items-wrapper .variable-item[aria-checked="true"] {
	box-shadow: 0 0 0 2px var(--ecb-plum);
}

/* --------------------------------------------------------------------------
   49.7 Cart and checkout
   Presentation only. Every amount, rule and label here is produced by
   ECB Commerce Core; M6 does not touch how any of it is calculated.
   -------------------------------------------------------------------------- */
.woocommerce table.shop_table td,
.woocommerce table.shop_table th,
.cart_totals .amount,
.woocommerce-checkout-review-order-table .amount {
	font-variant-numeric: tabular-nums;
}

/* Amounts align on their right edge so the column scans as a column. */
.woocommerce table.shop_table tfoot td,
.woocommerce-checkout-review-order-table tfoot td {
	text-align: right;
}

/* The Total is the one figure that should be unmistakable. Weight and size
   carry it — no tinted band, which M5.1 removed for reading as a warning. */
.woocommerce table.shop_table tfoot tr.order-total th,
.woocommerce table.shop_table tfoot tr.order-total td {
	border-top: 1px solid var(--ecb-border-strong);
	padding-top: var(--ecb-space-3);
	font-size: var(--ecb-fs-h4);
	font-weight: var(--ecb-fw-emphasis);
	color: var(--ecb-plum);
}

/* Savings stays a single compact line (M5.1). */
.ecb-savings {
	font-size: var(--ecb-fs-xs);
	font-weight: var(--ecb-fw-ui);
	white-space: nowrap;
}

/* Forms read as one set of controls, not as whatever each plugin shipped. */
.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.woocommerce-checkout input.input-text,
.woocommerce-checkout select {
	min-height: var(--ecb-tap);
	font-family: var(--ecb-font-body);
	font-size: var(--ecb-fs-body);
	border-radius: var(--ecb-radius-ctl);
}

.woocommerce form .form-row label {
	font-size: var(--ecb-fs-sm);
	font-weight: var(--ecb-fw-ui);
	letter-spacing: var(--ecb-ls-body);
	text-transform: none;
}

/* Validation is never colour alone: the field also gains a visible ring and
   the message carries text. */
.woocommerce form .form-row.woocommerce-invalid input.input-text,
.woocommerce form .form-row.woocommerce-invalid select {
	border-color: var(--ecb-sale);
	box-shadow: 0 0 0 1px var(--ecb-sale);
}

.woocommerce-error,
.woocommerce-info,
.woocommerce-message {
	font-size: var(--ecb-fs-sm);
	line-height: var(--ecb-lh-tight);
	border-radius: var(--ecb-radius-ctl);
}

/* Payment method cards share the summary card's language. */
.woocommerce-checkout #payment ul.payment_methods li label {
	font-weight: var(--ecb-fw-ui);
	font-size: var(--ecb-fs-body);
}

/* The floating contact button must never sit on top of the button that
   completes an order. Reserve its footprint at the end of the page instead. */
.woocommerce-checkout #payment,
.woocommerce-cart .wc-proceed-to-checkout {
	padding-bottom: var(--ecb-space-2);
}

@media (max-width: 782px) {
	.woocommerce-checkout .woocommerce,
	.woocommerce-cart .woocommerce {
		padding-bottom: calc(var(--ecb-tap) + var(--ecb-space-5));
	}
}

/* --------------------------------------------------------------------------
   49.8 Account, order and tracking
   Same cards, same labels, same badges as the rest of the site. Content and
   order-status logic are untouched — this is type and spacing only.
   -------------------------------------------------------------------------- */
.woocommerce-MyAccount-navigation ul li a,
.woocommerce-MyAccount-content h2,
.woocommerce-order-details h2,
.woocommerce-customer-details h2 {
	font-family: var(--ecb-font-body);
	font-weight: var(--ecb-fw-ui);
	letter-spacing: var(--ecb-ls-body);
}

.woocommerce-MyAccount-navigation ul li a {
	min-height: var(--ecb-tap);
	display: flex;
	align-items: center;
}

.ecb-card {
	border-radius: var(--ecb-radius-card);
	box-shadow: var(--ecb-shadow-sm);
}

.ecb-progress__step {
	font-size: var(--ecb-fs-xs);
	letter-spacing: var(--ecb-ls-body);
}

/* --------------------------------------------------------------------------
   49.9 Footer
   Hierarchy through type and space using the content that is already there.
   No invented guarantees, links, badges or claims.
   -------------------------------------------------------------------------- */
.ct-footer .widget-title,
.ct-footer h3 {
	font-family: var(--ecb-font-body);
	font-size: var(--ecb-fs-xs);
	font-weight: var(--ecb-fw-emphasis);
	letter-spacing: var(--ecb-ls-caps);
	text-transform: uppercase;
}

.ct-footer,
.ct-footer p,
.ct-footer li {
	font-size: var(--ecb-fs-sm);
	line-height: var(--ecb-lh-body);
}

/* Only standalone links get a reserved height. Applying inline-flex to every
   footer <a> would stop a link inside a sentence from wrapping mid-phrase. */
.ct-footer li > a,
.ct-footer .ct-footer-socials a {
	min-height: 24px;
	display: inline-flex;
	align-items: center;
}

/* --------------------------------------------------------------------------
   49.10 Responsive and accessibility safeguards
   -------------------------------------------------------------------------- */

/* Long unbroken strings — order numbers, tracking ids, emails — wrap rather
   than widening their container and scrolling the page. */
.woocommerce-order-details,
.woocommerce-customer-details,
.woocommerce table.shop_table td,
.ecb-card {
	overflow-wrap: anywhere;
}

/* Wide tables scroll inside themselves, never taking the page with them. */
@media (max-width: 782px) {
	.woocommerce table.shop_table_responsive,
	.woocommerce-order-details table {
		display: block;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
	}
}

/* Narrow phones: 360-430px is the real floor for this audience. Keep the grid
   at two columns rather than dropping to one — a single column of 4:5 images
   turns the shop into a very long scroll. */
@media (max-width: 430px) {
	.woocommerce ul.products {
		gap: var(--ecb-space-3);
	}

	.woocommerce ul.products li.product .woocommerce-loop-product__title {
		font-size: var(--ecb-fs-xs);
	}
}

/* Windows High Contrast / forced colours: stop painting our own palette and
   let the user's colours through, but keep the structure legible. */
@media (forced-colors: active) {
	.ecb-card,
	.woocommerce ul.products li.product .ct-media-container,
	.woocommerce-checkout #payment ul.payment_methods li {
		border: 1px solid CanvasText;
	}

	a:focus-visible,
	button:focus-visible,
	input:focus-visible,
	select:focus-visible,
	textarea:focus-visible,
	.ct-menu-link:focus-visible {
		outline: 2px solid Highlight;
		box-shadow: none;
	}

	/* Decorative rules and tints carry no meaning here. */
	.ecb-savings,
	.ecb-price__save {
		forced-color-adjust: none;
	}
}

/* Motion: section 2 already reduces durations globally. Reinforce it for the
   transforms M6 introduces, which are the ones a vestibular user notices. */
@media (prefers-reduced-motion: reduce) {
	.woocommerce ul.products li.product:hover .ct-media-container img {
		transform: none;
	}
}

/* --------------------------------------------------------------------------
   49.11 One discount statement per card
   Audit finding: a discounted card was carrying the same news three times —
   an "18% OFF" corner flag, WooCommerce's own "SALE" badge, and a second
   "18% OFF" beside the price (the get_price_html filter adds that one
   everywhere). Three shouts for one markdown is the "loud" the brief warns
   about, and it crowds the product name.

   Kept per context: exactly one percentage, plus the struck-through original
   and the new price, which are the substance. Nothing is deleted from the
   markup — this is presentation, and removing a rule restores the old badge.
   The hidden elements carry no information the remaining ones lack, and the
   del/ins pair keeps its own screen-reader text either way.
   -------------------------------------------------------------------------- */

/* On a card the corner flag is the clearest place for the percentage. */
.woocommerce ul.products li.product .onsale,
.woocommerce ul.products li.product .price .ecb-off {
	display: none;
}

/* On the single product page there is no corner flag, so the inline figure
   beside the price is the one that stays and the SALE badge goes. */
.single-product div.product > span.onsale,
.single-product div.product .woocommerce-product-gallery span.onsale {
	display: none;
}

/* --------------------------------------------------------------------------
   49.12 Card image ratio, both markup shapes
   Blocksy wraps archive thumbnails in .ct-media-container, but the shortcode
   loops the homepage sections use render a bare <img> inside the product link.
   Section 9 only styled the wrapped shape, so homepage cards were free to take
   whatever ratio the source image had while archive cards were locked to 4:5.
   That is the inconsistency the brief describes; this covers the second shape.
   -------------------------------------------------------------------------- */
.woocommerce ul.products li.product > .woocommerce-loop-product__link > img {
	aspect-ratio: 4 / 5;
	object-fit: cover;
	width: 100%;
	height: auto;
	display: block;
	border-radius: var(--ecb-radius-sm);
	border: 1px solid var(--ecb-border);
	background-color: var(--ecb-ivory);
	margin-bottom: var(--ecb-space-2);
}

@media (hover: hover) and (pointer: fine) {
	.woocommerce ul.products li.product > .woocommerce-loop-product__link > img {
		transition: transform var(--ecb-t-image) var(--ecb-ease);
	}

	.woocommerce ul.products li.product:hover > .woocommerce-loop-product__link > img {
		transform: scale(1.03);
	}
}

@media (prefers-reduced-motion: reduce) {
	.woocommerce ul.products li.product:hover > .woocommerce-loop-product__link > img {
		transform: none;
	}
}

/* The corner flag sits over the image in both shapes. */
.woocommerce ul.products li.product .ecb-card-flags {
	z-index: 2;
}

/* ==========================================================================
   50. Phase M7 — catalogue presentation
   Built entirely on the M6 tokens: no new colours, no new sizes, no new radii.
   If a value here is not a var(), it is a layout number that has no token.
   ========================================================================== */

/* --------------------------------------------------------------------------
   50.1 Shop search
   The site had none. It sits above the grid on shop and category archives and,
   inside a category, keeps the search scoped to that category.
   -------------------------------------------------------------------------- */
.ecb-shopsearch {
	display: flex;
	align-items: center;
	gap: var(--ecb-space-2);
	width: 100%;
	max-width: 460px;
	margin: 0 0 var(--ecb-space-4);
	padding: 0 var(--ecb-space-2) 0 var(--ecb-space-3);
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-ctl);
	background-color: var(--ecb-surface-raised);
	transition: border-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-shopsearch:focus-within {
	border-color: var(--ecb-border-strong);
}

.ecb-shopsearch__icon {
	display: inline-flex;
	color: var(--ecb-ink-muted);
	flex: 0 0 auto;
}

.ecb-shopsearch__field {
	flex: 1 1 auto;
	min-width: 0;
	min-height: var(--ecb-tap);
	border: 0;
	background: none;
	padding: 0;
	font-family: var(--ecb-font-body);
	font-size: var(--ecb-fs-sm);
	color: var(--ecb-ink);
}

/* The wrapper already shows focus, so the inner field must not draw a second
   ring inside it. Keyboard focus stays visible via :focus-within above. */
.ecb-shopsearch__field:focus,
.ecb-shopsearch__field:focus-visible {
	outline: none;
	box-shadow: none;
}

.ecb-shopsearch__field::placeholder {
	color: var(--ecb-ink-muted);
	opacity: 1;
}

/* Chrome and Safari add their own clear button; it collides with our padding. */
.ecb-shopsearch__field::-webkit-search-decoration,
.ecb-shopsearch__field::-webkit-search-results-button {
	display: none;
}

.ecb-shopsearch__submit {
	flex: 0 0 auto;
	min-height: 36px;
	padding: 0 var(--ecb-space-3);
	border: 0;
	border-radius: var(--ecb-radius-sm);
	background-color: var(--ecb-plum);
	color: var(--ecb-ink-inverse);
	font-family: var(--ecb-font-body);
	font-size: var(--ecb-fs-xs);
	font-weight: var(--ecb-fw-ui);
	letter-spacing: var(--ecb-ls-ui);
	cursor: pointer;
	transition: background-color var(--ecb-t-button) var(--ecb-ease);
}

.ecb-shopsearch__submit:hover {
	background-color: var(--ecb-ink);
}

@media (max-width: 480px) {
	.ecb-shopsearch {
		max-width: none;
	}

	/* The magnifier and the placeholder already say what the button says. */
	.ecb-shopsearch__submit {
		padding: 0 var(--ecb-space-2);
	}
}

/* --------------------------------------------------------------------------
   50.2 Empty collection — distinct from a failed search
   -------------------------------------------------------------------------- */
.ecb-empty--soon .ecb-empty__lead {
	font-family: var(--ecb-font-heading);
	font-size: var(--ecb-fs-h2);
	font-weight: var(--ecb-fw-emphasis);
	line-height: var(--ecb-lh-heading);
	letter-spacing: var(--ecb-ls-display);
	color: var(--ecb-plum);
}

/* --------------------------------------------------------------------------
   50.3 Category intro
   Renders only when a description exists — every category is empty today, so
   this is structure waiting for copy, not a placeholder that shows through.
   -------------------------------------------------------------------------- */
.ecb-cat-intro {
	max-width: 68ch;
	margin: 0 0 var(--ecb-space-5);
	color: var(--ecb-ink-muted);
	font-size: var(--ecb-fs-sm);
	line-height: var(--ecb-lh-body);
}

.ecb-cat-intro > :first-child { margin-top: 0; }
.ecb-cat-intro > :last-child { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   50.4 Stock
   Low stock is never signalled by colour alone: the wording carries the fact
   ("Only 2 left") and the colour only reinforces it.
   -------------------------------------------------------------------------- */
.woocommerce .stock.ecb-stock-low {
	color: var(--ecb-sale);
	font-weight: var(--ecb-fw-emphasis);
}

@media (forced-colors: active) {
	.woocommerce .stock.ecb-stock-low {
		color: CanvasText;
	}
}

/* ==========================================================================
   51. Phase M6.1 — confirmed visual corrections
   Each block below fixes one reported problem and states the cause. No area
   that was working is redesigned, and every value comes from the M6 tokens.
   ========================================================================== */

/* --------------------------------------------------------------------------
   51.1 Nothing may scroll the document sideways
   M6 put `overflow-x: clip` on body, which contains a stray wide child but
   does nothing about a child that is legitimately wider than its parent. The
   usual culprits on this site are the totals tables and the summary card,
   where a long amount plus a long label exceed a 360px column.
   -------------------------------------------------------------------------- */
html {
	overflow-x: clip;
}

.ecb-summary,
.woocommerce-checkout-review-order,
.cart_totals,
.woocommerce-cart-form {
	max-width: 100%;
	min-width: 0;
}

/* A grid or flex child refuses to shrink below its content unless told to.
   This single line is what actually stops a long price pushing the card wide. */
.ecb-summary *,
.cart_totals *,
.woocommerce-checkout-review-order * {
	min-width: 0;
}

/* --------------------------------------------------------------------------
   51.2 Checkout and cart summary at 360–425px
   Labels and amounts were laid out as two competing columns; at narrow widths
   neither could shrink and the amount escaped the card. Labels now wrap, the
   amount never does, and the amount keeps its own column.
   -------------------------------------------------------------------------- */
@media (max-width: 480px) {
	.woocommerce table.shop_table th,
	.woocommerce table.shop_table td {
		padding-inline: 8px;
		overflow-wrap: anywhere;
	}

	.woocommerce table.shop_table tfoot th {
		width: 55%;
		overflow-wrap: anywhere;
		hyphens: auto;
	}

	.woocommerce table.shop_table tfoot td {
		width: 45%;
		white-space: nowrap;
		text-align: right;
	}

	/* The Total must stay legible without becoming the widest thing on screen. */
	.woocommerce table.shop_table tfoot tr.order-total td {
		font-size: 1rem;
	}

	/* Old price above new price rather than beside it: side by side, plus a
	   saving chip, is three amounts on one line at 360px. */
	.ecb-price {
		display: flex;
		flex-wrap: wrap;
		align-items: baseline;
		gap: 2px 8px;
	}

	.ecb-price__was,
	.ecb-price__now,
	.ecb-price__save {
		white-space: nowrap;
	}

	.ecb-savings,
	.ecb-savings-row td {
		white-space: nowrap;
		font-size: var(--ecb-fs-xs);
	}

	/* Item rows: thumbnail, then a column that is allowed to shrink. */
	.ecb-summary__item {
		gap: 10px;
	}

	.ecb-summary__meta,
	.ecb-summary__name {
		min-width: 0;
		overflow-wrap: anywhere;
	}
}

/* --------------------------------------------------------------------------
   51.3 The floating contact button must never cover content
   It is fixed at the bottom-right with a 52px target. On checkout that put it
   over the order summary and the place-order button; on a product page it
   covered the gallery controls. Pages that end in an action now reserve its
   footprint, and it steps aside for the sticky purchase bar (already handled).
   -------------------------------------------------------------------------- */
.woocommerce-checkout .site-main,
.woocommerce-cart .site-main,
.single-product .site-main {
	padding-bottom: calc(52px + var(--ecb-space-5));
}

@media (max-width: 782px) {
	/* Slightly tighter to the corner on a phone, where every pixel of the
	   summary card matters more than the button's breathing room. */
	.ecb-fab {
		right: 12px;
		bottom: 12px;
	}
}

/* --------------------------------------------------------------------------
   51.4 Search glyph was oversized
   Blocksy sizes the header search icon from its own font-size, which the M6
   fluid type scale pushed up. The glyph is constrained directly while the 44px
   hit area set in M6 is left alone — shrinking the target would trade one
   accessibility problem for another.
   -------------------------------------------------------------------------- */
.ct-header [data-id="search"] svg,
.ct-header [data-id="search"] .ct-icon {
	width: 19px;
	height: 19px;
}

.ecb-shopsearch__icon svg {
	width: 17px;
	height: 17px;
}

/* --------------------------------------------------------------------------
   51.5 Section heading alignment
   .ecb-section-head was capped at the narrow container (750px) while the
   product grid below it uses the full container. On a wide screen the heading
   therefore started at the same left edge but the eyebrow and copy stopped
   short, which read as misalignment. The head now shares the grid's width and
   the supporting copy keeps its own comfortable measure.
   -------------------------------------------------------------------------- */
.ecb-section-head {
	max-width: none;
}

.ecb-section-head p {
	max-width: 60ch;
}

/* --------------------------------------------------------------------------
   51.6 Discount badge joins the brand palette
   --ecb-sale (#E01B24) was chosen when the badge had to shout. Against plum
   and cream it reads as a system warning rather than an offer. Plum ground
   with cream text measures ~13:1, so it is more legible than the red was, and
   it is the only sale indicator on the card — WooCommerce's own ribbon and the
   inline percentage stay hidden (M6).
   -------------------------------------------------------------------------- */
.ecb-flag--off {
	background-color: var(--ecb-plum);
	color: var(--ecb-ivory);
	border: 1px solid var(--ecb-gold);
	font-weight: var(--ecb-fw-ui);
	letter-spacing: var(--ecb-ls-caps);
}

/* The struck original stays quiet; the sale figure carries the brand colour
   rather than an alarm colour. */
.woocommerce ul.products li.product .price ins,
.woocommerce ul.products li.product .price ins .amount {
	color: var(--ecb-plum);
}

/* Keep the red for genuine problems only — validation and out-of-stock. */
.ecb-flag--oos {
	background-color: rgba(33, 30, 32, 0.88);
	color: var(--ecb-ivory);
}

/* --------------------------------------------------------------------------
   51.7 Card category metadata
   The category line under a product name carried a permanent underline, which
   made every card look like a page of links. It is quiet by default and only
   underlines on hover or keyboard focus.
   -------------------------------------------------------------------------- */
.woocommerce ul.products li.product .posted_in,
.woocommerce ul.products li.product .ecb-card-cat,
.woocommerce ul.products li.product .ecb-card-meta {
	font-size: var(--ecb-fs-xs);
	color: var(--ecb-ink-muted);
	letter-spacing: var(--ecb-ls-body);
}

.woocommerce ul.products li.product .posted_in a,
.woocommerce ul.products li.product .ecb-card-cat a,
.woocommerce ul.products li.product .ecb-card-meta a {
	color: inherit;
	text-decoration: none;
	border-bottom: 0;
}

.woocommerce ul.products li.product .posted_in a:hover,
.woocommerce ul.products li.product .ecb-card-cat a:hover,
.woocommerce ul.products li.product .ecb-card-meta a:hover,
.woocommerce ul.products li.product .posted_in a:focus-visible,
.woocommerce ul.products li.product .ecb-card-cat a:focus-visible,
.woocommerce ul.products li.product .ecb-card-meta a:focus-visible {
	color: var(--ecb-plum);
	text-decoration: underline;
	text-underline-offset: 2px;
}

/* --------------------------------------------------------------------------
   51.8 Cart and checkout opened with too much empty space
   The page-title band plus the section rhythm plus WooCommerce's own margin
   stacked into a large void above the first thing a customer needs to read.
   -------------------------------------------------------------------------- */
.woocommerce-cart .site-main,
.woocommerce-checkout .site-main {
	padding-top: var(--ecb-space-4);
}

.woocommerce-cart .entry-content > .woocommerce,
.woocommerce-checkout .entry-content > .woocommerce {
	margin-top: 0;
}

.woocommerce-cart .woocommerce-notices-wrapper:empty,
.woocommerce-checkout .woocommerce-notices-wrapper:empty {
	display: none;
}

@media (max-width: 782px) {
	.woocommerce-cart .site-main,
	.woocommerce-checkout .site-main {
		padding-top: var(--ecb-space-3);
	}
}

/* --------------------------------------------------------------------------
   51.9 Checkout's double box
   The review-order card sat inside another bordered wrapper, so every amount
   was framed twice. The outer frame loses its border and background; the card
   keeps them, because the card is the thing that should read as a panel.
   -------------------------------------------------------------------------- */
.woocommerce-checkout #order_review,
.woocommerce-checkout .woocommerce-checkout-review-order {
	border: 0;
	background: none;
	padding: 0;
	box-shadow: none;
}

.woocommerce-checkout #order_review_heading {
	margin-bottom: var(--ecb-space-3);
}

/* One frame, on the card itself. */
.woocommerce-checkout .woocommerce-checkout-review-order-table,
.woocommerce-cart .cart_totals {
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-card);
	background-color: var(--ecb-surface-raised);
	padding: var(--ecb-space-3);
}

/* The payment block is a sibling panel, not a third nested box. */
.woocommerce-checkout #payment {
	background: none;
	border: 0;
	padding: 0;
}

.woocommerce-checkout #payment ul.payment_methods {
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-card);
	background-color: var(--ecb-surface-raised);
	padding: var(--ecb-space-3);
	margin: var(--ecb-space-3) 0 0;
}

/* ==========================================================================
   52. Final staging pass — confirmed defects
   ========================================================================== */

/* --------------------------------------------------------------------------
   52.1 Checkout delivery row overlapped from 590px down
   Blocksy renders this row as a single <td colspan="2"> holding
   .ct-shipping-heading ("Delivery charge — Inside Dhaka") above a method list.
   Section 44 turned that into a flex row so it matches its neighbours, but the
   heading was flex: 1 1 auto with no min-width, and a flex item will not
   shrink below its content. Below about 590px the label therefore overflowed
   its box and ran under the amount. The stack fallback existed, but at 380px —
   two hundred pixels after the collision starts.
   -------------------------------------------------------------------------- */
.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child)
	.ct-shipping-heading {
	/* The one declaration that lets the label wrap instead of overflowing. */
	min-width: 0;
	overflow-wrap: anywhere;
}

.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child)
	ul#shipping_method label {
	white-space: nowrap;
}

/* Stack from 600px, where the label genuinely stops fitting beside the amount,
   rather than from 380px. */
@media (max-width: 600px) {
	.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child) {
		display: block;
	}

	.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child)
		.ct-shipping-heading {
		margin-bottom: 2px;
	}

	.woocommerce-shipping-totals > td:has(ul#shipping_method > li:only-child)
		ul#shipping_method {
		text-align: left;
	}
}

/* Browsers without :has() never got the flex treatment, so they were already
   stacked. Nothing to undo — this only guards the label there too. */
.woocommerce-shipping-totals .ct-shipping-heading {
	overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   52.2 Everything stays inside the mobile summary card
   Section 51 handled the totals rows; this extends the same treatment to the
   product line: title, struck price, sale price and per-line saving.
   -------------------------------------------------------------------------- */
.woocommerce table.shop_table,
.ecb-summary,
.ecb-summary__item {
	table-layout: auto;
	max-width: 100%;
}

.ecb-summary__name,
.ecb-summary__variation,
.ecb-summary__attrs,
.woocommerce table.shop_table td.product-name {
	min-width: 0;
	overflow-wrap: anywhere;
}

.ecb-price,
.ecb-price__was,
.ecb-price__now,
.ecb-price__save,
.ecb-savings,
.woocommerce table.shop_table td.product-total,
.woocommerce table.shop_table .amount {
	overflow-wrap: normal;
	word-break: keep-all;
}

@media (max-width: 430px) {
	/* An amount must never be the thing that widens the page, so at the
	   narrowest widths the line wraps under the name rather than beside it. */
	.ecb-summary__item {
		flex-wrap: wrap;
	}

	.ecb-summary__meta {
		flex: 1 1 100%;
	}

	.woocommerce table.shop_table td.product-name {
		padding-right: 6px;
	}

	.woocommerce table.shop_table td.product-total {
		white-space: nowrap;
		padding-left: 6px;
	}
}

/* --------------------------------------------------------------------------
   52.3 Search glyph
   The header has no search element at all (its builder holds logo, account,
   menu-secondary, text and offcanvas), so the only search on the site is the
   shop/category form, whose SVG already carries width/height attributes.
   These rules constrain the glyph wherever a search icon can appear —
   including anything Blocksy or WooCommerce may add later — while leaving the
   44px pointer target from section 49 alone. Shrinking the target would trade
   one accessibility problem for another.
   -------------------------------------------------------------------------- */
.ecb-shopsearch__icon,
.ecb-shopsearch__icon svg {
	width: 17px;
	height: 17px;
	flex: 0 0 17px;
}

.ct-header [data-id="search"] svg,
.ct-header [data-id="search"] .ct-icon,
.ct-panel [data-id="search"] svg,
.ct-panel .ct-search-form svg,
.woocommerce-product-search button svg,
.widget_product_search button svg {
	width: 19px;
	height: 19px;
	max-width: 19px;
	max-height: 19px;
}

/* A search control rendered by anything else still gets a sane glyph. */
form[role="search"] svg,
form.search-form svg {
	width: 18px;
	height: 18px;
	flex: 0 0 auto;
}

/* --------------------------------------------------------------------------
   52.4 The chat button clears every control it used to cover
   Section 51 reserved space at page level. These are the specific controls
   reported: the payment block, the gallery and the cart actions.
   -------------------------------------------------------------------------- */
.woocommerce-checkout #payment .form-row.place-order,
.woocommerce-cart .wc-proceed-to-checkout,
.woocommerce-cart .actions {
	position: relative;
	z-index: 2;
}

@media (max-width: 782px) {
	/* Gallery arrows and thumbnails sit bottom-right on a phone, which is
	   exactly where the button lives. */
	.single-product .woocommerce-product-gallery {
		padding-bottom: 8px;
	}

	.woocommerce-checkout #payment,
	.woocommerce-cart .cart_totals {
		margin-bottom: calc(52px + var(--ecb-space-3));
	}
}

/* --------------------------------------------------------------------------
   52.5 Checkout consent row
   WooCommerce's native terms checkbox is now connected. It arrives unstyled,
   and a consent control that looks like an afterthought does not read as one
   the customer has actually given.
   -------------------------------------------------------------------------- */
.woocommerce-terms-and-conditions-wrapper {
	margin: var(--ecb-space-3) 0 0;
	font-size: var(--ecb-fs-sm);
	line-height: var(--ecb-lh-tight);
	color: var(--ecb-ink-muted);
}

.woocommerce-terms-and-conditions-wrapper .form-row {
	margin: 0;
	padding: 0;
}

.woocommerce-terms-and-conditions-wrapper label {
	display: flex;
	align-items: flex-start;
	gap: var(--ecb-space-2);
	cursor: pointer;
}

.woocommerce-terms-and-conditions-wrapper input[type="checkbox"] {
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	margin: 2px 0 0;
}

.woocommerce-terms-and-conditions-wrapper a {
	color: var(--ecb-plum);
	text-underline-offset: 2px;
}

/* --------------------------------------------------------------------------
   52.6 The bKash call-to-action note
   Sits under the submit button and must read as a reassurance, not a warning.
   -------------------------------------------------------------------------- */
.ecb-cta-note {
	margin: var(--ecb-space-3) 0 0;
	padding: var(--ecb-space-3);
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-ctl);
	background-color: var(--ecb-surface-sunken);
	font-size: var(--ecb-fs-sm);
	line-height: var(--ecb-lh-tight);
	color: var(--ecb-ink);
}

.ecb-cta-note[hidden] {
	display: none;
}

/* ==========================================================================
   53. Checkout interaction and header glyph — measured fixes
   ========================================================================== */

/* --------------------------------------------------------------------------
   53.1 The oversized search glyph was my own tap-target rule
   Section 49.3 applied `min-height/min-width: 44px` to `[data-id="search"] > *`
   to guarantee a comfortable target. The direct child of that button IS the
   <svg>, so the minimum was applied to the glyph and inflated it to 44×44.
   Section 51.4 then set `width: 19px` on the same svg — but a min-width of
   44px beats a width of 19px, so the glyph never shrank and the rule looked
   like it "did nothing".
   The minimum belongs on the button, which is the actual control.
   -------------------------------------------------------------------------- */
.ct-header [data-id="search"],
.ct-header .ct-header-search {
	min-width: var(--ecb-tap);
	min-height: var(--ecb-tap);
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

/* The glyph inside is decoration; it must not inherit the target minimum. */
.ct-header [data-id="search"] > svg,
.ct-header [data-id="search"] .ct-icon,
.ct-header .ct-header-search > svg,
.ct-header .ct-header-search .ct-icon {
	min-width: 0;
	min-height: 0;
	width: 19px;
	height: 19px;
	flex: 0 0 19px;
}

/* Same correction for the other header actions: the 44px belongs to the
   control, not to whatever icon happens to be its first child. */
.ct-header [data-id="cart"] > a > svg,
.ct-header [data-id="cart"] > a .ct-icon,
.ct-header [data-id="account"] > a > svg,
.ct-header [data-id="account"] > a .ct-icon {
	min-width: 0;
	min-height: 0;
}

/* --------------------------------------------------------------------------
   53.2 Terms consent needs a real tap target
   The rendered checkbox is 16×16 — Blocksy draws it with appearance:none at a
   fixed size. The label is 45px tall so tapping the wording already works, but
   the box itself was a 16px target, well under the 44px minimum.
   An invisible extension of the label is placed over the box: a tap there
   activates the label, and a label's default action toggles its own control.
   It is deliberately narrow enough not to cover the "terms and conditions"
   link that sits further along the same line.
   -------------------------------------------------------------------------- */
.woocommerce-terms-and-conditions-wrapper .form-row label.checkbox {
	position: relative;
	display: block;
	min-height: var(--ecb-tap);
	padding-top: 12px;
	padding-left: 30px;
}

.woocommerce-terms-and-conditions-wrapper .form-row label.checkbox input[type="checkbox"] {
	position: absolute;
	left: 0;
	top: 14px;
	margin: 0;
}

/* The 44×44 hit area, centred on the box and behind the text. */
.woocommerce-terms-and-conditions-wrapper .form-row label.checkbox::before {
	content: "";
	position: absolute;
	left: -6px;
	top: 50%;
	width: var(--ecb-tap);
	height: var(--ecb-tap);
	transform: translateY(-50%);
	/* Sits under the text so the terms link stays clickable. */
	z-index: 0;
}

.woocommerce-terms-and-conditions-wrapper .form-row label.checkbox > * {
	position: relative;
	z-index: 1;
}

/* Keyboard focus must be as obvious here as anywhere else. */
.woocommerce-terms-and-conditions-wrapper input[type="checkbox"]:focus-visible {
	outline: var(--ecb-focus-width) solid var(--ecb-focus-ring);
	outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   53.3 Payment-plan choice needs room to be tapped
   -------------------------------------------------------------------------- */
.ecb-bkplan__card {
	min-height: var(--ecb-tap);
}

.ecb-bkplan__card input[type="radio"] {
	min-width: 20px;
	min-height: 20px;
}

/* ==========================================================================
   54. bKash resume flow and the 390px defects in the screenshots
   ========================================================================== */

/* --------------------------------------------------------------------------
   54.1 Words stopped breaking letter by letter
   Sections 51-52 used `overflow-wrap: anywhere` on product names, table cells
   and headings to stop a long string widening the page. That keyword does two
   things: it permits a break at any character AND it collapses the element's
   min-content width. On a 390px screen the result was "Meherjaan" broken
   mid-word across lines.
   `break-word` solves the original problem — a word too long for its line is
   still broken — without licensing a break inside every ordinary word, and
   without collapsing min-content.
   -------------------------------------------------------------------------- */
.woocommerce-order-details,
.woocommerce-customer-details,
.woocommerce table.shop_table td,
.woocommerce table.shop_table th,
.woocommerce table.shop_table tfoot th,
.woocommerce table.shop_table td.product-name,
.ecb-summary__meta,
.ecb-summary__name,
.ecb-summary__variation,
.ecb-summary__attrs,
.ecb-card,
.woocommerce-shipping-totals .ct-shipping-heading {
	overflow-wrap: break-word;
	word-break: normal;
	hyphens: manual;
}

/* Order numbers, tracking ids and email addresses have no break opportunities
   of their own, so they keep the stronger rule. */
.woocommerce-order-overview__order,
.woocommerce-order-overview__email,
.ecb-lookup__result code,
.ecb-bkmerch__num,
.woocommerce-order-details .order-number,
.ecb-card__fact code {
	overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   54.2 Amounts stay whole and right-aligned
   -------------------------------------------------------------------------- */
.woocommerce table.shop_table td.product-total,
.woocommerce table.shop_table tfoot td,
.woocommerce-Price-amount,
.ecb-summary__qty,
.ecb-bkpay__val,
.ecb-price__was,
.ecb-price__now {
	overflow-wrap: normal;
	word-break: keep-all;
	white-space: nowrap;
}

.woocommerce table.shop_table tfoot td,
.woocommerce table.shop_table td.product-total {
	text-align: right;
}

/* --------------------------------------------------------------------------
   54.3 QR presentation
   The official image is used untouched — only its display size is set.
   -------------------------------------------------------------------------- */
.ecb-bkash__qr {
	margin: var(--ecb-space-3) 0;
	text-align: center;
}

.ecb-bkash__qr img {
	display: block;
	width: 100%;
	max-width: 310px;
	height: auto;
	margin-inline: auto;
	padding: var(--ecb-space-2);
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-card);
	/* A QR needs a white quiet zone to scan reliably; the token is #ffffff. */
	background-color: var(--ecb-surface-raised);
}

@media (max-width: 480px) {
	.ecb-bkash__qr img {
		max-width: 275px;
	}
}

/* --------------------------------------------------------------------------
   54.4 Payment state, stated in words before the instructions
   -------------------------------------------------------------------------- */
.ecb-bkash__pending {
	display: flex;
	align-items: flex-start;
	gap: var(--ecb-space-2);
	margin: 0 0 var(--ecb-space-3);
	padding: var(--ecb-space-2) var(--ecb-space-3);
	border: 1px solid var(--ecb-border);
	border-left: 3px solid var(--ecb-gold);
	border-radius: var(--ecb-radius-ctl);
	background-color: var(--ecb-surface-sunken);
	font-size: var(--ecb-fs-sm);
	line-height: var(--ecb-lh-tight);
	color: var(--ecb-ink);
}

/* Decorative only: the sentence beside it carries the meaning. */
.ecb-bkash__dot {
	flex: 0 0 auto;
	width: 9px;
	height: 9px;
	margin-top: 6px;
	border-radius: 50%;
	background-color: var(--ecb-gold);
}

.ecb-bkash__plan-note {
	margin: 0 0 var(--ecb-space-3);
	font-size: var(--ecb-fs-sm);
	color: var(--ecb-ink-muted);
}

/* --------------------------------------------------------------------------
   54.5 Cancel is a quiet secondary link, never a button beside the primary one
   -------------------------------------------------------------------------- */
.woocommerce-orders-table .ecb-order-cancel,
.woocommerce-order-details .ecb-order-cancel,
a.ecb-order-cancel {
	display: inline-block;
	margin-top: var(--ecb-space-2);
	padding: 0;
	border: 0;
	background: none;
	color: var(--ecb-ink-muted);
	font-size: var(--ecb-fs-xs);
	font-weight: var(--ecb-fw-body);
	text-decoration: underline;
	text-underline-offset: 2px;
	min-height: 0;
}

a.ecb-order-cancel:hover,
a.ecb-order-cancel:focus-visible {
	color: var(--ecb-sale);
}

/* --------------------------------------------------------------------------
   54.6 Narrow screens
   -------------------------------------------------------------------------- */
@media (max-width: 480px) {
	/* One choice per row: side by side, each card had about 160px for two
	   amounts and a heading. */
	.ecb-bkplan {
		grid-template-columns: 1fr;
	}

	.ecb-bkplan__card {
		width: 100%;
	}

	.ecb-bkplan__amounts {
		gap: .25rem 1.25rem;
	}

	/* Order summary and order details: give the label column room to breathe
	   and stop the amount column being squeezed to nothing. */
	.woocommerce table.shop_table th,
	.woocommerce table.shop_table td {
		font-size: var(--ecb-fs-sm);
		padding-block: 10px;
	}

	.woocommerce table.shop_table td.product-name {
		width: 62%;
	}

	.woocommerce table.shop_table td.product-total {
		width: 38%;
	}

	.ecb-bkash,
	.ecb-bkpay,
	.ecb-bkmerch__num {
		max-width: 100%;
	}
}

/* --------------------------------------------------------------------------
   54.7 The chat button must not sit over a transaction
   Reserving space was not enough on a short viewport: the button floats over
   the totals, the transaction-id field and the submit button. On the three
   pages where money is being handled it is hidden on small screens — the same
   contact routes are in the footer and on the Contact page.
   -------------------------------------------------------------------------- */
@media (max-width: 782px) {
	.woocommerce-checkout .ecb-fab,
	.woocommerce-cart .ecb-fab,
	.woocommerce-order-received .ecb-fab,
	.woocommerce-view-order .ecb-fab {
		display: none;
	}

	/* With it gone the reserved footprint is dead space. */
	.woocommerce-checkout .site-main,
	.woocommerce-cart .site-main {
		padding-bottom: var(--ecb-space-5);
	}
}

/* ==========================================================================
   55. Totals columns, QR enlarge, WhatsApp help, order status card
   ========================================================================== */

/* --------------------------------------------------------------------------
   55.1 The delivery row now has real columns
   Blocksy collapsed WooCommerce's <th>label</th><td>amount</td> into one
   <td colspan="2">, so sections 44 and 52 had to simulate columns with flex.
   A flex item will not shrink below its content, so once the label grew —
   "Delivery charge — Outside Dhaka" — it ran under the amount.
   ECB_Totals::restore_shipping_columns() puts the two cells back, so the row
   aligns by the table's own column widths like subtotal and total. The flex
   simulation is switched off wherever the real label cell is present.
   -------------------------------------------------------------------------- */
.woocommerce-shipping-totals:has(> th.ecb-ship-label) > td:has(ul#shipping_method) {
	display: table-cell;
}

.ecb-ship-label {
	text-align: left;
}

.ecb-ship-amount ul#shipping_method,
.ecb-ship-amount ul#shipping_method li {
	margin: 0;
	padding: 0;
	list-style: none;
}

.ecb-ship-amount ul#shipping_method label {
	margin: 0;
	font-weight: var(--ecb-fw-body);
}

/* One shape for every totals row: label column wraps between words, amount
   column never wraps and hugs the right edge. */
.woocommerce table.shop_table tfoot th,
.woocommerce table.shop_table tfoot td,
.woocommerce-checkout-review-order-table tfoot th,
.woocommerce-checkout-review-order-table tfoot td {
	vertical-align: top;
}

.woocommerce table.shop_table tfoot th,
.woocommerce-checkout-review-order-table tfoot th {
	width: 58%;
	text-align: left;
	overflow-wrap: break-word;
	word-break: normal;
	hyphens: manual;
	padding-right: var(--ecb-space-3);
}

.woocommerce table.shop_table tfoot td,
.woocommerce-checkout-review-order-table tfoot td {
	width: 42%;
	text-align: right;
	white-space: nowrap;
	word-break: keep-all;
}

/* The savings row is now two cells like its neighbours. */
.ecb-savings-row .ecb-savings__amount {
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

@media (max-width: 430px) {
	.woocommerce table.shop_table tfoot th,
	.woocommerce-checkout-review-order-table tfoot th {
		width: 54%;
		padding-right: var(--ecb-space-2);
	}

	.woocommerce table.shop_table tfoot td,
	.woocommerce-checkout-review-order-table tfoot td {
		width: 46%;
	}
}

/* --------------------------------------------------------------------------
   55.2 Click to enlarge the QR
   -------------------------------------------------------------------------- */
.ecb-qr-open {
	display: block;
	width: 100%;
	max-width: 310px;
	margin-inline: auto;
	padding: var(--ecb-space-2);
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-card);
	background-color: var(--ecb-surface-raised);
	cursor: zoom-in;
}

.ecb-qr-open img {
	display: block;
	width: 100%;
	height: auto;
}

.ecb-qr-open__hint {
	display: block;
	margin-top: var(--ecb-space-2);
	font-size: var(--ecb-fs-xs);
	font-weight: var(--ecb-fw-ui);
	color: var(--ecb-plum);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.ecb-qr-open:hover {
	border-color: var(--ecb-border-strong);
}

.ecb-qr-open:focus-visible {
	outline: var(--ecb-focus-width) solid var(--ecb-focus-ring);
	outline-offset: var(--ecb-focus-offset);
}

@media (max-width: 480px) {
	.ecb-qr-open {
		max-width: 275px;
	}
}

.ecb-qr-dialog {
	max-width: 90vw;
	max-height: 90vh;
	padding: 0;
	border: 0;
	border-radius: var(--ecb-radius-card);
	background-color: var(--ecb-surface-raised);
	color: var(--ecb-ink);
	overflow: visible;
}

.ecb-qr-dialog::backdrop {
	background-color: rgba(33, 30, 32, 0.72);
}

.ecb-qr-dialog__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--ecb-space-3);
	padding: var(--ecb-space-4);
}

/* Aspect ratio is preserved and the white quiet zone travels with it. */
.ecb-qr-dialog__img {
	display: block;
	max-width: min(78vw, 620px);
	max-height: 72vh;
	width: auto;
	height: auto;
	padding: var(--ecb-space-3);
	background-color: var(--ecb-surface-raised);
	border-radius: var(--ecb-radius-sm);
}

.ecb-qr-dialog__close {
	min-height: var(--ecb-tap);
	padding: 0 var(--ecb-space-5);
	border: 1px solid var(--ecb-plum);
	border-radius: var(--ecb-radius-ctl);
	background-color: var(--ecb-plum);
	color: var(--ecb-ink-inverse);
	font-family: var(--ecb-font-body);
	font-size: var(--ecb-fs-sm);
	font-weight: var(--ecb-fw-ui);
	cursor: pointer;
}

.ecb-qr-dialog__close:hover {
	background-color: var(--ecb-ink);
	border-color: var(--ecb-ink);
}

/* Belt and braces for engines that do not lock the page behind a modal. */
html.ecb-qr-locked,
html.ecb-qr-locked body {
	overflow: hidden;
}

/* --------------------------------------------------------------------------
   55.3 The alternative routes, offered quietly
   -------------------------------------------------------------------------- */
.ecb-alt-note {
	margin: var(--ecb-space-2) 0 0;
	font-size: var(--ecb-fs-xs);
	line-height: var(--ecb-lh-tight);
	color: var(--ecb-ink-muted);
}

.ecb-alt-note a,
.ecb-status__wa {
	color: var(--ecb-plum);
	text-decoration: underline;
	text-underline-offset: 2px;
}

/* --------------------------------------------------------------------------
   55.4 Order status card
   -------------------------------------------------------------------------- */
.ecb-status {
	margin: 0 0 var(--ecb-space-4);
	padding: var(--ecb-space-4);
	border: 1px solid var(--ecb-border);
	border-radius: var(--ecb-radius-card);
	background-color: var(--ecb-surface-raised);
}

.ecb-status__head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--ecb-space-2) var(--ecb-space-3);
	margin-bottom: var(--ecb-space-3);
}

.ecb-status__num {
	display: block;
	font-weight: var(--ecb-fw-emphasis);
	color: var(--ecb-ink);
}

.ecb-status__date {
	display: block;
	font-size: var(--ecb-fs-xs);
	color: var(--ecb-ink-muted);
}

.ecb-status__badge {
	flex: 0 0 auto;
	padding: 5px 12px;
	border-radius: 999px;
	border: 1px solid var(--ecb-border-strong);
	font-size: var(--ecb-fs-xs);
	font-weight: var(--ecb-fw-emphasis);
	letter-spacing: var(--ecb-ls-ui);
	white-space: nowrap;
}

/* Tone never carries the meaning on its own — the badge always says the state
   in words, and the steps below repeat it. */
.ecb-status__badge--wait { background-color: var(--ecb-surface-sunken); color: var(--ecb-plum); }
.ecb-status__badge--go   { background-color: var(--ecb-plum); color: var(--ecb-ink-inverse); border-color: var(--ecb-plum); }
.ecb-status__badge--done { background-color: var(--ecb-plum); color: var(--ecb-ink-inverse); border-color: var(--ecb-plum); }
.ecb-status__badge--stop { background-color: var(--ecb-surface-sunken); color: var(--ecb-ink-muted); }

.ecb-status__next {
	margin: 0 0 var(--ecb-space-3);
	font-size: var(--ecb-fs-sm);
	line-height: var(--ecb-lh-tight);
	color: var(--ecb-ink);
}

.ecb-status__steps {
	display: flex;
	flex-wrap: wrap;
	gap: var(--ecb-space-2) var(--ecb-space-4);
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: none;
}

.ecb-status__step {
	display: flex;
	align-items: center;
	gap: var(--ecb-space-2);
	font-size: var(--ecb-fs-xs);
	color: var(--ecb-ink-muted);
}

.ecb-status__marker {
	flex: 0 0 auto;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	border: 1px solid var(--ecb-border-strong);
	background-color: transparent;
}

.ecb-status__step.is-done .ecb-status__marker {
	background-color: var(--ecb-plum);
	border-color: var(--ecb-plum);
}

.ecb-status__step.is-current .ecb-status__marker {
	background-color: var(--ecb-gold);
	border-color: var(--ecb-gold);
}

.ecb-status__step.is-done .ecb-status__label,
.ecb-status__step.is-current .ecb-status__label {
	color: var(--ecb-ink);
	font-weight: var(--ecb-fw-ui);
}

.ecb-status__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--ecb-space-2) var(--ecb-space-4);
	margin: var(--ecb-space-4) 0 0;
	padding-top: var(--ecb-space-3);
	border-top: 1px solid var(--ecb-border);
}

.ecb-status__resume {
	display: inline-flex;
	align-items: center;
	min-height: var(--ecb-tap);
	padding: 0 var(--ecb-space-4);
	border-radius: var(--ecb-radius-ctl);
	background-color: var(--ecb-plum);
	color: var(--ecb-ink-inverse);
	font-size: var(--ecb-fs-sm);
	font-weight: var(--ecb-fw-ui);
	text-decoration: none;
}

.ecb-status__resume:hover {
	background-color: var(--ecb-ink);
	color: var(--ecb-ink-inverse);
}

.ecb-status__wa {
	font-size: var(--ecb-fs-xs);
}

@media (max-width: 430px) {
	.ecb-status__head {
		flex-direction: column;
		align-items: flex-start;
	}

	.ecb-status__steps {
		flex-direction: column;
		gap: var(--ecb-space-2);
	}

	.ecb-status__actions {
		flex-direction: column;
		align-items: stretch;
	}

	.ecb-status__resume {
		justify-content: center;
	}
}

/* ==========================================================================
   56. Phase 1 — Approved visual direction
   Implements the signed-off prototype inside the existing Blocksy child theme.
   Nothing here is a rebuild: the tokens, components and hooks below sit on top
   of sections 1–55 and override only what the prototype actually changes.

   The prototype's palette turned out to be within a hair of ours, which is why
   this section adds almost no new colour. What it does change is *density* —
   the interface type drops to 10–13px, the two header rows are pinned to a
   fixed 60px + 40px, and section rhythm tightens to 64/80px. Premium here is
   carried by restraint, not by size.
   ========================================================================== */

:root {
	/* ---- Prototype-matched surfaces ------------------------------------
	   Our existing plum/gold/ivory already matched; these are the few tones
	   the prototype uses that we had no token for. */
	--ecb-p1-announce: #250914;     /* deeper than the header plum on purpose */
	--ecb-p1-header: rgba(251, 248, 245, 0.95);
	--ecb-p1-header-solid: #FBF8F5;
	--ecb-p1-rule: #E2D5CE;         /* header underline */
	--ecb-p1-rule-soft: #EADFD9;    /* between the two header rows */
	--ecb-p1-panel: #FFFDFA;        /* dropdown / raised card ground */
	--ecb-p1-panel-border: #DFD2CB;
	--ecb-p1-panel-rule: #EEE4DE;   /* hairline between dropdown links */
	--ecb-p1-nav: #4F3A43;          /* row-1 shortcut labels */
	--ecb-p1-nav-strong: #34252B;   /* row-2 category labels */
	--ecb-p1-nav-hover: #7A2949;
	--ecb-p1-eyebrow: #9A7B65;      /* dropdown column headings */
	--ecb-p1-link: #4E3842;         /* dropdown links */
	--ecb-p1-hover-wash: #F1E8E3;   /* icon-button hover ground */
	--ecb-p1-foot: #2F0E1C;
	--ecb-p1-foot-ink: #FFF9F4;
	--ecb-p1-foot-muted: #D8C5CC;
	--ecb-p1-foot-link: #EADFE3;
	--ecb-p1-foot-head: #C8A873;
	--ecb-p1-badge: #5A1231;

	/* ---- Fixed header geometry ------------------------------------------
	   Both rows are pinned rather than content-sized. A header that changes
	   height when a menu label wraps makes the sticky offset a moving target
	   and shifts every anchor on the page. */
	--ecb-p1-row1: 60px;
	--ecb-p1-row2: 40px;
	--ecb-p1-announce-h: 26px;

	/* ---- Compact interface type -----------------------------------------
	   The prototype's interface voice is small, bold and tracked out. At these
	   sizes weight does the work that size would otherwise do, which is what
	   keeps the header quiet without making it faint. */
	--ecb-p1-nav1-size: 10px;
	--ecb-p1-nav1-size-lg: 11px;
	--ecb-p1-nav2-size: 11px;
	--ecb-p1-nav2-size-lg: 12px;
	--ecb-p1-nav-ls: 0.1em;
	--ecb-p1-nav2-ls: 0.08em;
	--ecb-p1-eyebrow-size: 10px;
	--ecb-p1-eyebrow-ls: 0.16em;
	--ecb-p1-drop-link: 13px;

	/* ---- Section rhythm --------------------------------------------------
	   64px on a phone, 80px from the large breakpoint. The old ladder ran to
	   96/128px, which is where the page started to read as a template. */
	--ecb-p1-band: 64px;
	--ecb-p1-band-lg: 80px;

	/* Focus ring, matched to the prototype: a wide soft plum halo that stays
	   legible on both the cream ground and the dark hero. */
	--ecb-p1-focus: rgba(122, 41, 73, 0.42);
}

/* --------------------------------------------------------------------------
   56.1 Compact type scale
   The display voice gets *larger* than before and the interface voice gets
   smaller. That widening gap is the whole trick: it reads as editorial rather
   than as a uniformly-scaled-up template.
   -------------------------------------------------------------------------- */
:root {
	--ecb-fs-h2: clamp(1.75rem, 1.55rem + 0.9vw, 2.25rem);   /* 28 -> 36 */
	--ecb-fs-h3: clamp(1.125rem, 1.06rem + 0.28vw, 1.3125rem);
}

/* Display headings carry the prototype's tight tracking. Cormorant is already
   our display face and needs the negative tracking more than a sans would. */
.ecb-section-head h2,
.ecb-section h2,
.ecb-foot-brand {
	letter-spacing: -0.02em;
}

/* Eyebrows: one shape everywhere. */
.ecb-eyebrow {
	font-family: var(--ecb-font-body);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--ecb-gold);
	margin-bottom: 6px;
}

/* --------------------------------------------------------------------------
   56.2 Section rhythm
   One ladder, applied to the homepage bands and the generic section wrapper.
   -------------------------------------------------------------------------- */
.ecb-section,
.ecb-band {
	padding-top: var(--ecb-p1-band);
	padding-bottom: var(--ecb-p1-band);
}

@media (min-width: 1000px) {
	.ecb-section,
	.ecb-band {
		padding-top: var(--ecb-p1-band-lg);
		padding-bottom: var(--ecb-p1-band-lg);
	}
}

.ecb-section-head {
	margin-bottom: 28px;
}

@media (min-width: 1000px) {
	.ecb-section-head { margin-bottom: 34px; }
}

/* --------------------------------------------------------------------------
   56.3 Announcement bar
   The prototype runs a marquee on narrow screens. We keep our existing
   rotator instead — it already fades one whole message at a time, pauses when
   the tab is hidden and collapses to a single line under reduced motion, and
   a rotator is easier to read than text sliding under your thumb. Only the
   dress changes here, not the mechanism.
   -------------------------------------------------------------------------- */
.ct-header [data-row="top"] .ct-header-text,
.ct-header [data-row="top"] .ecb-rotator {
	font-family: var(--ecb-font-body);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.12em;
	line-height: 1.4;
	text-transform: uppercase;
	color: #FFF8F3;
}

@media (min-width: 690px) {
	.ct-header [data-row="top"] .ct-header-text,
	.ct-header [data-row="top"] .ecb-rotator { font-size: 11px; }
}

/* The customizer still carries 13px / #FBF8F3 for this element, compiled to
   [data-id="text"] as --theme-font-size and --theme-text-color. The child
   stylesheet loads after global.css so the rules above already win, but the
   theme's own variables are fed too — otherwise the two disagree, and the
   next person to read the customizer would be told the wrong size. */
html [data-header*="type-1"] .ct-header [data-id="text"] {
	--theme-font-size: 10px;
	--theme-line-height: 1.4;
	--theme-text-color: #FFF8F3;
}

@media (min-width: 690px) {
	html [data-header*="type-1"] .ct-header [data-id="text"] { --theme-font-size: 11px; }
}

/* --------------------------------------------------------------------------
   56.4 Header shell — sticky, two fixed rows
   -------------------------------------------------------------------------- */
/* Row rules.
   Blocksy paints these from its own variables behind `#header [data-row]` —
   an ID selector, specificity (1,0,1). Writing `border-bottom` here would lose
   to it outright. Feeding `--theme-border-*` instead means the rule lands
   through the theme's own mechanism, which is both lighter and the reason no
   !important is needed anywhere in this block.

   Row height needs nothing further: `#header [data-row] > div` already reads
   `min-height: var(--shrink-height, var(--height))`, and --height is set from
   our token just below, so the value is inherited rather than fought over. */
html [data-header*="type-1"] .ct-header [data-row*="middle"] {
	--theme-border-bottom: 1px solid var(--ecb-p1-rule);
}

html [data-header*="type-1"] .ct-header [data-row*="bottom"] {
	--theme-border-top: 1px solid var(--ecb-p1-rule-soft);
}

/* Row 2 sits centred, as in the prototype. */
.ct-header [data-id="menu-secondary"] > ul {
	justify-content: center;
	gap: 0;
}

/* Row heights.
   Blocksy compiles its own header sizing into uploads/blocksy/css/global.css
   as `[data-header*="type-1"] .ct-header [data-row*="middle"] { --height: … }`
   — specificity (0,3,0), restated again inside two breakpoints. A plain
   `.ct-header [data-row="middle"]` rule here is (0,2,0) and loses to it no
   matter how late it appears, because the cascade only considers source order
   at equal specificity.

   So the row geometry is set by overriding Blocksy's own variable, at a
   specificity that also clears its breakpoint rules. Leading `html` costs one
   element selector and buys (0,3,1), which beats every compiled variant
   without reaching for !important. */
html [data-header*="type-1"] .ct-header [data-row*="top"]    { --height: var(--ecb-p1-announce-h); }
html [data-header*="type-1"] .ct-header [data-row*="middle"] { --height: var(--ecb-p1-row1); }
html [data-header*="type-1"] .ct-header [data-row*="bottom"] { --height: var(--ecb-p1-row2); }

/* Backgrounds are compiled by Blocksy at the same specificity, so they are
   restated here in the same shape. */
html [data-header*="type-1"] .ct-header [data-row*="top"] {
	background-color: var(--ecb-p1-announce);
}

html [data-header*="type-1"] .ct-header [data-row*="middle"],
html [data-header*="type-1"] .ct-header [data-row*="bottom"] {
	background-color: transparent;
}

/* Sticky.
   Blocksy's own sticky feature is switched off (its sticky.js only loads for a
   [data-sticky] container), so this is the only implementation and there is no
   second one to fight with.

   The obvious move — sticking rows 1 and 2 individually — does not work. A
   sticky box is bounded by its containing block, and both rows sit inside a
   ~130px `[data-device]` wrapper, so they would come unstuck almost as soon as
   they stuck. The whole header is stuck instead: its containing block is
   #main-container, which spans the document.

   The prototype lets the announcement scroll away while the two navigation
   rows stay. Offsetting the sticky top by exactly the announcement's height
   reproduces that with one sticky element: the bar rides up out of view and
   the rows below it come to rest against the viewport top. The offset is
   trustworthy because the same token sets the row height directly above. */
/* `#header` — an ID, specificity (1,0,0) — already carries
   `position: relative; z-index: 50` in Blocksy's main.min.css. A `.ct-header`
   rule here is (0,1,0) and loses outright, so the header rendered static and
   the sticky behaviour never happened at all. Matching the ID and adding the
   class takes it to (1,1,0), which wins without !important.

   z-index stays at Blocksy's 50 rather than dropping to 40: the theme chose 50
   so the header clears the content it overlaps, and lowering it would put the
   stuck bar behind things it is supposed to cover. */
#header.ct-header {
	position: sticky;
	top: calc(-1 * var(--ecb-p1-announce-h));
	z-index: 50;
	background-color: var(--ecb-p1-header);
	backdrop-filter: blur(20px);
	-webkit-backdrop-filter: blur(20px);
}

/* Backdrop blur is a progressive nicety. Where it is unsupported the header
   falls back to a solid ground rather than to translucency over content
   scrolling underneath it. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	#header.ct-header {
		background-color: var(--ecb-p1-header-solid);
	}
}

/* The drawer must sit above the stuck header, not behind it. */
.ct-drawer-canvas,
#offcanvas {
	z-index: 100;
}
/* --------------------------------------------------------------------------
   56.5 Navigation type — two levels, deliberately unequal

   Blocksy compiles menu typography into custom properties behind
   `[data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a`, which is
   specificity (0,3,3) — higher than any sensible `.ct-menu-link` rule here.
   Rather than out-shout it, this feeds the same variables it reads, from a
   selector one element heavier. The theme then applies our values through its
   own machinery, so hover, current-item and mobile states keep working instead
   of needing to be re-implemented.
   -------------------------------------------------------------------------- */
html [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a {
	--theme-font-family: var(--ecb-font-body);
	--theme-font-size: var(--ecb-p1-nav1-size);
	--theme-font-weight: 700;
	--theme-text-transform: uppercase;
	--theme-letter-spacing: var(--ecb-p1-nav-ls);
	--theme-link-initial-color: var(--ecb-p1-nav);
	--theme-link-hover-color: var(--ecb-p1-nav-hover);
	padding-left: 10px;
	padding-right: 10px;
}

html [data-header*="type-1"] .ct-header [data-id="menu-secondary"] > ul > li > a {
	--theme-font-family: var(--ecb-font-body);
	--theme-font-size: var(--ecb-p1-nav2-size);
	--theme-font-weight: 700;
	--theme-text-transform: uppercase;
	--theme-letter-spacing: var(--ecb-p1-nav2-ls);
	--theme-link-initial-color: var(--ecb-p1-nav-strong);
	--theme-link-hover-color: var(--ecb-p1-nav-hover);
	padding-left: 16px;
	padding-right: 16px;
}

@media (min-width: 1280px) {
	html [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a {
		--theme-font-size: var(--ecb-p1-nav1-size-lg);
	}
	html [data-header*="type-1"] .ct-header [data-id="menu-secondary"] > ul > li > a {
		--theme-font-size: var(--ecb-p1-nav2-size-lg);
	}
}

/* The section you are actually in stays marked in plum. */
html [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li.current-menu-item > a,
html [data-header*="type-1"] .ct-header [data-id="menu-secondary"] > ul > li.current-menu-item > a,
html [data-header*="type-1"] .ct-header [data-id="menu-secondary"] > ul > li.current-menu-ancestor > a {
	--theme-link-initial-color: var(--ecb-p1-nav-hover);
}

/* Dropdown rows are driven the same way. */
html [data-header*="type-1"] .ct-header [data-id="menu"] .sub-menu .ct-menu-link,
html [data-header*="type-1"] .ct-header [data-id="menu-secondary"] .sub-menu .ct-menu-link {
	--theme-font-family: var(--ecb-font-body);
	--theme-font-size: var(--ecb-p1-drop-link);
	--theme-font-weight: 600;
	--theme-text-transform: none;
	--theme-letter-spacing: 0;
	--theme-link-initial-color: var(--ecb-p1-link);
	--theme-link-hover-color: var(--ecb-p1-nav-hover);
}

/* Blocksy's default dropdown is a dark panel with a dashed divider and a soft
   grey shadow. The prototype's is a light card with hairline rules, so both of
   those defaults are cleared here at the specificity that set them. */
html [data-header*="type-1"] .ct-header [data-id="menu"] .sub-menu,
html [data-header*="type-1"] .ct-header [data-id="menu-secondary"] .sub-menu {
	--dropdown-divider: none;
	--theme-box-shadow: 0 24px 68px rgba(47, 14, 28, 0.16);
	--theme-border-radius: 0;
	--dropdown-background-color: var(--ecb-p1-panel);
}

/* Font size has to be a real declaration, not a variable.

   Feeding `--theme-font-size` works for colour and borders because Blocksy
   consumes those variables on the link itself. It does not work for size: the
   only `font-size: var(--theme-font-size)` rule in the theme matches an
   ancestor, so the link simply inherits — it was rendering at the 16px body
   size while the variable sat on it unread, which is why the header still
   looked full-size after the rest of the section had landed.

   The variables above are left in place: they are what the current-item colour
   and hover states read. */
html [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a {
	font-size: var(--ecb-p1-nav1-size);
	font-weight: 700;
	letter-spacing: var(--ecb-p1-nav-ls);
	text-transform: uppercase;
	font-family: var(--ecb-font-body);
}

html [data-header*="type-1"] .ct-header [data-id="menu-secondary"] > ul > li > a {
	font-size: var(--ecb-p1-nav2-size);
	font-weight: 700;
	letter-spacing: var(--ecb-p1-nav2-ls);
	text-transform: uppercase;
	font-family: var(--ecb-font-body);
}

@media (min-width: 1280px) {
	html [data-header*="type-1"] .ct-header [data-id="menu"] > ul > li > a {
		font-size: var(--ecb-p1-nav1-size-lg);
	}
	html [data-header*="type-1"] .ct-header [data-id="menu-secondary"] > ul > li > a {
		font-size: var(--ecb-p1-nav2-size-lg);
	}
}

/* Dropdown rows, same reasoning. */
html [data-header*="type-1"] .ct-header [data-id="menu"] .sub-menu .ct-menu-link,
html [data-header*="type-1"] .ct-header [data-id="menu-secondary"] .sub-menu .ct-menu-link {
	font-size: var(--ecb-p1-drop-link);
	font-weight: 600;
	letter-spacing: 0;
	text-transform: none;
}
/* The gold underline from section 34 now tracks the tighter padding. */
.header-menu-1 > li > .ct-menu-link::after { left: 10px; right: 10px; bottom: 8px; }
.header-menu-2 > li > .ct-menu-link::after { left: 16px; right: 16px; bottom: 8px; }
/* "Visit Us" carries a map pin, as in the prototype. The glyph is drawn from
   an inline SVG data URI rather than an icon font: one request fewer, and it
   cannot arrive late and shift the row. */
.ct-header .ecb-nav-visit > .ct-menu-link {
	display: inline-flex;
	align-items: center;
	gap: 6px;
}

.ct-header .ecb-nav-visit > .ct-menu-link::before {
	content: "";
	width: 14px;
	height: 14px;
	flex: 0 0 14px;
	background-color: currentColor;
	-webkit-mask: var(--ecb-icon-pin) center / contain no-repeat;
	mask: var(--ecb-icon-pin) center / contain no-repeat;
}

:root {
	--ecb-icon-pin: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0'/%3E%3Ccircle cx='12' cy='10' r='3'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   56.6 Desktop dropdown / mega-menu
   Blocksy already renders the real <ul class="sub-menu"> and already handles
   hover and keyboard focus. This restyles that panel into the prototype's
   card; it does not add a second dropdown mechanism, so keyboard access and
   the aria-expanded toggle keep working exactly as the theme intends.
   -------------------------------------------------------------------------- */
.ct-header [data-id="menu-secondary"] .sub-menu,
.ct-header [data-id="menu"] .sub-menu {
	background-color: var(--ecb-p1-panel);
	border: 1px solid var(--ecb-p1-panel-border);
	border-radius: 0;
	box-shadow: 0 24px 68px rgba(47, 14, 28, 0.16);
	padding: 20px 22px;
	min-width: 240px;
}

.ct-header .sub-menu > li > .ct-menu-link {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	min-height: 36px;
	padding: 4px 0;
	border-bottom: 1px solid var(--ecb-p1-panel-rule);
	font-family: var(--ecb-font-body);
	font-size: var(--ecb-p1-drop-link);
	font-weight: 600;
	letter-spacing: 0;
	text-transform: none;
	color: var(--ecb-p1-link);
	--theme-link-initial-color: var(--ecb-p1-link);
}

.ct-header .sub-menu > li:last-child > .ct-menu-link {
	border-bottom: 0;
}

.ct-header .sub-menu > li > .ct-menu-link:hover,
.ct-header .sub-menu > li.current-menu-item > .ct-menu-link {
	color: var(--ecb-p1-nav-hover);
	--theme-link-initial-color: var(--ecb-p1-nav-hover);
}

/* The prototype marks each row with a small outbound arrow. It is decorative,
   so it is generated content and carries no text for a screen reader. */
.ct-header .sub-menu > li > .ct-menu-link::after {
	content: "\2197";
	font-size: 11px;
	line-height: 1;
	opacity: 0.45;
	transition: opacity var(--ecb-t-color) var(--ecb-ease),
	            transform var(--ecb-t-color) var(--ecb-ease);
}

.ct-header .sub-menu > li > .ct-menu-link:hover::after {
	opacity: 1;
	transform: translate(2px, -2px);
}

/* The prototype labels each panel column ("Shop sarees", "By occasion"). Those
   labels exist there because its panels group several unrelated lists. Ours
   hold one list whose name is the nav item directly above the panel, so a
   heading would only repeat a word already on screen a few pixels higher. The
   panel is left unlabelled on purpose — and no label is invented to fill it.

   Panels longer than four items split into two columns, which is the same
   520px layout the prototype uses for its larger menus. :has() reads the real
   child count, so this follows the menu rather than a hardcoded list of which
   items are "big". Engines without :has() keep the single column, which is a
   quieter failure than a broken grid. */
@supports selector(:has(*)) {
	@media (min-width: 1000px) {
		.ct-header .sub-menu:has(> li:nth-child(5)) {
			display: grid;
			grid-template-columns: 1fr 1fr;
			column-gap: 28px;
			min-width: 460px;
		}
	}
}

/* The chevron turns over when the panel is open.

   Blocksy does not open its dropdowns with CSS :hover — its script toggles a
   `.ct-active` class on the parent item and maintains aria-expanded alongside
   it. Keying this on :hover would look right with a mouse and then desynchronise
   the moment the panel is opened from the keyboard, which is exactly when the
   arrow direction matters most. So the open state is read from `.ct-active`,
   the same signal the panel itself uses. */
.ct-header .ct-toggle-dropdown-desktop svg {
	transition: transform var(--ecb-t-button) var(--ecb-ease);
}

.ct-header li.ct-active > .ct-menu-link .ct-toggle-dropdown-desktop svg,
.ct-header li.ct-active > .ct-menu-link > .ct-toggle-dropdown-desktop svg {
	transform: rotate(180deg);
}

/* Blocksy sizes the panel with `width: var(--dropdown-width, 200px)`, so the
   width is set through that variable rather than fought with min-width. */
html [data-header*="type-1"] .ct-header [data-id="menu"] .sub-menu,
html [data-header*="type-1"] .ct-header [data-id="menu-secondary"] .sub-menu {
	--dropdown-width: 260px;
}

/* --------------------------------------------------------------------------
   56.7 Header actions — search, account, cart
   Circular, quiet at rest, washed on hover. Sized 40px where a mouse is the
   likely pointer and 44px wherever the pointer is coarse, so the touch target
   never drops below the accessible minimum on a phone.
   -------------------------------------------------------------------------- */
.ct-header [data-id="search"] > *,
.ct-header [data-id="account"] > a,
.ct-header [data-id="cart"] > a,
.ct-header [data-id="trigger"] {
	width: 40px;
	height: 40px;
	min-width: 40px;
	min-height: 40px;
	border-radius: 999px;
	transition: background-color var(--ecb-t-color) var(--ecb-ease);
}

.ct-header [data-id="search"] > *:hover,
.ct-header [data-id="account"] > a:hover,
.ct-header [data-id="cart"] > a:hover,
.ct-header [data-id="trigger"]:hover {
	background-color: var(--ecb-p1-hover-wash);
}

@media (pointer: coarse) {
	.ct-header [data-id="search"] > *,
	.ct-header [data-id="account"] > a,
	.ct-header [data-id="cart"] > a,
	.ct-header [data-id="trigger"] {
		width: var(--ecb-tap);
		height: var(--ecb-tap);
		min-width: var(--ecb-tap);
		min-height: var(--ecb-tap);
	}
}

/* Icons sit at 19px inside the 40px circle, as in the prototype. Constrain the
   glyph itself, never the button: a min-* on the SVG wins over its width and
   was the cause of the oversized search glyph fixed in section 51. */
.ct-header [data-id="search"] svg,
.ct-header [data-id="account"] svg,
.ct-header [data-id="cart"] svg,
.ct-header [data-id="trigger"] svg {
	width: 19px;
	height: 19px;
}

/* Cart count: a small filled disc, not a pill that resizes with the number. */
.ct-header [data-id="cart"] .ct-cart-badge {
	background-color: var(--ecb-p1-badge);
	color: #fff;
	font-family: var(--ecb-font-body);
	font-size: 10px;
	font-weight: 700;
	min-width: 18px;
	height: 18px;
	border-radius: 999px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

/* One focus ring for the whole header, matching the prototype's soft halo. */
.ct-header a:focus-visible,
.ct-header button:focus-visible,
.ct-header [tabindex]:focus-visible {
	outline: 3px solid var(--ecb-p1-focus);
	outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   56.8 Mobile navigation
   Blocksy's offcanvas panel, dressed to match. The trigger, the panel and the
   rows are the theme's own, so the focus trap, the Escape key and the
   aria-expanded state all keep working; only the surface changes.
   -------------------------------------------------------------------------- */
#offcanvas .ct-panel-inner,
#offcanvas .ct-panel-content {
	background-color: var(--ecb-p1-panel);
}

#offcanvas .ct-menu-link {
	font-family: var(--ecb-font-body);
	font-size: 14px;
	font-weight: 600;
	letter-spacing: 0.01em;
	text-transform: none;
	color: var(--ecb-p1-link);
	min-height: var(--ecb-tap);
	display: flex;
	align-items: center;
	border-radius: 10px;
	padding-left: 12px;
	padding-right: 12px;
	transition: background-color var(--ecb-t-color) var(--ecb-ease),
	            color var(--ecb-t-color) var(--ecb-ease);
}

#offcanvas .ct-menu-link:hover,
#offcanvas .current-menu-item > .ct-menu-link {
	background-color: #F3EAE4;
	color: var(--ecb-p1-nav-hover);
}

/* Second-level rows are indented and quieter, so the hierarchy survives
   without the panel needing separators between every row. */
#offcanvas .sub-menu .ct-menu-link {
	font-size: 13px;
	font-weight: 500;
	padding-left: 24px;
	color: var(--ecb-ink-muted);
}

/* The expand control must be its own target, not a sliver beside the label. */
#offcanvas .ct-toggle-dropdown-mobile {
	min-width: var(--ecb-tap);
	min-height: var(--ecb-tap);
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

#offcanvas a:focus-visible,
#offcanvas button:focus-visible {
	outline: 3px solid var(--ecb-p1-focus);
	outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   56.9 Footer
   Deeper plum than the header, gold column headings, four columns weighted so
   the brand block gets the room the prototype gives it.

   Blocksy compiles the footer the same way it compiles the header — variables
   behind `[data-footer*="type-1"] .ct-footer [data-row*="middle"]`, (0,3,0).
   The same `html`-prefixed shape is used here, which is why this whole block
   needs no !important.
   -------------------------------------------------------------------------- */
html [data-footer*="type-1"] .ct-footer [data-row*="middle"] {
	background-color: var(--ecb-p1-foot);
}

/* 56px of band, against the theme default of 70px: the compact rhythm applies
   to the footer too, or it becomes the one oversized thing on the page. */
html [data-footer*="type-1"] .ct-footer [data-row*="middle"] > div {
	--container-spacing: 56px;
	--grid-template-columns: 1.35fr 0.8fr 0.9fr 1.1fr;
}

html [data-footer*="type-1"] .ct-footer [data-row*="bottom"] {
	background-color: var(--ecb-p1-foot);
}

/* Four weighted columns only hold while there is room for four. */
@media (max-width: 999.98px) {
	html [data-footer*="type-1"] .ct-footer [data-row*="middle"] > div {
		--grid-template-columns: 1fr 1fr;
		--container-spacing: 44px;
	}
}

@media (max-width: 689.98px) {
	html [data-footer*="type-1"] .ct-footer [data-row*="middle"] > div {
		--grid-template-columns: 1fr;
		--container-spacing: 36px;
	}
}

.ct-footer [data-row="middle"],
.ct-footer [data-row="middle"] p,
.ct-footer [data-row="middle"] li {
	color: var(--ecb-p1-foot-link);
}

html [data-footer*="type-1"] .ct-footer .widget-title,
.ct-footer .ecb-foot-menu-title {
	--theme-font-size: 12px;
	font-family: var(--ecb-font-body);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: var(--ecb-p1-eyebrow-ls);
	text-transform: uppercase;
	color: var(--ecb-p1-foot-head);
	margin-bottom: 16px;
}

.ct-footer .ecb-foot-brand {
	font-family: var(--ecb-font-heading);
	font-size: 1.75rem;
	font-weight: 400;
	line-height: 1.15;
	color: var(--ecb-p1-foot-ink);
}

.ct-footer .ecb-foot-desc,
.ct-footer .ecb-foot-tag {
	font-size: 14px;
	line-height: 1.75;
	color: var(--ecb-p1-foot-muted);
	max-width: 30rem;
}

.ct-footer [data-row="middle"] a {
	font-size: 14px;
	color: var(--ecb-p1-foot-link);
	transition: color var(--ecb-t-color) var(--ecb-ease);
}

.ct-footer [data-row="middle"] a:hover {
	color: var(--ecb-p1-foot-ink);
}

.ct-footer a:focus-visible {
	outline: 3px solid rgba(255, 249, 244, 0.5);
	outline-offset: 3px;
}

/* Footer link rows need a real target height on a phone. */
@media (pointer: coarse) {
	.ct-footer [data-row="middle"] .ct-menu-link {
		min-height: var(--ecb-tap);
		display: flex;
		align-items: center;
	}
}
/* --------------------------------------------------------------------------
   56.10 Hero
   The prototype's hero is a dark editorial plate: a full-bleed photograph, a
   left-weighted gradient so the copy sits on its darkest part, and a very slow
   scale that you notice only if you look for it.
   -------------------------------------------------------------------------- */
.ecb-hero-carousel {
	background-color: #251018;
}

.ecb-hero-slide {
	min-height: 600px;
}

@media (max-width: 999.98px) {
	.ecb-hero-slide { min-height: 520px; }
}

@media (max-width: 480px) {
	.ecb-hero-slide { min-height: 460px; }
}

/* Photography is warmed very slightly and pulled off full saturation, which is
   what stops a mixed set of supplier images from reading as a stock grid. */
.ecb-hero-slide__img,
.ecb-cat-card__img,
.ecb-pick__img {
	filter: saturate(0.94) contrast(1.01);
}

/* The slow drift. 7s against a 0.9s cross-fade means the movement is never the
   thing you are watching — it just keeps the plate from feeling like a static
   JPEG. It is a transform on a composited layer, so it costs no layout. */
.ecb-hero-carousel.is-enhanced .ecb-hero-slide__img {
	transform: scale(1.025);
	transition: transform 7s ease-out;
}

.ecb-hero-carousel.is-enhanced .ecb-hero-slide.is-active .ecb-hero-slide__img {
	transform: scale(1);
}

.ecb-hero-slide__kicker {
	font-family: var(--ecb-font-body);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: #DFC18C;
}

.ecb-hero-slide__title {
	letter-spacing: -0.05em;
	line-height: 0.94;
}

/* Progress marks, not dots: the active slide is a wider bar. Width is the only
   thing that changes, so the row never reflows. */
.ecb-hero-dot {
	width: 24px;
	height: 6px;
	border-radius: 0;
	background-color: rgba(255, 255, 255, 0.42);
	transition: width var(--ecb-t-button) var(--ecb-ease),
	            background-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-hero-dot.is-active {
	width: 48px;
	background-color: #fff;
}

.ecb-hero-carousel .ecb-hero-dot:focus-visible,
.ecb-hero-carousel .ecb-hero-nav:focus-visible {
	outline: 3px solid rgba(255, 255, 255, 0.7);
	outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   56.11 Trust strip
   Divided cells on a raised ground, bounded top and bottom — the prototype's
   band. The column count follows the number of real items rather than being
   pinned at four, so the strip stays correct if the owner adds or removes one.
   -------------------------------------------------------------------------- */
.ecb-trust-grid {
	gap: 0;
	background-color: var(--ecb-p1-panel);
	border-top: 1px solid var(--ecb-p1-panel-border);
	border-bottom: 1px solid var(--ecb-p1-panel-border);
}

.ecb-trust-item {
	border-top: 0;
	border-left: 1px solid #E4D8D1;
	min-height: 96px;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: 20px 24px;
}

.ecb-trust-item:first-child {
	border-left: 0;
}

.ecb-trust-item h3 {
	font-size: 14px;
	letter-spacing: 0.01em;
}

.ecb-trust-item p {
	font-size: 13px;
	line-height: 1.6;
}

@media (max-width: 689px) {
	.ecb-trust-grid {
		grid-template-columns: 1fr 1fr;
		gap: 0;
	}
	.ecb-trust-item {
		border-left: 1px solid #E4D8D1;
		border-top: 1px solid #E4D8D1;
		padding: 16px 18px;
		min-height: 84px;
	}
	.ecb-trust-item:nth-child(odd) { border-left: 0; }
	.ecb-trust-item:nth-child(-n + 2) { border-top: 0; }
}

/* --------------------------------------------------------------------------
   56.12 Motion
   Two additions only: a small stagger so a grid resolves in sequence rather
   than as one block, and a hover lift measured in pixels rather than shadow.
   Both sit behind the existing reduced-motion switch in section 21.
   -------------------------------------------------------------------------- */
[data-ecb-reveal].ecb-reveal-armed > * {
	opacity: 0;
	transform: translateY(12px);
}

[data-ecb-reveal].is-revealed > * {
	opacity: 1;
	transform: none;
	transition: opacity 520ms var(--ecb-ease), transform 520ms var(--ecb-ease);
}

[data-ecb-reveal].is-revealed > :nth-child(2) { transition-delay: 70ms; }
[data-ecb-reveal].is-revealed > :nth-child(3) { transition-delay: 140ms; }
[data-ecb-reveal].is-revealed > :nth-child(4) { transition-delay: 210ms; }
[data-ecb-reveal].is-revealed > :nth-child(5) { transition-delay: 280ms; }
[data-ecb-reveal].is-revealed > :nth-child(6) { transition-delay: 350ms; }

/* A card rises 2px and its image drifts 2%. No shadow is added on hover —
   a shadow that appears on hover is the single loudest "template" tell. */
.ecb-cat-card,
.ecb-pick {
	transition: transform var(--ecb-t-button) var(--ecb-ease);
}

@media (hover: hover) {
	.ecb-cat-card:hover,
	.ecb-pick:hover {
		transform: translateY(-2px);
	}
	.ecb-cat-card:hover .ecb-cat-card__img,
	.ecb-pick:hover .ecb-pick__img {
		transform: scale(1.02);
	}
}

.ecb-cat-card__img,
.ecb-pick__img {
	transition: transform var(--ecb-t-image) var(--ecb-ease);
}

@media (prefers-reduced-motion: reduce) {
	[data-ecb-reveal].ecb-reveal-armed > *,
	[data-ecb-reveal].is-revealed > * {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
		transition-delay: 0ms !important;
	}
	.ecb-hero-carousel.is-enhanced .ecb-hero-slide__img,
	.ecb-hero-carousel.is-enhanced .ecb-hero-slide.is-active .ecb-hero-slide__img {
		transform: none !important;
		transition: none !important;
	}
	.ecb-cat-card:hover,
	.ecb-pick:hover,
	.ecb-cat-card:hover .ecb-cat-card__img,
	.ecb-pick:hover .ecb-pick__img {
		transform: none !important;
	}
}

/* --------------------------------------------------------------------------
   56.13 Overflow containment
   A sticky header and a full-bleed hero are the two things most likely to
   introduce a horizontal scrollbar, so the guard is explicit rather than
   assumed. `overflow-x: clip` is used in preference to `hidden` because
   `hidden` on a scroll container silently breaks `position: sticky`.
   -------------------------------------------------------------------------- */
/* Sections 49.2 and 51.1 both clip sideways overflow — 49.2 on `body`, 51.1 on
   `html`. Each was correct on its own; together they are what stopped the
   sticky header from ever sticking, and the interaction is worth spelling out
   because it is invisible in either rule alone.

   Only the ROOT element's overflow propagates to the viewport. While `html` is
   `visible`, body's value is the one that propagates, and body computes back to
   `visible`. Once 51.1 gave `html` a value of its own that stopped: html's clip
   propagates, and body keeps an overflow of its own. A box with one axis
   clipped and the other `visible` computes that `visible` to `auto` — so body
   silently became a 7800px-tall scroll container. `position: sticky` resolves
   against its nearest scrolling ancestor, which was then body rather than the
   viewport; body never scrolls, so the header scrolled away with the page.

   html's clip already protects the viewport, which is the point of both rules,
   so body's copy is redundant. Clearing it removes the second scroll container
   and hands sticky back to the viewport. Neither earlier section is edited —
   this resolves them rather than unpicking them. */
/* `html body` (0,0,2), not `body` (0,0,1): Blocksy sets `body { overflow-x:
   hidden }` in main.min.css, which is enqueued AFTER the child stylesheet, so
   an equal-specificity rule here loses on source order. That is also why
   49.2s body clip never actually applied — the computed value was Blocksy's
   `hidden` the whole time. */
html body {
	overflow: visible;
}

.ecb-hero-carousel,
.ecb-hero-carousel__viewport,
.ecb-trust-grid,
.ct-header [data-row="middle"],
.ct-header [data-row="bottom"] {
	max-width: 100%;
}

/* Long unbroken strings — an order id, an email, a URL in a policy page — are
   the other overflow source. They wrap anywhere; ordinary prose does not, so
   this is deliberately not applied globally. */
.ecb-break-any,
.ct-footer a[href^="mailto:"] {
	overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   56.14 Trust band placement
   The strip now sits directly under the hero, so it must read as part of the
   same plate rather than as the first content section. It gets no band padding
   of its own: the cells carry their own height, and the rules top and bottom
   do the separating.
   -------------------------------------------------------------------------- */
.ecb-trust-band {
	padding-top: 0;
	padding-bottom: 0;
}

.ecb-trust-band > .ecb-trust-grid {
	border-top: 0; /* the hero already ends in a hard edge */
}

/* Deliberately not revealed on scroll: it sits above the fold on most desktop
   viewports, and an element that animates in while already visible reads as a
   glitch rather than as polish. */
.ecb-trust-band [data-ecb-reveal] {
	opacity: 1;
	transform: none;
}

/* --------------------------------------------------------------------------
   56.15 Logo, sized to the row
   Section 35 caps the mark at 62px, which was right for the old 70px row and
   is 2px taller than the new one — the row would quietly grow to fit and the
   header would stop being the 60px the prototype specifies.

   The logo file is 800x336, so a 40px cap renders it 95px wide. That is close
   to the proportion the prototype gives its wordmark, and leaves 10px of air
   above and below inside the 60px row.
   -------------------------------------------------------------------------- */
.ct-header [data-id="logo"] img,
.site-logo-container .site-logo {
	max-height: 40px;
	max-width: 200px;
}

@media (max-width: 689.98px) {
	.ct-header [data-id="logo"] img,
	.site-logo-container .site-logo {
		max-height: 36px;
		max-width: 150px;
	}
}

/* --------------------------------------------------------------------------
   56.16 Sticky header vs the WordPress admin bar
   The admin bar is `position: fixed` and 32px tall, so a header resting at
   `top: 0` parks underneath it — invisible to visitors, but it hides the nav
   from every logged-in editor, which is precisely who reviews the site.

   The offset is pushed down by the admin bar's height, and only when WordPress
   has actually put `.admin-bar` on the body. Visitors keep the flush-to-top
   behaviour. The bar becomes 46px and stops being fixed below 783px, which is
   WordPress's own breakpoint, so the offset is dropped there to match.
   -------------------------------------------------------------------------- */
body.admin-bar #header.ct-header {
	top: calc(32px - var(--ecb-p1-announce-h));
}

@media screen and (max-width: 782px) {
	body.admin-bar #header.ct-header {
		top: calc(-1 * var(--ecb-p1-announce-h));
	}
}

/* ==========================================================================
   57. Version 9 — frozen design foundation

   The Version 9 handoff freezes an exact palette, type stack and geometry.
   This section supersedes the values sections 1 and 56 arrived at, rather than
   editing them in place: the earlier declarations stay readable as the record
   of how the design got here, and the cascade resolves to the frozen values
   because these come later at equal specificity.

   Where a frozen value already matched what we had (the 10-13px interface
   type, the 40px category row, the 64/80px band rhythm) nothing is repeated —
   only genuine differences appear below.
   ========================================================================== */

:root {
	/* ---- Frozen palette (01-IMPLEMENTATION-CONTRACT.md) ------------------ */
	--ecb-v9-bg: #FDFBF8;
	--ecb-v9-fg: #20171C;
	--ecb-v9-card: #FFFDFA;
	--ecb-v9-primary: #4B0F2A;
	--ecb-v9-action: #5A1231;
	--ecb-v9-accent: #C3A066;
	--ecb-v9-secondary: #EFE6DF;
	--ecb-v9-muted: #F4EDE7;
	--ecb-v9-muted-fg: #76646C;
	--ecb-v9-destructive: #A52A36;
	--ecb-v9-border: #DFD2CB;
	--ecb-v9-input: #D9CBC3;
	--ecb-v9-ring: #7A2949;
	--ecb-v9-radius: 0.55rem;

	/* The discount treatment is deliberately louder than the destructive
	   token: a markdown badge has to read as a markdown at 10px. */
	--ecb-v9-sale: #BD1735;

	/* ---- Frozen type ------------------------------------------------------
	   The reference resolves to Avenir Next / Iowan Old Style on Apple
	   hardware and to Arial / Georgia everywhere else. Noto Sans Bengali is
	   appended rather than substituted: it only ever matches Bengali
	   codepoints, so it cannot alter how Latin text renders, and without it
	   the Bangla policy copy loses its face. */
	--ecb-font-body: "Avenir Next", "Helvetica Neue", Arial, "Noto Sans Bengali", sans-serif;
	--ecb-font-heading: "Iowan Old Style", "Palatino Linotype", Georgia, "Times New Roman", "Noto Sans Bengali", serif;
	--ecb-font-bangla: "Noto Sans Bengali", "Avenir Next", "Helvetica Neue", Arial, sans-serif;

	--ecb-v9-body-size: 16px;
	--ecb-v9-body-lh: 1.55;

	/* ---- Frozen geometry -------------------------------------------------- */
	--ecb-container: 1440px;
	--ecb-p1-announce-h: 32px;   /* handoff: announcement minimum height */
	--ecb-p1-row1: 58px;         /* handoff: desktop primary header */
	--ecb-p1-row2: 40px;         /* unchanged - already frozen-correct */

	--ecb-v9-hero-min: 560px;

	/* Surfaces realigned onto the frozen ground. */
	--ecb-page: var(--ecb-v9-bg);
	--ecb-ivory: var(--ecb-v9-bg);
	--ecb-surface-sunken: var(--ecb-v9-muted);
	--ecb-ink: var(--ecb-v9-fg);
	--ecb-ink-muted: var(--ecb-v9-muted-fg);
	--ecb-plum: var(--ecb-v9-primary);
	--ecb-gold: var(--ecb-v9-accent);
	--ecb-sale: var(--ecb-v9-sale);
	--ecb-border: var(--ecb-v9-border);

	/* Panel tones follow the frozen card/border pair. */
	--ecb-p1-panel: var(--ecb-v9-card);
	--ecb-p1-panel-border: var(--ecb-v9-border);
	--ecb-p1-focus: rgba(122, 41, 73, 0.42);

	--ecb-radius-card: var(--ecb-v9-radius);
	--ecb-radius-ctl: calc(var(--ecb-v9-radius) - 2px);
}

/* --------------------------------------------------------------------------
   57.1 Base
   -------------------------------------------------------------------------- */
body {
	background-color: var(--ecb-v9-bg);
	color: var(--ecb-v9-fg);
	font-family: var(--ecb-font-body);
	font-size: var(--ecb-v9-body-size);
	line-height: var(--ecb-v9-body-lh);
}

::selection {
	background: var(--ecb-v9-action);
	color: #FFFAF7;
}

/* --------------------------------------------------------------------------
   57.2 Announcement bar
   The frozen 32px is a *minimum*, not a fixed height: on a narrow phone the
   longest message needs two lines, and clipping it would be worse than a
   taller bar. The sticky offset in 57.3 is measured from the same variable, so
   the two cannot drift apart.
   -------------------------------------------------------------------------- */
html [data-header*="type-1"] .ct-header [data-row*="top"] {
	--height: var(--ecb-p1-announce-h);
}

html [data-header*="type-1"] .ct-header [data-row*="top"] > div {
	min-height: var(--ecb-p1-announce-h);
	height: auto;
}

.ecb-rotator {
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.13em;
	text-transform: uppercase;
}

@media (min-width: 640px) {
	.ecb-rotator { font-size: 11px; }
}

/* --------------------------------------------------------------------------
   57.3 Sticky header

   #header carries position:relative and z-index:50 in Blocksy's main.min.css,
   which loads after this stylesheet; #header.ct-header is the lowest
   specificity that reliably wins. The negative offset parks the announcement
   above the viewport as the page scrolls, leaving the two navigation rows
   pinned - which is what the reference does.
   -------------------------------------------------------------------------- */
#header.ct-header {
	top: calc(-1 * var(--ecb-p1-announce-h));
}

body.admin-bar #header.ct-header {
	top: calc(32px - var(--ecb-p1-announce-h));
}

@media screen and (max-width: 782px) {
	body.admin-bar #header.ct-header {
		top: calc(-1 * var(--ecb-p1-announce-h));
	}
}

/* --------------------------------------------------------------------------
   57.4 Mega-menu column headings
   -------------------------------------------------------------------------- */
.ecb-megahead {
	margin: 0 0 10px;
	color: var(--ecb-p1-eyebrow);
	font-family: var(--ecb-font-body);
	font-size: var(--ecb-p1-eyebrow-size);
	font-weight: 700;
	letter-spacing: var(--ecb-p1-eyebrow-ls);
	text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   57.5 Four-action mobile dock

   Fixed to the bottom edge below the large breakpoint, exactly as the
   reference. The body gains matching bottom padding so the last section of
   every page clears it, and the existing floating support button lifts above
   it rather than sitting on top of the bag.
   -------------------------------------------------------------------------- */
.ecb-dock { display: none; }

@media (max-width: 1023.98px) {
	.ecb-dock {
		position: fixed;
		z-index: 60;
		right: 0;
		bottom: 0;
		left: 0;
		display: grid;
		grid-template-columns: repeat(4, 1fr);
		min-height: 4.25rem;
		border-top: 1px solid var(--ecb-v9-border);
		background: rgba(255, 253, 250, 0.96);
		box-shadow: 0 -12px 36px rgba(56, 16, 31, 0.09);
		backdrop-filter: blur(18px);
		-webkit-backdrop-filter: blur(18px);
	}

	.ecb-dock__item {
		position: relative;
		display: flex;
		flex-direction: column;
		gap: 3px;
		align-items: center;
		justify-content: center;
		min-height: 44px;
		color: #4F2938;
		text-decoration: none;
	}

	.ecb-dock__item.is-current,
	.ecb-dock__item:hover,
	.ecb-dock__item:focus-visible {
		color: var(--ecb-v9-action);
	}

	.ecb-dock__label {
		font-size: 9px;
		font-weight: 700;
		letter-spacing: 0.08em;
		text-transform: uppercase;
	}

	.ecb-dock__count {
		position: absolute;
		top: 0.55rem;
		right: calc(50% - 1.45rem);
		display: flex;
		width: 1rem;
		height: 1rem;
		align-items: center;
		justify-content: center;
		border-radius: 999px;
		background: var(--ecb-p1-badge);
		color: #fff;
		font-size: 0.58rem;
		font-weight: 700;
		line-height: 1;
	}

	/* An empty bag needs no badge - the reference only shows a live count. */
	.ecb-dock__count[data-count="0"] { display: none; }

	body { padding-bottom: 4.4rem; }

	.ecb-fab { bottom: calc(4.4rem + 1rem); }
}

/* --------------------------------------------------------------------------
   57.6 Support dock
   -------------------------------------------------------------------------- */
.ecb-fab__link {
	display: flex;
	gap: 12px;
	align-items: center;
	min-height: 44px;
	width: 100%;
	padding: 0 12px;
	border: 1px solid #E2D6CF;
	background: transparent;
	color: inherit;
	font-family: inherit;
	font-size: 14px;
	font-weight: 700;
	text-align: left;
	cursor: pointer;
}

.ecb-fab__link .ecb-brand-icon,
.ecb-fab__link svg {
	flex: 0 0 auto;
	color: var(--ecb-v9-ring);
}

.ecb-fab__link--copy[data-ecb-copied] { border-color: var(--ecb-v9-action); }

/* --------------------------------------------------------------------------
   57.7 Footer, Version 9
   -------------------------------------------------------------------------- */
.ecb-foot-social {
	display: flex;
	gap: 8px;
	margin-top: 20px;
}

.ecb-foot-social__btn {
	display: flex;
	width: 40px;
	height: 40px;
	align-items: center;
	justify-content: center;
	border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: 999px;
	color: inherit;
}

.ecb-foot-social__btn:hover,
.ecb-foot-social__btn:focus-visible {
	border-color: rgba(255, 255, 255, 0.5);
}

.ecb-footcol__links {
	display: grid;
	gap: 10px;
	margin-top: 4px;
}

.ecb-footcol__link {
	display: flex;
	gap: 12px;
	align-items: flex-start;
	font-size: 14px;
	line-height: 1.5;
	color: var(--ecb-p1-foot-link);
	text-decoration: none;
}

.ecb-footcol__link svg {
	flex: 0 0 auto;
	margin-top: 3px;
	opacity: 0.85;
}

.ecb-footcol__link:hover,
.ecb-footcol__link:focus-visible {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* --------------------------------------------------------------------------
   57.8 Brand marks
   Sized by the surrounding control; the mark itself never sets a colour, so it
   inherits the dark footer ink and the plum support panel alike.
   -------------------------------------------------------------------------- */
.ecb-brand-icon {
	display: block;
	flex: 0 0 auto;
}

/* --------------------------------------------------------------------------
   57.9 Motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	.ecb-dock { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* --------------------------------------------------------------------------
   57.10 Find Us

   Version 9 renames the shortcut from Visit Us to Find Us. Section 56 drew the
   map pin against .ecb-nav-visit; the rule is re-pointed here rather than
   edited there, so the two class names stay documented side by side and the
   glyph keeps working if the older class is ever reintroduced.
   -------------------------------------------------------------------------- */
.ct-header .ecb-nav-find > .ct-menu-link {
	display: inline-flex;
	align-items: center;
	gap: 6px;
}

.ct-header .ecb-nav-find > .ct-menu-link::before {
	content: "";
	width: 14px;
	height: 14px;
	flex: 0 0 14px;
	background-color: currentColor;
	-webkit-mask: var(--ecb-icon-pin) center / contain no-repeat;
	mask: var(--ecb-icon-pin) center / contain no-repeat;
}

/* Sale is the one shortcut that carries its own colour, as in the reference. */
.ct-header .ecb-nav-sale > .ct-menu-link {
	color: #A31432;
}

/* ==========================================================================
   58. Version 9 — homepage

   Section order, geometry and density from 04-VISUAL-PARITY-CHECKLIST.md.
   Every band renders from a shortcode reading live WooCommerce data; the rules
   below only give that output its shape.
   ========================================================================== */

/* Blocksy publishes the container width on :root in its compiled stylesheet,
   which loads after this file. html:root outranks a bare :root regardless of
   order, which is what makes the frozen 1440px actually take effect. */
html:root {
	--theme-normal-container-max-width: var(--ecb-container);
}

:root {
	--ecb-v9-gap: 16px;
	--ecb-v9-tile-lead: 460px;
	--ecb-v9-tile-small: 320px;
	--ecb-v9-occasion-h: 400px;
	--ecb-v9-scrim: linear-gradient(to top, rgba(0, 0, 0, 0.72) 0%, rgba(0, 0, 0, 0.05) 55%, transparent 100%);
	--ecb-v9-stories-bg: #2F0E1C;
	--ecb-v9-newin-bg: #F1E9E3;
	--ecb-v9-signature-bg: #F0E7E1;
	--ecb-v9-service-card: #FAF5F1;
}

/* --------------------------------------------------------------------------
   58.1 Band rhythm — 64px on a phone, 80px from the large breakpoint
   -------------------------------------------------------------------------- */
.ecb-v9-shopway,
.ecb-v9-newin,
.ecb-v9-occasion-section,
.ecb-v9-stories-section,
.ecb-v9-signature-section,
.ecb-v9-service-section {
	padding-block: var(--ecb-p1-band);
}

@media (min-width: 1024px) {
	.ecb-v9-shopway,
	.ecb-v9-newin,
	.ecb-v9-occasion-section,
	.ecb-v9-stories-section,
	.ecb-v9-signature-section,
	.ecb-v9-service-section {
		padding-block: var(--ecb-p1-band-lg);
	}
}

.ecb-v9-eyebrow {
	margin: 0;
	color: var(--ecb-v9-ring);
	font-family: var(--ecb-font-body);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.18em;
	text-transform: uppercase;
}

.ecb-v9-eyebrow--gold { color: #D7B678; }

.ecb-section-head--center { text-align: center; }

.ecb-section-head__lede {
	max-width: 28rem;
	font-size: 0.875rem;
	line-height: 1.6;
}

/* --------------------------------------------------------------------------
   58.2 Trust strip

   Four cells, so a phone shows two even rows. Three would leave the last item
   alone on a row of its own, which is the orphan the checklist calls out.
   -------------------------------------------------------------------------- */
.ecb-v9-trust {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	max-width: var(--ecb-container);
	margin-inline: auto;
	border-top: 1px solid var(--ecb-v9-border);
	border-bottom: 1px solid var(--ecb-v9-border);
	background: var(--ecb-v9-card);
}

.ecb-v9-trust__item {
	display: flex;
	gap: 12px;
	align-items: center;
	min-height: 96px;
	padding: 20px 16px;
	border-right: 1px solid #E4D8D1;
	border-bottom: 1px solid #E4D8D1;
}

.ecb-v9-trust__item:nth-child(2n) { border-right: 0; }
.ecb-v9-trust__item:nth-last-child(-n+2) { border-bottom: 0; }

.ecb-v9-trust__icon { color: var(--ecb-v9-ring); }
.ecb-v9-trust__body { display: block; }

.ecb-v9-trust__title {
	display: block;
	font-size: 0.875rem;
	font-weight: 700;
}

.ecb-v9-trust__note {
	display: block;
	margin-top: 2px;
	color: #826C75;
	font-size: 0.75rem;
}

@media (min-width: 768px) {
	.ecb-v9-trust { grid-template-columns: repeat(4, minmax(0, 1fr)); }
	.ecb-v9-trust__item { padding-inline: 24px; border-bottom: 0; border-right: 1px solid #E4D8D1; }
	.ecb-v9-trust__item:nth-child(2n) { border-right: 1px solid #E4D8D1; }
	.ecb-v9-trust__item:last-child { border-right: 0; }
}

/* --------------------------------------------------------------------------
   58.3 Shared tile chrome — collections, occasions and stories
   -------------------------------------------------------------------------- */
.ecb-v9-tile,
.ecb-v9-occasion,
.ecb-v9-story {
	position: relative;
	display: block;
	overflow: hidden;
	background: #E8DDD6;
	color: #fff;
	text-decoration: none;
}

.ecb-v9-tile__media {
	position: absolute;
	inset: 0;
	display: block;
}

.ecb-v9-tile__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform var(--ecb-t-image) var(--ecb-ease);
}

.ecb-v9-tile__scrim {
	position: absolute;
	inset: 0;
	display: block;
	background: var(--ecb-v9-scrim);
}

.ecb-v9-tile__body {
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	display: block;
	padding: 24px;
}

.ecb-v9-tile__eyebrow {
	display: block;
	color: rgba(255, 255, 255, 0.76);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.15em;
	text-transform: uppercase;
}

.ecb-v9-tile__row {
	display: flex;
	gap: 12px;
	align-items: center;
	justify-content: space-between;
	margin-top: 8px;
}

.ecb-v9-tile__title {
	display: block;
	font-family: var(--ecb-font-heading);
	font-size: 1.875rem;
	font-weight: 400;
	line-height: 1.1;
	letter-spacing: -0.035em;
}

.ecb-v9-tile__arrow { flex: 0 0 auto; transition: transform var(--ecb-t-button) var(--ecb-ease); }

@media (hover: hover) {
	.ecb-v9-tile:hover .ecb-v9-tile__img,
	.ecb-v9-occasion:hover .ecb-v9-tile__img,
	.ecb-v9-story:hover .ecb-v9-tile__img { transform: scale(1.035); }
	.ecb-v9-tile:hover .ecb-v9-tile__arrow { transform: translateX(4px); }
}

@media (min-width: 640px) {
	.ecb-v9-tile__body { padding: 32px; }
}

/* --------------------------------------------------------------------------
   58.4 Shop your way
   -------------------------------------------------------------------------- */
.ecb-v9-collections {
	display: grid;
	gap: var(--ecb-v9-gap);
	margin-top: 32px;
}

.ecb-v9-tile { min-height: var(--ecb-v9-tile-small); }
.ecb-v9-tile--lead,
.ecb-v9-tile--wide { min-height: var(--ecb-v9-tile-lead); }

@media (min-width: 640px) {
	.ecb-v9-collections { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
	.ecb-v9-collections { grid-template-columns: repeat(4, minmax(0, 1fr)); }
	.ecb-v9-tile--lead { grid-column: span 2; grid-row: span 2; }
	.ecb-v9-tile--wide { grid-column: span 2; }
}

/* --------------------------------------------------------------------------
   58.5 New in
   -------------------------------------------------------------------------- */
.ecb-v9-newin { background: var(--ecb-v9-newin-bg); }

/* --------------------------------------------------------------------------
   58.6 Shop by occasion
   -------------------------------------------------------------------------- */
.ecb-v9-occasions {
	display: grid;
	gap: var(--ecb-v9-gap);
	margin-top: 32px;
}

.ecb-v9-occasion { min-height: var(--ecb-v9-occasion-h); }

@media (min-width: 768px) {
	.ecb-v9-occasions { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
   58.7 ECB style stories
   -------------------------------------------------------------------------- */
.ecb-v9-stories-section {
	background: var(--ecb-v9-stories-bg);
	color: #fff;
}

.ecb-v9-stories-section .wp-block-heading,
.ecb-v9-stories-section .ecb-section-head__lede { color: #fff; }
.ecb-v9-stories-section .ecb-section-head__lede { color: rgba(255, 255, 255, 0.65); }

.ecb-v9-stories {
	display: grid;
	gap: var(--ecb-v9-gap);
	margin-top: 32px;
}

.ecb-v9-story {
	aspect-ratio: 3 / 5;
	background: #4B1B2D;
}

@media (min-width: 640px) {
	.ecb-v9-stories { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
   58.8 Desi Designer signature edit
   -------------------------------------------------------------------------- */
.ecb-v9-signature { display: grid; }

.ecb-v9-signature__media {
	position: relative;
	min-height: 480px;
	overflow: hidden;
	background: #EADFD8;
}

.ecb-v9-signature__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.ecb-v9-signature__copy {
	display: flex;
	align-items: center;
	padding: 48px 28px;
	background: var(--ecb-v9-signature-bg);
}

.ecb-v9-signature__title {
	margin: 12px 0 0;
	font-family: var(--ecb-font-heading);
	font-size: 2.25rem;
	font-weight: 400;
	line-height: 1.03;
	letter-spacing: -0.035em;
}

.ecb-v9-signature__text {
	max-width: 28rem;
	margin: 20px 0 0;
	color: #735D67;
	line-height: 1.7;
}

.ecb-v9-signature__cta {
	display: inline-flex;
	gap: 8px;
	align-items: center;
	min-height: 44px;
	margin-top: 28px;
	border-bottom: 1px solid var(--ecb-v9-action);
	color: var(--ecb-v9-action);
	font-size: 0.875rem;
	font-weight: 700;
	text-decoration: none;
}

@media (min-width: 768px) {
	.ecb-v9-signature { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.ecb-v9-signature__copy { padding: 48px 56px; }
}

/* --------------------------------------------------------------------------
   58.9 Customer guidance cards
   -------------------------------------------------------------------------- */
.ecb-v9-service {
	display: grid;
	gap: var(--ecb-v9-gap);
	max-width: 1200px;
	margin-inline: auto;
}

.ecb-v9-service__card {
	padding: 28px;
	border: 1px solid var(--ecb-v9-border);
	background: var(--ecb-v9-service-card);
}

.ecb-v9-service__icon { display: block; color: var(--ecb-v9-ring); }

.ecb-v9-service__title {
	margin: 24px 0 0;
	font-family: var(--ecb-font-heading);
	font-size: 1.5rem;
	font-weight: 400;
	line-height: 1.2;
	letter-spacing: -0.03em;
}

.ecb-v9-service__text {
	margin: 12px 0 0;
	color: #755F69;
	font-size: 0.875rem;
	line-height: 1.6;
}

@media (min-width: 768px) {
	.ecb-v9-service { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.ecb-v9-service__card { padding: 32px; }
}

/* --------------------------------------------------------------------------
   58.10 Final checkout CTA
   -------------------------------------------------------------------------- */
.ecb-v9-cta {
	padding-block: 40px;
	background: var(--ecb-v9-action);
	color: #FFFAF7;
}

.ecb-v9-cta .wp-block-heading {
	font-family: var(--ecb-font-heading);
	font-size: 1.5rem;
	font-weight: 400;
	letter-spacing: -0.03em;
	color: #FFFAF7;
}

.ecb-v9-cta p { color: rgba(255, 255, 255, 0.7); font-size: 0.875rem; }

/* --------------------------------------------------------------------------
   58.11 Hero — frozen minimum height
   -------------------------------------------------------------------------- */
.ecb-hero,
.ecb-hero__slide { min-height: var(--ecb-v9-hero-min); }

/* --------------------------------------------------------------------------
   58.12 Motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	.ecb-v9-tile__img,
	.ecb-v9-tile__arrow { transition: none; }

	.ecb-v9-tile:hover .ecb-v9-tile__img,
	.ecb-v9-occasion:hover .ecb-v9-tile__img,
	.ecb-v9-story:hover .ecb-v9-tile__img,
	.ecb-v9-tile:hover .ecb-v9-tile__arrow { transform: none; }
}

/* ==========================================================================
   59. Version 9 — catalogue

   Subcategory navigation, the Sale route and the Coming Soon state. Filter
   facets become single-open accordions, which is the reference's behaviour and
   what stops a phone screen filling with every facet at once.
   ========================================================================== */

/* --------------------------------------------------------------------------
   59.1 Button variants used by the Coming Soon state
   -------------------------------------------------------------------------- */
.ecb-btn--primary {
	background-color: var(--ecb-v9-action);
	border-color: var(--ecb-v9-action);
	color: #FFFAF7;
}

.ecb-btn--primary:hover {
	background-color: var(--ecb-v9-primary);
	border-color: var(--ecb-v9-primary);
	color: #FFFAF7;
}

.ecb-btn--ghost {
	background-color: transparent;
	border-color: var(--ecb-v9-input);
	color: var(--ecb-v9-action);
}

.ecb-btn--ghost:hover {
	background-color: var(--ecb-v9-secondary);
	border-color: var(--ecb-v9-action);
	color: var(--ecb-v9-action);
}

/* --------------------------------------------------------------------------
   59.2 Subcategory navigation

   A horizontal rail that scrolls on a phone rather than wrapping into a block
   of chips. The scrollbar is thin and the row keeps a stable gutter, so the
   rail does not jump when it becomes scrollable.
   -------------------------------------------------------------------------- */
.ecb-subnav {
	display: flex;
	gap: 8px;
	overflow-x: auto;
	margin-bottom: 20px;
	padding-bottom: 4px;
	scrollbar-width: thin;
	scrollbar-color: #B99CA7 transparent;
	-webkit-overflow-scrolling: touch;
}

.ecb-subnav__link {
	display: inline-flex;
	gap: 6px;
	align-items: center;
	flex: 0 0 auto;
	min-height: 36px;
	padding: 0 14px;
	border: 1px solid var(--ecb-v9-border);
	border-radius: 999px;
	background: var(--ecb-v9-card);
	color: var(--ecb-p1-nav-strong);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-decoration: none;
	white-space: nowrap;
}

.ecb-subnav__link:hover,
.ecb-subnav__link:focus-visible {
	border-color: var(--ecb-v9-ring);
	color: var(--ecb-v9-ring);
}

.ecb-subnav__link.is-active {
	border-color: var(--ecb-v9-action);
	background: var(--ecb-v9-action);
	color: #FFFAF7;
}

.ecb-subnav__count {
	color: inherit;
	font-size: 10px;
	font-weight: 700;
	opacity: 0.7;
}

/* --------------------------------------------------------------------------
   59.3 Coming Soon

   A real destination, not a dead end: the category is named, the reason is
   stated plainly, and both a Shop All route and real in-stock products follow.
   -------------------------------------------------------------------------- */
.ecb-v9-soon {
	max-width: var(--ecb-container);
	margin-inline: auto;
	padding-block: var(--ecb-p1-band);
	text-align: center;
}

.ecb-v9-soon .ecb-empty__lead {
	margin: 10px 0 0;
	font-family: var(--ecb-font-heading);
	font-size: var(--ecb-fs-h2);
	font-weight: 400;
	line-height: 1.15;
	letter-spacing: -0.03em;
}

.ecb-v9-soon .ecb-empty__text {
	max-width: 34rem;
	margin: 14px auto 0;
	color: var(--ecb-v9-muted-fg);
	font-size: 0.9375rem;
	line-height: 1.65;
}

.ecb-v9-soon__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	justify-content: center;
	margin-top: 28px;
}

.ecb-v9-soon__recs {
	margin-top: 56px;
	text-align: left;
}

.ecb-v9-soon__recs-title {
	margin: 0 0 20px;
	font-family: var(--ecb-font-body);
	font-size: var(--ecb-p1-eyebrow-size);
	font-weight: 700;
	letter-spacing: var(--ecb-p1-eyebrow-ls);
	text-transform: uppercase;
	color: var(--ecb-p1-eyebrow);
}

/* --------------------------------------------------------------------------
   59.4 Filter facets — single-open accordions

   Each facet is its own <details>, so it works with JavaScript disabled; the
   single-open rule is added by script. Closing one to open another keeps the
   panel short enough to use on a phone.
   -------------------------------------------------------------------------- */
.ecb-filters__panel .ecb-filter-widget {
	border-bottom: 1px solid var(--ecb-p1-panel-rule);
}

.ecb-facet__summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	min-height: 44px;
	cursor: pointer;
	list-style: none;
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.ecb-facet__summary::-webkit-details-marker { display: none; }

.ecb-facet__summary::after {
	content: "";
	width: 9px;
	height: 9px;
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: translateY(-2px) rotate(45deg);
	transition: transform var(--ecb-t-button) var(--ecb-ease);
}

.ecb-facet[open] > .ecb-filter-widget > .ecb-facet__summary::after { transform: translateY(2px) rotate(225deg); }

.ecb-facet > .ecb-filter-widget { padding-bottom: 16px; }

/* --------------------------------------------------------------------------
   59.5 Sale route
   -------------------------------------------------------------------------- */
.ecb-sale-note {
	display: flex;
	gap: 10px;
	align-items: center;
	margin-bottom: 20px;
	padding: 12px 16px;
	border: 1px solid var(--ecb-v9-border);
	background: var(--ecb-v9-card);
	font-size: 0.875rem;
}

.ecb-sale-note__badge {
	padding: 3px 8px;
	background: var(--ecb-v9-sale);
	color: #fff;
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

@media (prefers-reduced-motion: reduce) {
	.ecb-facet__summary::after { transition: none; }
}

/* ==========================================================================
   60. Version 9 — product cards and product page

   The wishlist heart, Compact Hybrid swatches, stock flags and the pre-order
   panel. The discount treatment is the one place the palette is allowed to
   shout: a markdown has to read as a markdown at 10px.
   ========================================================================== */

/* --------------------------------------------------------------------------
   60.1 Wishlist heart
   -------------------------------------------------------------------------- */
.ecb-heart {
	position: absolute;
	z-index: 3;
	top: 12px;
	right: 12px;
	display: flex;
	width: 40px;
	height: 40px;
	align-items: center;
	justify-content: center;
	border: 1px solid rgba(255, 255, 255, 0.75);
	border-radius: 999px;
	background: rgba(255, 253, 250, 0.94);
	color: var(--ecb-v9-action);
	cursor: pointer;
	box-shadow: 0 1px 3px rgba(33, 30, 32, 0.08);
	transition: background-color var(--ecb-t-button) var(--ecb-ease),
	            border-color var(--ecb-t-button) var(--ecb-ease),
	            color var(--ecb-t-button) var(--ecb-ease);
}

.ecb-heart.is-saved {
	border-color: var(--ecb-v9-action);
	background: var(--ecb-v9-action);
	color: #fff;
}

.ecb-heart[disabled] { opacity: 0.6; cursor: progress; }

/* The confirmation is a live region rather than a tooltip, so it is announced
   as well as seen. It is off-screen until a toggle actually happens. */
.ecb-heart__flash {
	position: absolute;
	right: calc(100% + 8px);
	padding: 4px 8px;
	border-radius: 3px;
	background: #2A2226;
	color: #fff;
	font-size: 10px;
	font-weight: 700;
	line-height: 1;
	white-space: nowrap;
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--ecb-t-color) var(--ecb-ease);
}

.ecb-heart[data-ecb-flash] .ecb-heart__flash { opacity: 1; }

.ecb-product-save {
	display: flex;
	gap: 10px;
	align-items: center;
	margin: 16px 0 0;
}

/* On the product page the heart sits in the flow rather than over an image. */
.ecb-product-save .ecb-heart {
	position: static;
	border-color: var(--ecb-v9-input);
}

.ecb-product-save__label {
	font-size: 0.8125rem;
	font-weight: 600;
	color: var(--ecb-v9-muted-fg);
}

/* --------------------------------------------------------------------------
   60.2 Compact Hybrid colour swatches
   -------------------------------------------------------------------------- */
.ecb-swatches {
	display: flex;
	gap: 5px;
	align-items: center;
	margin-top: 8px;
}

.ecb-swatches__dot {
	width: 14px;
	height: 14px;
	flex: 0 0 14px;
	border: 1px solid rgba(42, 22, 30, 0.18);
	border-radius: 0;
	background: var(--ecb-v9-muted);
}

.ecb-swatches__more {
	color: var(--ecb-v9-muted-fg);
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.04em;
}

/* --------------------------------------------------------------------------
   60.3 Stock flags
   -------------------------------------------------------------------------- */
.ecb-stockflag {
	position: absolute;
	z-index: 2;
	top: 58px;
	right: 12px;
	padding: 4px 9px;
	color: #fff;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.ecb-stockflag--out { background: #3B3236; }
.ecb-stockflag--preorder { background: #9A6A18; }

/* --------------------------------------------------------------------------
   60.4 Discount treatment

   Vivid red, everywhere a saving appears — card badge, price line, cart and
   checkout. The deeper brand maroon reads as furniture and gets ignored.
   -------------------------------------------------------------------------- */
.ecb-badge--sale,
.ecb-save-pct,
.ecb-discount {
	background: var(--ecb-v9-sale);
	color: #fff;
}

.ecb-price-save {
	color: var(--ecb-v9-sale);
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   60.5 Pre-order panel
   -------------------------------------------------------------------------- */
.ecb-preorder {
	margin: 20px 0 0;
	padding: 18px 20px;
	border: 1px solid var(--ecb-v9-border);
	background: var(--ecb-v9-card);
}

.ecb-preorder__title {
	margin: 0;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: #9A6A18;
}

.ecb-preorder__text {
	margin: 8px 0 16px;
	font-size: 0.875rem;
	line-height: 1.6;
	color: var(--ecb-v9-muted-fg);
}

.ecb-preorder .ecb-btn { min-height: 44px; font-size: 14px; }

/* --------------------------------------------------------------------------
   60.6 Selected colour readout
   -------------------------------------------------------------------------- */
.ecb-chosen-colour {
	display: flex;
	gap: 8px;
	align-items: baseline;
	margin: 0 0 10px;
	font-size: 0.8125rem;
}

.ecb-chosen-colour__label {
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	font-size: 10px;
	color: var(--ecb-v9-muted-fg);
}

.ecb-chosen-colour__value { font-weight: 600; }

/* --------------------------------------------------------------------------
   60.7 Motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	.ecb-heart,
	.ecb-heart__flash { transition: none; }
}

/* ==========================================================================
   61. Version 9 — checkout, account and supporting pages

   Passes 5 to 8. The district selector, the account summary, the wishlist page
   and the FAQ list.
   ========================================================================== */

/* --------------------------------------------------------------------------
   61.1 Area / District selector

   One control, and it is the widest thing in the billing block — it decides
   the delivery charge, so it should not look like an afterthought beside the
   postcode.
   -------------------------------------------------------------------------- */
.ecb-delivery-district select {
	width: 100%;
	min-height: 48px;
}

.ecb-delivery-district .description {
	margin-top: 6px;
	color: var(--ecb-v9-muted-fg);
	font-size: 0.8125rem;
	line-height: 1.5;
}

/* --------------------------------------------------------------------------
   61.2 Account summary
   -------------------------------------------------------------------------- */
.ecb-account-summary {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 12px;
	margin-bottom: 28px;
}

.ecb-account-stat {
	display: block;
	padding: 18px 16px;
	border: 1px solid var(--ecb-v9-border);
	background: var(--ecb-v9-card);
	color: inherit;
	text-align: center;
	text-decoration: none;
}

.ecb-account-stat:hover,
.ecb-account-stat:focus-visible { border-color: var(--ecb-v9-ring); }

.ecb-account-stat__value {
	display: block;
	font-family: var(--ecb-font-heading);
	font-size: 1.75rem;
	font-weight: 400;
	line-height: 1.1;
	color: var(--ecb-v9-action);
}

.ecb-account-stat__label {
	display: block;
	margin-top: 4px;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--ecb-v9-muted-fg);
}

@media (max-width: 480px) {
	/* Three stat tiles at 360px leave no room for the labels, so they stack
	   into a single readable column rather than shrinking the numbers. */
	.ecb-account-summary { grid-template-columns: 1fr; }
	.ecb-account-stat { display: flex; align-items: baseline; justify-content: space-between; text-align: left; }
	.ecb-account-stat__label { margin-top: 0; }
}

/* --------------------------------------------------------------------------
   61.3 Wishlist page
   -------------------------------------------------------------------------- */
.ecb-wishlist__count {
	margin: 0 0 20px;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--ecb-v9-muted-fg);
}

/* --------------------------------------------------------------------------
   61.4 FAQ
   -------------------------------------------------------------------------- */
.ecb-faq-item {
	padding: 22px 0;
	border-bottom: 1px solid var(--ecb-p1-panel-rule);
}

.ecb-faq-item h3 {
	margin: 0;
	font-family: var(--ecb-font-heading);
	font-size: 1.25rem;
	font-weight: 400;
	letter-spacing: -0.02em;
}

.ecb-faq-item p {
	margin: 8px 0 0;
	color: var(--ecb-v9-muted-fg);
	line-height: 1.65;
}

.ecb-lede {
	max-width: 38rem;
	font-size: 1.0625rem;
	line-height: 1.6;
	color: var(--ecb-v9-muted-fg);
}

/* ==========================================================================
   62. Version 9 — corrections found in the browser

   Defects that only show up once the frozen font stack is actually applied in
   a real browser. Kept separate from the sections they correct so the reason
   stays attached to the fix.
   ========================================================================== */

/* --------------------------------------------------------------------------
   62.1 Dropdown arrow

   Section 56 drew the reference's outbound arrow with content: "\2197".
   Version 9 moved the body stack to Avenir Next / Helvetica Neue / Arial, and
   none of those carries U+2197 — so every mega-menu row rendered a tofu box.

   Redrawn as an inline SVG mask, which cannot depend on font coverage. Same
   size, same position, same decorative status.
   -------------------------------------------------------------------------- */
:root {
	--ecb-icon-arrow-ne: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7'/%3E%3Cpath d='M8 7h9v9'/%3E%3C/svg%3E");
}

.ct-header .sub-menu > li > .ct-menu-link::after {
	content: "";
	width: 10px;
	height: 10px;
	flex: 0 0 10px;
	background-color: currentColor;
	-webkit-mask: var(--ecb-icon-arrow-ne) center / contain no-repeat;
	mask: var(--ecb-icon-arrow-ne) center / contain no-repeat;
}

/* --------------------------------------------------------------------------
   62.2 Announcement before the script runs

   The rotator is progressive enhancement: the server prints all four messages
   and the script promotes one. Until it runs, all four stacked and the
   announcement bar was four lines tall, which shoved the page down and then
   snapped back.

   Only the first message is shown until the script marks the rotator
   enhanced. With JavaScript off the visitor sees one accurate message rather
   than a stack — and the other three stay in the DOM for assistive tech.
   -------------------------------------------------------------------------- */
.ecb-rotator:not(.is-enhanced) > .ecb-rotator__item ~ .ecb-rotator__item {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* --------------------------------------------------------------------------
   62.3 Arrows in the homepage tiles

   Same reasoning as 62.1: these are written as → in the markup rather than as
   generated content, so they are given a face that definitely carries the
   glyph before the frozen stack is applied.
   -------------------------------------------------------------------------- */
.ecb-v9-tile__arrow,
.ecb-v9-signature__cta span[aria-hidden="true"] {
	font-family: "Segoe UI Symbol", "Apple Symbols", "Noto Sans Symbols 2", sans-serif;
	line-height: 1;
}

/* --------------------------------------------------------------------------
   62.4 Announcement stays one line

   Measured at 360px, the longest message wrapped and the bar grew to 38px
   while the sticky offset still assumed 32px — leaving a six-pixel sliver of
   the bar pinned above the navigation.

   The reference keeps the message on one line and lets the bar clip it, which
   is what makes the 32px a reliable offset. Matching that here means the
   sticky calculation can never drift from the rendered height.
   -------------------------------------------------------------------------- */
html [data-header*="type-1"] .ct-header [data-row*="top"] > div {
	overflow: hidden;
}

.ecb-rotator,
.ecb-rotator__item {
	white-space: nowrap;
}

/* Below the smallest breakpoint the gap between the two figures is the first
   thing that can go, before the text itself is clipped. */
@media (max-width: 400px) {
	.ecb-rotator { letter-spacing: 0.08em; }
}

/* --------------------------------------------------------------------------
   62.5 Section headings take the display face

   An earlier phase put section headings in the interface font. Version 9's
   reference marks every section heading with its display class, and the
   widening gap between a serif display voice and a small sans interface voice
   is what stops the page reading as a uniformly scaled template.
   -------------------------------------------------------------------------- */
.ecb-section-head h2,
.ecb-v9-shopway h2,
.ecb-v9-newin h2,
.ecb-v9-occasion-section h2,
.ecb-v9-stories-section h2,
.ecb-v9-service-section h2 {
	font-family: var(--ecb-font-heading);
	font-weight: 400;
	line-height: 1.1;
	letter-spacing: -0.035em;
}

/* --------------------------------------------------------------------------
   62.6 Eyebrow escapes the constrained content width

   Gutenberg's constrained layout gives a bare paragraph the narrow content
   size and centres it, so the eyebrow floated to the middle of the band while
   the heading beneath it stayed flush left. The eyebrow belongs to the
   heading, so it takes the heading's box.
   -------------------------------------------------------------------------- */
.ecb-section-head > .ecb-v9-eyebrow,
.ecb-section-head > .ecb-section-head__lede {
	max-width: none;
	margin-inline: 0;
}

.ecb-section-head--center > .ecb-v9-eyebrow {
	margin-inline: auto;
	text-align: center;
}

/* The section head is a row on wide screens: heading on the left, the
   "view all" link trailing on the right, as the reference lays it out. */
.ecb-section-head {
	display: flex;
	flex-direction: column;
	gap: 8px;
	align-items: flex-start;
	margin-bottom: 32px;
}

.ecb-section-head--center { align-items: center; }

.ecb-section-head h2 { margin: 0; }

.ecb-section-head__link {
	display: inline-flex;
	gap: 8px;
	align-items: center;
	min-height: 44px;
	color: var(--ecb-v9-action);
	font-size: 0.875rem;
	font-weight: 700;
	text-decoration: none;
}

@media (min-width: 640px) {
	.ecb-section-head {
		flex-direction: row;
		flex-wrap: wrap;
		align-items: flex-end;
		justify-content: space-between;
	}

	.ecb-section-head--center { flex-direction: column; align-items: center; }

	.ecb-section-head__group { display: grid; gap: 8px; }
}

/* --------------------------------------------------------------------------
   62.7 Section heads escape Gutenberg's constrained layout

   The block editor writes an inline rule that gives every direct child of a
   constrained group the narrow content size plus margin-inline:auto. Inside a
   section head that centred the eyebrow and the trailing link while the
   heading stayed flush left, which read as three unrelated fragments.

   :where() contributes no specificity, so the editor's rule is (0,1,0) and
   these are (0,2,0) — enough to win without !important.
   -------------------------------------------------------------------------- */
.ecb-section-head > :where(:not(.alignleft):not(.alignright):not(.alignfull)),
.ecb-section-head__group > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {
	max-width: none;
	margin-inline: 0;
}

.ecb-section-head__group { display: grid; gap: 6px; }

/* The trailing link is the only thing that should sit away from the heading. */
.ecb-section-head > p:last-child:not(.ecb-v9-eyebrow):not(.ecb-section-head__lede) {
	margin: 0;
}

@media (min-width: 640px) {
	.ecb-section-head > p:last-child:not(.ecb-v9-eyebrow):not(.ecb-section-head__lede) {
		text-align: right;
	}
}

/* Centred heads keep their own alignment. */
.ecb-section-head--center > .ecb-section-head__group { justify-items: center; text-align: center; }

/* --------------------------------------------------------------------------
   62.8 Undo the editor's auto margins inside a section head

   62.7 removed the constrained max-width, but the block editor also writes
   `margin-left: auto !important; margin-right: auto !important` on every
   direct child of a constrained group. Nothing without !important can beat
   that, so this is one of the few places the site uses it — narrowly scoped to
   section heads, and only to cancel a third-party !important rather than to
   win an argument with our own cascade.
   -------------------------------------------------------------------------- */
.ecb-section-head > *,
.ecb-section-head__group > * {
	margin-left: 0 !important;
	margin-right: 0 !important;
	max-width: none;
}

/* A centred head still centres — it just does it with the flex box rather
   than with auto margins the layout cannot see. */
.ecb-section-head--center,
.ecb-section-head--center > .ecb-section-head__group {
	justify-items: center;
	text-align: center;
}

/* The eyebrow is a short label, so the 60ch measure meant for prose does not
   apply to it or to the trailing link. */
.ecb-section-head p.ecb-v9-eyebrow,
.ecb-section-head > p:last-child {
	max-width: none;
}

/* --------------------------------------------------------------------------
   62.9 The head sits on one line

   With the constrained max-width removed the heading group grew to the full
   container, which pushed the trailing link onto its own row. The group sizes
   to its content instead, so heading and link share a baseline as they do in
   the reference — and still stack on a narrow screen.
   -------------------------------------------------------------------------- */
@media (min-width: 640px) {
	.ecb-section-head__group { flex: 0 1 auto; min-width: 0; }
	.ecb-section-head > p:last-child:not(.ecb-v9-eyebrow):not(.ecb-section-head__lede) { flex: 0 0 auto; }
	.ecb-section-head__lede { flex: 0 1 28rem; }
}

/* --------------------------------------------------------------------------
   62.10 Section head layout, stated deterministically

   Flex sizing kept giving the heading group the full container width, because
   .wp-block-group carries its own width rules. A two-column grid states the
   intent directly — heading takes the free space, the trailing link takes only
   what it needs — and cannot be talked out of it by a block style.
   -------------------------------------------------------------------------- */
@media (min-width: 640px) {
	.ecb-section-head {
		display: grid;
		grid-template-columns: 1fr auto;
		align-items: end;
		column-gap: 24px;
	}

	.ecb-section-head--center {
		display: block;
		text-align: center;
	}

	.ecb-section-head--center > .ecb-section-head__group { display: block; }
}

/* --------------------------------------------------------------------------
   62.11 Announcement on a narrow screen

   Measured at 390px: the bar is 315px wide and the longest message renders
   430px, so holding it to one line clipped "Order support on WhatsApp &
   Messenger" mid-word. The frozen 32px is a minimum, not a fixed height, so
   the honest answer is to let the bar take a second line below the small
   breakpoint rather than truncate a message the customer is meant to read.

   The sticky offset reads the same token, so it follows the taller bar exactly
   and no sliver of the announcement can stay pinned above the navigation.
   -------------------------------------------------------------------------- */
@media (max-width: 639.98px) {
	:root { --ecb-p1-announce-h: 44px; }

	.ecb-rotator,
	.ecb-rotator__item {
		white-space: normal;
	}

	.ecb-rotator {
		line-height: 1.35;
		text-align: center;
	}

	/* Each message is absolutely positioned once the rotator is enhanced, so
	   the bar must reserve the height of the tallest rather than the current
	   one — otherwise it would resize on every rotation. */
	html [data-header*="type-1"] .ct-header [data-row*="top"] > div {
		align-items: center;
		padding-block: 4px;
	}
}

/* --------------------------------------------------------------------------
   62.12 The rotator sizes to its widest message

   The original rotator kept the active message in flow and the rest absolute,
   so the container was only ever as wide as whichever message happened to be
   showing. A longer message then overflowed a box sized for a shorter one.

   Stacking every message in a single grid cell makes the container as wide and
   as tall as the widest and tallest message, so nothing is measured against
   the wrong box and the bar never resizes as messages rotate.
   -------------------------------------------------------------------------- */
.ecb-rotator {
	display: grid;
	place-items: center;
	max-width: 100%;
}

.ecb-rotator > .ecb-rotator__item {
	position: relative;
	grid-area: 1 / 1;
	max-width: 100%;
}

/* Before the script runs only the first message is shown, so the others must
   not contribute height to the grid. */
.ecb-rotator:not(.is-enhanced) > .ecb-rotator__item ~ .ecb-rotator__item {
	position: absolute;
}

@media (max-width: 639.98px) {
	/* min-height already reserves the two-line box; extra padding would make
	   the rendered bar taller than the token the sticky offset reads. */
	html [data-header*="type-1"] .ct-header [data-row*="top"] > div {
		padding-block: 0;
	}
}

/* --------------------------------------------------------------------------
   62.13 Rotator items share one grid cell

   62.12 set the grid but section 23's `.ecb-rotator.is-enhanced
   .ecb-rotator__item` (0,3,0) kept the inactive messages absolutely
   positioned, so the container was still only as wide as the active one and
   the three longer messages were cut off at desktop widths.

   Stacking them in a single grid cell instead of taking them out of flow
   gives the container the width and height of the widest message. The
   cross-fade is unchanged — it was never the positioning that produced it.
   -------------------------------------------------------------------------- */
.ecb-rotator.is-enhanced > .ecb-rotator__item {
	position: relative;
	inset: auto;
	grid-area: 1 / 1;
}

.ecb-rotator.is-enhanced > .ecb-rotator__item.is-active {
	position: relative;
}

/* --------------------------------------------------------------------------
   62.14 Hero carousel dots get a real hit area

   The dots are deliberately thin — the reference draws them as 6px bars — but
   a 24x20 hit area is below a comfortable touch target. The bar keeps its
   size; the button grows an invisible pad around it so a thumb can land on it.
   -------------------------------------------------------------------------- */
.ecb-hero-dot {
	position: relative;
}

.ecb-hero-dot::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 44px;
	height: 44px;
	transform: translate(-50%, -50%);
}

/* --------------------------------------------------------------------------
   62.15 Mobile dock item keeps its badge inside its column

   The bag badge is absolutely placed from the column's centre. At 360px the
   column is 90px, so the badge sat a few pixels proud of it. Anchoring it to
   the icon rather than to the column keeps it inside whatever width the column
   ends up being.
   -------------------------------------------------------------------------- */
.ecb-dock__item--bag { overflow: hidden; }

@media (max-width: 1023.98px) {
	.ecb-dock__count {
		right: auto;
		left: 50%;
		margin-left: 2px;
		transform: translateX(0);
	}
}

/* ==========================================================================
   63. Version 9 — occasion routes

   Occasions are shop queries, exactly as the frozen prototype links them. This
   names the occasion above the grid so the heading matches the label the
   customer clicked rather than the term underneath it.
   ========================================================================== */
.ecb-occasion-head {
	margin-bottom: 24px;
	padding-bottom: 20px;
	border-bottom: 1px solid var(--ecb-v9-border);
}

.ecb-occasion-head__title {
	margin: 6px 0 0;
	font-family: var(--ecb-font-heading);
	font-size: var(--ecb-fs-h2);
	font-weight: 400;
	line-height: 1.1;
	letter-spacing: -0.03em;
}

.ecb-occasion-head__note {
	margin: 6px 0 16px;
	color: var(--ecb-v9-muted-fg);
	font-size: 0.9375rem;
}

.ecb-occasion-head .ecb-subnav { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   63.1 Hero and full-bleed bands reach the viewport edge

   Measured at 1440: the hero rendered 1296px wide with 65px gutters, while the
   prototype's hero runs edge to edge. The block carries alignfull, but the
   theme's content container still bounds it, so the band is pulled back out to
   the full viewport width the way the reference lays it out.

   100vw would overshoot by the scrollbar width and reintroduce horizontal
   overflow, so the width is taken from the document element instead.
   -------------------------------------------------------------------------- */
.ecb-hero-wrap,
.ecb-trust-band,
.ecb-v9-stories-section,
.ecb-v9-cta {
	width: 100%;
	max-width: none;
	margin-inline: 0;
}

/* The hero itself is the band, so it fills whatever the band gives it. */
.ecb-hero-wrap > .ecb-hero-carousel,
.ecb-hero-carousel {
	max-width: none;
	margin-inline: 0;
}

/* --------------------------------------------------------------------------
   63.2 Full-bleed bands: cancel the editor's auto margins

   The hero sat 1296px wide inside a 1425px band because the block editor
   applies `margin-left/right: auto !important` to every child of a constrained
   group. Removing the max-width alone was not enough — the auto margins still
   centred a box the browser had already sized to the container.

   Scoped to the four bands the reference runs edge to edge.
   -------------------------------------------------------------------------- */
.ecb-hero-wrap > .ecb-hero-carousel,
.ecb-trust-band > .ecb-v9-trust,
.ecb-v9-stories-section > .ecb-v9-stories,
.ecb-v9-cta > * {
	margin-left: 0 !important;
	margin-right: 0 !important;
	max-width: none;
	width: 100%;
}

/* The trust grid still respects the frozen 1440 content maximum; it is the
   hairline dividers that should reach the edge, not the text. */
.ecb-trust-band > .ecb-v9-trust {
	max-width: var(--ecb-container);
	margin-inline: auto !important;
}

/* 63.3 The stories band is full-bleed but its grid is not: the reference keeps
   the three panels inside the container so they do not touch the edge. */
.ecb-v9-stories-section > .ecb-v9-stories {
	max-width: var(--ecb-container);
	margin-inline: auto !important;
	padding-inline: clamp(20px, 4vw, 40px);
}

/* --------------------------------------------------------------------------
   63.4 Hero typography, to the frozen scale

   Measured against the prototype at 1440: our headline rendered 56px at weight
   600 where the reference sets clamp(2.8rem, 5.2vw, 4.7rem) at weight 400 —
   74.9px at that width. The gap made the hero read as a smaller, heavier
   version of the same design rather than the same design.

   The kicker was 16px against the reference's 12px, which is what made the
   whole block feel loose.
   -------------------------------------------------------------------------- */
.ecb-hero-slide__title {
	font-family: var(--ecb-font-heading);
	font-size: clamp(2.8rem, 5.2vw, 4.7rem);
	font-weight: 400;
	line-height: 0.94;
	letter-spacing: -0.045em;
	max-width: 37.5rem;
}

.ecb-hero-slide__kicker {
	font-family: var(--ecb-font-body);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: #DFC18C;
}

.ecb-hero-slide__text {
	max-width: 32rem;
	font-size: 1rem;
	line-height: 1.75;
	color: rgba(255, 255, 255, 0.78);
}

/* The copy block sits against the left edge of the container, as the reference
   lays it out, rather than centred in the band. */
.ecb-hero-slide__inner {
	max-width: var(--ecb-container);
	margin-inline: auto;
	padding-inline: clamp(20px, 4vw, 40px);
}

/* ==========================================================================
   64. Version 9 — visual parity corrections

   Values taken from the reference source, not estimated: header gutters
   px-4 / sm:px-7 / lg:px-10, hero min-height 560, hero controls as one bar
   with dots left and transport right, product cards with no add-to-cart.
   ========================================================================== */

/* --------------------------------------------------------------------------
   64.1 Header geometry

   The reference pads the header 16 / 28 / 40px rather than using the site
   container's gutter, which is what made our header read wider and looser
   than the prototype's at every width.
   -------------------------------------------------------------------------- */
html [data-header*="type-1"] .ct-header [data-row] > div > .ct-container,
html [data-header*="type-1"] .ct-header [data-row] > .ct-container {
	max-width: var(--ecb-container);
	padding-inline: 16px;
}

@media (min-width: 640px) {
	html [data-header*="type-1"] .ct-header [data-row] > div > .ct-container,
	html [data-header*="type-1"] .ct-header [data-row] > .ct-container { padding-inline: 28px; }
}

@media (min-width: 1024px) {
	html [data-header*="type-1"] .ct-header [data-row] > div > .ct-container,
	html [data-header*="type-1"] .ct-header [data-row] > .ct-container { padding-inline: 40px; }
}

/* The real logo stays; only its bounding box is constrained so the 58px row
   holds the prototype's proportions. */
html .ct-header [data-id="logo"] .site-logo-container img,
html .ct-header [data-id="logo"] img {
	max-height: 34px;
	max-width: 168px;
	width: auto;
	height: auto;
}

@media (max-width: 689.98px) {
	html .ct-header [data-id="logo"] .site-logo-container img,
	html .ct-header [data-id="logo"] img { max-height: 30px; max-width: 132px; }
}

/* --------------------------------------------------------------------------
   64.2 Cart: icon and count only

   The reference shows a bag glyph with an 18px count badge. The running total
   beside it is Blocksy's, not the prototype's, and it is the widest thing in
   the header actions row.
   -------------------------------------------------------------------------- */
.ct-header [data-id="cart"] .ct-label,
.ct-header [data-id="cart"] .ct-amount,
.ct-header [data-id="cart"] .woocommerce-Price-amount {
	display: none;
}

.ct-header [data-id="cart"] .ct-cart-item {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
}

.ct-header [data-id="cart"] .ct-icon-container {
	position: static;
}

.ct-header [data-id="cart"] .ct-dynamic-count-cart {
	position: absolute;
	top: -2px;
	right: -2px;
	display: flex;
	width: 18px;
	height: 18px;
	align-items: center;
	justify-content: center;
	border-radius: 999px;
	background: var(--ecb-p1-badge);
	color: #fff;
	font-size: 10px;
	font-weight: 700;
	line-height: 1;
}

/* An empty bag carries no badge in the reference. */
.ct-header [data-id="cart"] .ct-dynamic-count-cart[data-count="0"] { display: none; }

/* --------------------------------------------------------------------------
   64.3 Hero — frozen geometry
   -------------------------------------------------------------------------- */
.ecb-hero-carousel,
.ecb-hero-slide {
	min-height: var(--ecb-v9-hero-min);
}

/* Left-to-right scrim, as the reference draws it. Ours ran bottom-to-top,
   which is why the photograph read flat behind the copy. */
.ecb-hero-slide__scrim {
	background: linear-gradient(90deg,
		rgba(26, 8, 16, 0.92) 0%,
		rgba(36, 11, 22, 0.64) 42%,
		rgba(36, 11, 22, 0.14) 72%,
		rgba(20, 6, 12, 0.28) 100%);
}

.ecb-hero-slide__inner {
	display: flex;
	align-items: flex-end;
	min-height: var(--ecb-v9-hero-min);
	max-width: var(--ecb-container);
	margin-inline: auto;
	padding: 80px 20px;
}

@media (min-width: 640px) { .ecb-hero-slide__inner { padding-inline: 32px; } }

@media (min-width: 1024px) {
	.ecb-hero-slide__inner {
		align-items: center;
		padding-inline: 40px;
		padding-bottom: 56px;
	}
}

.ecb-hero-slide__inner > * { max-width: 40.625rem; }

.ecb-hero-slide__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin-top: 28px;
}

.ecb-hero-cta {
	display: inline-flex;
	gap: 8px;
	align-items: center;
	min-height: 48px;
	padding-inline: 20px;
	font-size: 0.875rem;
	font-weight: 700;
	text-decoration: none;
	border: 1px solid transparent;
}

.ecb-hero-cta--primary { background: #FFFAF6; color: #431027; }
.ecb-hero-cta--primary:hover { background: #fff; color: #431027; }

.ecb-hero-cta--ghost {
	border-color: rgba(255, 255, 255, 0.52);
	background: rgba(0, 0, 0, 0.1);
	color: #fff;
	backdrop-filter: blur(4px);
	-webkit-backdrop-filter: blur(4px);
}

.ecb-hero-cta--ghost:hover { background: rgba(255, 255, 255, 0.1); color: #fff; }

.ecb-hero-cta__arrow {
	width: 15px;
	height: 15px;
	background-color: currentColor;
	-webkit-mask: var(--ecb-icon-arrow-right) center / contain no-repeat;
	mask: var(--ecb-icon-arrow-right) center / contain no-repeat;
}

:root {
	--ecb-icon-arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='m13 6 6 6-6 6'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   64.4 Hero control bar — dots left, transport right
   -------------------------------------------------------------------------- */
.ecb-hero-bar {
	position: absolute;
	inset-inline: 0;
	bottom: 24px;
	z-index: 3;
	display: flex;
	gap: 16px;
	align-items: center;
	justify-content: space-between;
	max-width: var(--ecb-container);
	margin-inline: auto;
	padding-inline: 20px;
}

@media (min-width: 640px) { .ecb-hero-bar { padding-inline: 32px; } }
@media (min-width: 1024px) { .ecb-hero-bar { padding-inline: 40px; } }

.ecb-hero-dots {
	position: static;
	display: flex;
	gap: 8px;
	align-items: center;
	transform: none;
}

.ecb-hero-dot {
	width: 24px;
	height: 6px;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: rgba(255, 255, 255, 0.42);
	cursor: pointer;
	transition: width var(--ecb-t-button) var(--ecb-ease), background-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-hero-dot:hover { background: rgba(255, 255, 255, 0.7); }
.ecb-hero-dot.is-active { width: 48px; background: #fff; }

.ecb-hero-transport { display: flex; gap: 8px; align-items: center; }

.ecb-hero-ctl {
	display: flex;
	width: 44px;
	height: 44px;
	align-items: center;
	justify-content: center;
	border: 1px solid rgba(255, 255, 255, 0.35);
	border-radius: 999px;
	background: rgba(0, 0, 0, 0.15);
	color: #fff;
	cursor: pointer;
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
}

.ecb-hero-ctl--solid { border-color: #fff; background: #fff; color: #431027; }

.ecb-hero-ctl__arrow {
	width: 16px;
	height: 16px;
	background-color: currentColor;
	-webkit-mask: var(--ecb-icon-arrow-right) center / contain no-repeat;
	mask: var(--ecb-icon-arrow-right) center / contain no-repeat;
}

.ecb-hero-ctl__arrow--prev { transform: rotate(180deg); }

.ecb-hero-ctl__pause,
.ecb-hero-ctl__play {
	width: 14px;
	height: 14px;
	background-color: currentColor;
}

.ecb-hero-ctl__pause {
	-webkit-mask: var(--ecb-icon-pause) center / contain no-repeat;
	mask: var(--ecb-icon-pause) center / contain no-repeat;
}

.ecb-hero-ctl__play {
	display: none;
	-webkit-mask: var(--ecb-icon-play) center / contain no-repeat;
	mask: var(--ecb-icon-play) center / contain no-repeat;
}

.ecb-hero-carousel.is-paused .ecb-hero-ctl__pause { display: none; }
.ecb-hero-carousel.is-paused .ecb-hero-ctl__play { display: block; }

:root {
	--ecb-icon-pause: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Crect x='6' y='4' width='4' height='16' rx='1'/%3E%3Crect x='14' y='4' width='4' height='16' rx='1'/%3E%3C/svg%3E");
	--ecb-icon-play: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M7 4.5v15l13-7.5z'/%3E%3C/svg%3E");
}

/* The old edge arrows are gone from the markup; neutralise any leftover rule. */
.ecb-hero-nav { display: none; }

/* --------------------------------------------------------------------------
   64.5 Product cards — the reference's card, not WooCommerce's

   The prototype's card carries no add-to-cart control: the whole media area is
   the link, and a "View piece" bar rises on hover. Selling controls belong on
   the product page, where the variation choice actually lives.
   -------------------------------------------------------------------------- */
.woocommerce ul.products li.product .button,
.woocommerce ul.products li.product .added_to_cart,
.ecb-product-shortcode ul.products li.product .button,
.ecb-product-shortcode ul.products li.product .added_to_cart {
	display: none;
}

.woocommerce ul.products li.product a img,
.ecb-product-shortcode ul.products li.product a img {
	aspect-ratio: 4 / 5;
	object-fit: cover;
	background: #EEE4DE;
	margin-bottom: 0;
}

.woocommerce ul.products li.product .woocommerce-loop-product__title,
.ecb-product-shortcode ul.products li.product .woocommerce-loop-product__title {
	min-height: 2.5rem;
	padding-top: 4px;
	font-family: var(--ecb-font-body);
	font-size: 0.875rem;
	font-weight: 600;
	line-height: 1.25rem;
	letter-spacing: 0;
}

.woocommerce ul.products li.product .price,
.ecb-product-shortcode ul.products li.product .price {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	align-items: baseline;
	margin-top: 4px;
	font-size: 0.875rem;
	color: var(--ecb-v9-action);
	font-weight: 700;
}

.woocommerce ul.products li.product .price del,
.ecb-product-shortcode ul.products li.product .price del {
	color: #9A878F;
	font-size: 0.75rem;
	font-weight: 400;
	opacity: 1;
}

.woocommerce ul.products li.product .price ins,
.ecb-product-shortcode ul.products li.product .price ins {
	background: none;
	text-decoration: none;
	font-weight: 700;
}

/* The saving, in the vivid red reserved for markdowns. */
.ecb-price-off {
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--ecb-v9-sale);
}

/* Discount badge, top-left of the media. */
.ecb-card-badge {
	position: absolute;
	z-index: 2;
	left: 12px;
	top: 12px;
	padding: 4px 10px;
	background: var(--ecb-v9-sale);
	color: #fff;
	font-size: 10px;
	font-weight: 800;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

/* "View piece" bar, rising on hover as the reference does. */
.ecb-card-view {
	position: absolute;
	z-index: 2;
	inset-inline: 12px;
	bottom: 12px;
	display: flex;
	gap: 8px;
	align-items: center;
	justify-content: space-between;
	min-height: 44px;
	padding-inline: 16px;
	background: rgba(255, 253, 250, 0.94);
	color: var(--ecb-v9-action);
	font-size: 0.75rem;
	font-weight: 700;
	opacity: 0;
	transform: translateY(12px);
	pointer-events: none;
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	box-shadow: 0 10px 24px rgba(47, 14, 28, 0.14);
	transition: opacity 300ms var(--ecb-ease), transform 300ms var(--ecb-ease);
}

@media (hover: hover) {
	li.product:hover .ecb-card-view { opacity: 1; transform: translateY(0); }
}

.ecb-card-view__arrow {
	width: 15px;
	height: 15px;
	background-color: currentColor;
	-webkit-mask: var(--ecb-icon-arrow-ne) center / contain no-repeat;
	mask: var(--ecb-icon-arrow-ne) center / contain no-repeat;
}

/* Category eyebrow above the title. */
.ecb-card-eyebrow {
	display: block;
	margin-top: 12px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: #8A6F79;
}

@media (prefers-reduced-motion: reduce) {
	.ecb-hero-dot,
	.ecb-card-view { transition: none; }
	.ecb-card-view { transform: none; }
}

/* --------------------------------------------------------------------------
   64.6 Hero copy stacks

   The reference's hero flex holds a single copy column. Ours holds four
   siblings, so `display: flex` laid the kicker, headline, paragraph and
   buttons side by side across the band. They stack, and the flex box is used
   only for the vertical placement the reference asks for: bottom-aligned on a
   phone, centred from the large breakpoint.
   -------------------------------------------------------------------------- */
.ecb-hero-slide__inner {
	flex-direction: column;
	align-items: flex-start;
	justify-content: flex-end;
}

@media (min-width: 1024px) {
	.ecb-hero-slide__inner { justify-content: center; }
}

.ecb-hero-slide__inner > * { width: 100%; }

.ecb-hero-slide__kicker { margin: 0 0 12px; }
.ecb-hero-slide__title { margin: 0; }
.ecb-hero-slide__text { margin: 20px 0 0; }

/* The logo needs a little more presence than the 34px cap gave it while still
   fitting the 58px row. */
html .ct-header [data-id="logo"] .site-logo-container img,
html .ct-header [data-id="logo"] img {
	max-height: 40px;
	max-width: 190px;
}

/* --------------------------------------------------------------------------
   64.7 Band rhythm

   Measured on the live page: every band carried an extra 24px above it from
   the editor's content spacing, and three of them were getting 36px of top
   padding from the older .ecb-section ladder instead of the frozen 64/80.

   The reference butts its bands together and lets each one's own padding do
   the spacing, so the stray margin goes and the padding is stated once, here,
   at a specificity the older rules cannot beat.
   -------------------------------------------------------------------------- */
.entry-content > .ecb-hero-wrap,
.entry-content > .ecb-trust-band,
.entry-content > .ecb-v9-shopway,
.entry-content > .ecb-v9-newin,
.entry-content > .ecb-v9-occasion-section,
.entry-content > .ecb-v9-stories-section,
.entry-content > .ecb-v9-signature-section,
.entry-content > .ecb-v9-service-section,
.entry-content > .ecb-v9-cta {
	margin-block: 0;
}

.entry-content > .ecb-v9-shopway,
.entry-content > .ecb-v9-newin,
.entry-content > .ecb-v9-occasion-section,
.entry-content > .ecb-v9-stories-section,
.entry-content > .ecb-v9-signature-section,
.entry-content > .ecb-v9-service-section {
	padding-block: var(--ecb-p1-band);
}

@media (min-width: 1024px) {
	.entry-content > .ecb-v9-shopway,
	.entry-content > .ecb-v9-newin,
	.entry-content > .ecb-v9-occasion-section,
	.entry-content > .ecb-v9-stories-section,
	.entry-content > .ecb-v9-signature-section,
	.entry-content > .ecb-v9-service-section {
		padding-block: var(--ecb-p1-band-lg);
	}
}

/* The trust strip sits flush under the hero, as the reference places it. */
.entry-content > .ecb-trust-band { padding-block: 0; }

/* Outer gutters match the header's, so bands and navigation line up. */
.ecb-v9-shopway,
.ecb-v9-newin,
.ecb-v9-occasion-section,
.ecb-v9-signature-section,
.ecb-v9-service-section {
	padding-inline: 20px;
}

@media (min-width: 640px) {
	.ecb-v9-shopway,
	.ecb-v9-newin,
	.ecb-v9-occasion-section,
	.ecb-v9-signature-section,
	.ecb-v9-service-section { padding-inline: 32px; }
}

@media (min-width: 1024px) {
	.ecb-v9-shopway,
	.ecb-v9-newin,
	.ecb-v9-occasion-section,
	.ecb-v9-signature-section,
	.ecb-v9-service-section { padding-inline: 40px; }
}

/* Inner content still caps at the frozen 1440. */
.ecb-v9-shopway > *,
.ecb-v9-newin > *,
.ecb-v9-occasion-section > *,
.ecb-v9-signature-section > *,
.ecb-v9-service-section > * {
	max-width: var(--ecb-container);
	margin-inline: auto;
}

/* --------------------------------------------------------------------------
   64.8 The V9 bands opt out of the older section seam

   `.ecb-section + .ecb-section:not(.ecb-section--surface)` (0,3,0) tightened
   adjacent sections to a 26-36px seam. That ladder predates Version 9, whose
   bands each carry their own 64/80 padding, so the seam was quietly halving
   the top of three of them. These selectors are (0,3,1) and win.
   -------------------------------------------------------------------------- */
.entry-content > .ecb-section.ecb-v9-shopway,
.entry-content > .ecb-section.ecb-v9-newin,
.entry-content > .ecb-section.ecb-v9-occasion-section,
.entry-content > .ecb-section.ecb-v9-stories-section,
.entry-content > .ecb-section.ecb-v9-signature-section,
.entry-content > .ecb-section.ecb-v9-service-section {
	padding-block: var(--ecb-p1-band);
}

@media (min-width: 1024px) {
	.entry-content > .ecb-section.ecb-v9-shopway,
	.entry-content > .ecb-section.ecb-v9-newin,
	.entry-content > .ecb-section.ecb-v9-occasion-section,
	.entry-content > .ecb-section.ecb-v9-stories-section,
	.entry-content > .ecb-section.ecb-v9-signature-section,
	.entry-content > .ecb-section.ecb-v9-service-section {
		padding-block: var(--ecb-p1-band-lg);
	}
}

/* --------------------------------------------------------------------------
   64.9 Selected colour reads as part of the Colour label

   The value is appended to the row's own label — "Colour: Plum" — so there is
   one heading per attribute rather than a stray third one above the form.
   -------------------------------------------------------------------------- */
.variations label .ecb-chosen-colour__value {
	font-weight: 600;
	text-transform: none;
	letter-spacing: 0;
	color: var(--ecb-v9-action);
}

/* --------------------------------------------------------------------------
   64.10 Gallery thumbnails

   Blocksy prints the gallery with its slider disabled, so every image was
   stacked and the thumbnail pills did nothing. The script wires them; this
   shows one image at a time once it has, and leaves the stacked fallback
   alone when it has not.
   -------------------------------------------------------------------------- */
.woocommerce-product-gallery.ecb-gallery-ready .flexy-items > .flexy-item {
	display: none;
}

.woocommerce-product-gallery.ecb-gallery-ready .flexy-items > .flexy-item.is-active {
	display: block;
}

.woocommerce-product-gallery.ecb-gallery-ready .flexy-pills li {
	cursor: pointer;
	border: 2px solid transparent;
	transition: border-color var(--ecb-t-color) var(--ecb-ease);
}

.woocommerce-product-gallery.ecb-gallery-ready .flexy-pills li.active {
	border-color: var(--ecb-v9-ring);
}

.woocommerce-product-gallery.ecb-gallery-ready .flexy-pills li:focus-visible {
	outline: 3px solid var(--ecb-p1-focus);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.woocommerce-product-gallery.ecb-gallery-ready .flexy-pills li { transition: none; }
}

/* --------------------------------------------------------------------------
   64.11 Account is an icon, as in the reference

   The "MY ACCOUNT" label wrapped to two lines and was the widest thing in the
   header actions row. The reference shows a person glyph with an accessible
   name and no visible text. The label is moved off-screen rather than removed,
   so it still names the control for a screen reader.
   -------------------------------------------------------------------------- */
.ct-header [data-id="account"] .ct-label {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.ct-header [data-id="account"] .ct-account-item {
	display: flex;
	width: 40px;
	height: 40px;
	align-items: center;
	justify-content: center;
}

/* ==========================================================================
   65. Version 9 — catalogue hero and heading block

   Values from components/page-hero.tsx: compact band 260px, left-to-right
   scrim from #210712/96 through #35101f/72 to /16, a hairline along the
   bottom edge, and the copy bottom-aligned with 32px of clearance.
   ========================================================================== */
.ecb-v9-pagehero {
	position: relative;
	overflow: hidden;
	min-height: 260px;
	background: #2A0A18;
	color: #fff;
}

.ecb-v9-pagehero__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0.7;
}

.ecb-v9-pagehero__scrim {
	position: absolute;
	inset: 0;
	background: linear-gradient(to right,
		rgba(33, 7, 18, 0.96) 0%,
		rgba(53, 16, 31, 0.72) 50%,
		rgba(53, 16, 31, 0.16) 100%);
}

/* The hairline the reference draws along the bottom edge. */
.ecb-v9-pagehero::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	height: 1px;
	background: rgba(255, 255, 255, 0.25);
}

.ecb-v9-pagehero__inner {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	min-height: 260px;
	max-width: var(--ecb-container);
	margin-inline: auto;
	padding: 0 20px 32px;
}

@media (min-width: 640px) { .ecb-v9-pagehero__inner { padding-inline: 32px; } }
@media (min-width: 1024px) { .ecb-v9-pagehero__inner { padding-inline: 40px; } }

.ecb-v9-pagehero__eyebrow {
	margin: 0;
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: #E1C697;
}

.ecb-v9-pagehero__title {
	margin: 8px 0 0;
	max-width: 42rem;
	font-family: var(--ecb-font-heading);
	font-size: 1.875rem;
	font-weight: 400;
	line-height: 1.02;
	letter-spacing: -0.03em;
	color: #fff;
}

@media (min-width: 640px) { .ecb-v9-pagehero__title { font-size: 2.25rem; } }

.ecb-v9-pagehero__text {
	max-width: 36rem;
	margin: 16px 0 0;
	font-size: 0.875rem;
	line-height: 1.5rem;
	color: rgba(255, 255, 255, 0.78);
}

@media (min-width: 640px) { .ecb-v9-pagehero__text { font-size: 1rem; } }

/* --------------------------------------------------------------------------
   65.1 Catalogue heading block
   -------------------------------------------------------------------------- */
.ecb-v9-cathead {
	display: flex;
	flex-direction: column;
	gap: 20px;
	justify-content: space-between;
	padding-bottom: 24px;
	margin-bottom: 28px;
	border-bottom: 1px solid var(--ecb-v9-border);
}

@media (min-width: 768px) {
	.ecb-v9-cathead { flex-direction: row; align-items: flex-end; }
}

.ecb-v9-cathead__title {
	margin: 8px 0 0;
	font-family: var(--ecb-font-heading);
	font-size: 1.875rem;
	font-weight: 400;
	line-height: 1.1;
	letter-spacing: -0.03em;
	color: #35101F;
}

@media (min-width: 640px) { .ecb-v9-cathead__title { font-size: 2.25rem; } }

.ecb-v9-cathead__count {
	margin: 8px 0 0;
	font-size: 0.875rem;
	color: #7A6570;
}

/* The archive's own page title is replaced by the hero, so hide the duplicate. */
.woocommerce-products-header,
.ecb-v9-pagehero + .woocommerce-products-header { display: none; }

/* --------------------------------------------------------------------------
   65.2 One title per catalogue page

   Our editorial band carries the h1, so Blocksy's own page-title hero
   duplicated it — "Shop all" over the photograph, then "Shop" again with a
   breadcrumb underneath. The theme band is removed on catalogue routes only;
   every other page keeps it.

   The h1 is ours, so nothing is lost to a screen reader or to SEO.
   -------------------------------------------------------------------------- */
.woocommerce-shop .hero-section,
.tax-product_cat .hero-section,
.post-type-archive-product .hero-section {
	display: none;
}

/* The reference carries no breadcrumb on a catalogue route — the hero names
   the page and the category rail handles lateral movement. It stays on the
   product page, where the reference does show one. */
.woocommerce-shop .ecb-archive-crumb,
.tax-product_cat .ecb-archive-crumb,
.post-type-archive-product .ecb-archive-crumb {
	display: none;
}

/* ==========================================================================
   66. Version 9 — Contact and Find Us
   ========================================================================== */
.ecb-v9-contact-actions,
.ecb-v9-reach-band { padding-block: 40px; }

@media (min-width: 1024px) {
	.ecb-v9-contact-actions,
	.ecb-v9-reach-band { padding-block: 56px; }
}

.ecb-v9-actions,
.ecb-v9-reach {
	display: grid;
	gap: 16px;
	max-width: 1160px;
	margin-inline: auto;
	padding-inline: 20px;
}

@media (min-width: 640px) {
	.ecb-v9-actions, .ecb-v9-reach { padding-inline: 32px; }
}

@media (min-width: 768px) {
	.ecb-v9-actions { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.ecb-v9-reach { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
	.ecb-v9-actions, .ecb-v9-reach { padding-inline: 40px; }
}

/* --------------------------------------------------------------------------
   66.1 Action cards
   -------------------------------------------------------------------------- */
.ecb-v9-action {
	display: block;
	padding: 24px;
	border: 1px solid var(--ecb-v9-border);
	background: var(--ecb-v9-card);
	color: inherit;
	font: inherit;
	text-align: left;
	text-decoration: none;
	cursor: pointer;
	transition: border-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-v9-action:hover,
.ecb-v9-action:focus-visible { border-color: var(--ecb-v9-ring); }

.ecb-v9-action__icon { display: block; color: var(--ecb-v9-ring); }

.ecb-v9-action__label {
	display: block;
	margin-top: 20px;
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: #896F79;
}

.ecb-v9-action__title {
	display: block;
	margin-top: 8px;
	font-family: var(--ecb-font-heading);
	font-size: 1.5rem;
	font-weight: 400;
	line-height: 1.15;
	letter-spacing: -0.02em;
}

.ecb-v9-action__note {
	display: block;
	margin-top: 8px;
	font-size: 0.875rem;
	color: #715B65;
}

.ecb-v9-action--copy[data-ecb-copied] { border-color: var(--ecb-v9-action); }

/* --------------------------------------------------------------------------
   66.2 Find Us band
   -------------------------------------------------------------------------- */
.ecb-v9-findus-band {
	padding-block: 40px;
	border-top: 1px solid var(--ecb-v9-border);
	border-bottom: 1px solid var(--ecb-v9-border);
	background: #F2E9E3;
	scroll-margin-top: 120px;
}

@media (min-width: 1024px) { .ecb-v9-findus-band { padding-block: 56px; } }

.ecb-v9-findus {
	display: grid;
	overflow: hidden;
	max-width: 1160px;
	margin-inline: auto;
	border: 1px solid #D8CBC4;
	background: var(--ecb-v9-card);
	scroll-margin-top: 120px;
}

@media (min-width: 1024px) {
	.ecb-v9-findus { grid-template-columns: 0.82fr 1.18fr; }
}

.ecb-v9-findus__panel {
	display: flex;
	align-items: center;
	padding: 28px;
}

@media (min-width: 640px) { .ecb-v9-findus__panel { padding: 36px; } }

.ecb-v9-findus__title {
	margin: 8px 0 0;
	font-family: var(--ecb-font-heading);
	font-size: 1.875rem;
	font-weight: 400;
	line-height: 1.1;
	letter-spacing: -0.03em;
	color: #38101F;
}

.ecb-v9-findus__text {
	margin: 16px 0 0;
	font-size: 0.875rem;
	line-height: 1.5rem;
	color: #715B65;
}

.ecb-v9-findus__note {
	margin: 8px 0 0;
	font-size: 0.8125rem;
	color: var(--ecb-v9-muted-fg);
}

.ecb-v9-findus__actions {
	display: grid;
	gap: 8px;
	margin-top: 24px;
}

.ecb-v9-findus__actions .ecb-btn { gap: 8px; min-height: 48px; font-size: 0.875rem; }

.ecb-v9-findus__map {
	min-height: 360px;
	background: #E6DDD7;
}

.ecb-v9-findus__map iframe {
	display: block;
	width: 100%;
	height: 100%;
	min-height: 360px;
	border: 0;
}

/* --------------------------------------------------------------------------
   66.3 Reach cards
   -------------------------------------------------------------------------- */
.ecb-v9-reach__card {
	display: flex;
	gap: 16px;
	align-items: flex-start;
	padding: 24px;
	border: 1px solid var(--ecb-v9-border);
	background: var(--ecb-v9-card);
}

.ecb-v9-reach__icon { flex: 0 0 auto; margin-top: 2px; color: var(--ecb-v9-ring); }
.ecb-v9-reach__title { margin: 0; font-size: 0.9375rem; font-weight: 700; }

.ecb-v9-reach__note {
	margin: 8px 0 0;
	font-size: 0.875rem;
	line-height: 1.5rem;
	color: #715B65;
}

.ecb-v9-reach__social { display: flex; gap: 8px; margin-top: 16px; }

.ecb-v9-reach__social-btn {
	display: flex;
	width: 40px;
	height: 40px;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--ecb-v9-border);
	border-radius: 999px;
	color: var(--ecb-v9-ring);
}

.ecb-v9-reach__social-btn:hover,
.ecb-v9-reach__social-btn:focus-visible {
	border-color: var(--ecb-v9-ring);
	background: var(--ecb-v9-secondary);
}

/* The Contact page carries our editorial hero, so the theme's title band goes. */
.page-id-198 .hero-section { display: none; }

@media (prefers-reduced-motion: reduce) {
	.ecb-v9-action { transition: none; }
}

/* Three reach cards fit a three-column row from the medium breakpoint. */
@media (min-width: 768px) {
	.ecb-v9-reach { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ==========================================================================
   67. Version 9 — account shell
   ========================================================================== */
.woocommerce-account .woocommerce {
	max-width: 1180px;
	margin-inline: auto;
	padding-inline: 20px;
}

@media (min-width: 640px) { .woocommerce-account .woocommerce { padding-inline: 32px; } }
@media (min-width: 1024px) { .woocommerce-account .woocommerce { padding-inline: 40px; } }

.ecb-v9-account-head {
	display: flex;
	flex-direction: column;
	gap: 16px;
	justify-content: space-between;
	padding-bottom: 24px;
	margin-bottom: 28px;
	border-bottom: 1px solid var(--ecb-v9-border);
}

@media (min-width: 640px) {
	.ecb-v9-account-head { flex-direction: row; align-items: flex-end; }
}

.ecb-v9-account-head__title {
	margin: 8px 0 0;
	font-family: var(--ecb-font-heading);
	font-size: 1.875rem;
	font-weight: 400;
	line-height: 1.1;
	letter-spacing: -0.03em;
	color: #38101F;
}

@media (min-width: 640px) { .ecb-v9-account-head__title { font-size: 2.25rem; } }

.ecb-v9-account-head__note {
	margin: 8px 0 0;
	font-size: 0.875rem;
	color: #755F69;
}

.ecb-v9-account-head__avatar {
	display: flex;
	width: 44px;
	height: 44px;
	flex: 0 0 44px;
	align-items: center;
	justify-content: center;
	border-radius: 999px;
	background: #EFE3E8;
	color: var(--ecb-v9-action);
}

/* --------------------------------------------------------------------------
   67.1 Overview cards
   -------------------------------------------------------------------------- */
.ecb-v9-account-cards {
	display: grid;
	gap: 16px;
	margin-bottom: 32px;
}

@media (min-width: 640px) { .ecb-v9-account-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .ecb-v9-account-cards { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.ecb-v9-account-card {
	display: block;
	padding: 20px;
	border: 1px solid var(--ecb-v9-border);
	background: var(--ecb-v9-card);
	color: inherit;
	text-decoration: none;
	transition: border-color var(--ecb-t-color) var(--ecb-ease);
}

.ecb-v9-account-card:hover,
.ecb-v9-account-card:focus-visible { border-color: var(--ecb-v9-ring); }

.ecb-v9-account-card__icon { display: block; color: var(--ecb-v9-ring); }

.ecb-v9-account-card__label {
	display: block;
	margin-top: 16px;
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: #826A74;
}

.ecb-v9-account-card__value {
	display: block;
	margin-top: 4px;
	font-family: var(--ecb-font-heading);
	font-size: 1.5rem;
	font-weight: 400;
	line-height: 1.1;
	font-variant-numeric: tabular-nums;
}

.ecb-v9-account-card__addr {
	display: block;
	margin-top: 4px;
	font-size: 0.875rem;
	font-weight: 700;
	line-height: 1.35;
}

/* --------------------------------------------------------------------------
   67.2 Two-column layout with the navigation as a rail
   -------------------------------------------------------------------------- */
@media (min-width: 768px) {
	.woocommerce-account .woocommerce-MyAccount-navigation { width: 220px; }
	.woocommerce-account .woocommerce-MyAccount-content { width: calc(100% - 252px); }
}

.woocommerce-MyAccount-navigation ul li a {
	display: flex;
	align-items: center;
	min-height: 44px;
	padding-inline: 12px;
}

/* The account page carries its own header, so the theme's title band goes. */
.woocommerce-account .hero-section { display: none; }

/* ==========================================================================
   68. Version 9 — motion system

   The interaction layer: hero video, hover states, and scroll reveals. Every
   rule here is additive — remove the whole section and the page is still
   complete, just still. Everything is disabled under prefers-reduced-motion at
   the end of the section rather than rule by rule.
   ========================================================================== */

/* --------------------------------------------------------------------------
   68.1 Hero video

   The video sits over the still, which is its own poster, and fades in only
   once it is genuinely playing. That way a slow start shows the photograph
   rather than a black rectangle.
   -------------------------------------------------------------------------- */
.ecb-hero-slide__video {
	position: absolute;
	inset: 0;
	z-index: 1;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
	transition: opacity 900ms var(--ecb-ease);
	pointer-events: none;
}

.ecb-hero-slide__video.is-playing { opacity: 1; }

/* The scrim and copy stay above the video. */
.ecb-hero-slide__scrim { z-index: 2; }
.ecb-hero-slide__inner { position: relative; z-index: 3; }
.ecb-hero-bar { z-index: 4; }

/* --------------------------------------------------------------------------
   68.2 Card and tile hover

   One idea, applied consistently: the image drifts closer, the surface lifts a
   little, and the label reveals. Nothing rotates, nothing bounces.
   -------------------------------------------------------------------------- */
@media (hover: hover) {
	.woocommerce ul.products li.product a img,
	.ecb-product-shortcode ul.products li.product a img {
		transition: transform 700ms var(--ecb-ease);
	}

	.woocommerce ul.products li.product:hover a img,
	.ecb-product-shortcode ul.products li.product:hover a img {
		transform: scale(1.035);
	}

	/* The media box has to clip, or the scaled image spills over the card. */
	.woocommerce ul.products li.product a,
	.ecb-product-shortcode ul.products li.product a {
		overflow: hidden;
	}

	.ecb-v9-tile__title,
	.ecb-v9-tile__eyebrow {
		transition: transform 500ms var(--ecb-ease);
	}

	.ecb-v9-tile:hover .ecb-v9-tile__title,
	.ecb-v9-occasion:hover .ecb-v9-tile__title,
	.ecb-v9-story:hover .ecb-v9-tile__title {
		transform: translateY(-2px);
	}

	/* Scrim deepens slightly so the label stays legible as the image brightens. */
	.ecb-v9-tile__scrim { transition: opacity 500ms var(--ecb-ease); }
	.ecb-v9-tile:hover .ecb-v9-tile__scrim,
	.ecb-v9-occasion:hover .ecb-v9-tile__scrim,
	.ecb-v9-story:hover .ecb-v9-tile__scrim { opacity: 0.88; }

	.ecb-v9-action,
	.ecb-v9-account-card,
	.ecb-v9-service__card,
	.ecb-v9-reach__card {
		transition: border-color var(--ecb-t-color) var(--ecb-ease),
		            transform var(--ecb-t-button) var(--ecb-ease),
		            box-shadow var(--ecb-t-button) var(--ecb-ease);
	}

	.ecb-v9-action:hover,
	.ecb-v9-account-card:hover,
	.ecb-v9-service__card:hover {
		transform: translateY(-2px);
		box-shadow: 0 12px 28px rgba(47, 14, 28, 0.08);
	}

	/* Buttons and links shift their arrow rather than their whole box. */
	.ecb-hero-cta__arrow,
	.ecb-section-head__link span,
	.ecb-v9-signature__cta span {
		transition: transform var(--ecb-t-button) var(--ecb-ease);
	}

	.ecb-hero-cta:hover .ecb-hero-cta__arrow,
	.ecb-section-head__link:hover span,
	.ecb-v9-signature__cta:hover span {
		transform: translateX(4px);
	}

	.ecb-v9-tile:hover .ecb-v9-tile__arrow { transform: translateX(4px); }
}

/* --------------------------------------------------------------------------
   68.3 Scroll reveal

   Bands rise a little as they enter. The stagger is small and capped at five
   steps: past that it stops reading as one movement and starts reading as a
   queue the visitor has to wait for.
   -------------------------------------------------------------------------- */
/* Scoped to .ecb-reveal-armed, the class the script adds once it has an
   IntersectionObserver to reveal with. Hiding on [data-ecb-reveal] alone
   would leave the content invisible for good with JavaScript off, or on a
   browser without IO — the attribute is in the markup, the class is not. */
.ecb-reveal-armed {
	opacity: 0;
	transform: translateY(18px);
	transition: opacity 700ms var(--ecb-ease), transform 700ms var(--ecb-ease);
}

.ecb-reveal-armed.is-revealed {
	opacity: 1;
	transform: none;
}

/* Children of a revealed grid follow in sequence. */
.ecb-reveal-armed.is-revealed > *:nth-child(1) { transition-delay: 0ms; }
.ecb-reveal-armed.is-revealed > *:nth-child(2) { transition-delay: 70ms; }
.ecb-reveal-armed.is-revealed > *:nth-child(3) { transition-delay: 140ms; }
.ecb-reveal-armed.is-revealed > *:nth-child(4) { transition-delay: 210ms; }
.ecb-reveal-armed.is-revealed > *:nth-child(n+5) { transition-delay: 280ms; }

/* --------------------------------------------------------------------------
   68.4 Header on scroll

   The header tightens once the page moves, which is what makes the two rows
   read as one bar rather than as a stack that never changes.
   -------------------------------------------------------------------------- */
#header.ct-header {
	transition: box-shadow var(--ecb-t-color) var(--ecb-ease),
	            background-color var(--ecb-t-color) var(--ecb-ease);
}

body.is-scrolled #header.ct-header {
	box-shadow: 0 8px 28px rgba(47, 14, 28, 0.08);
}

/* --------------------------------------------------------------------------
   68.5 Reduced motion

   One place, everything off. The page keeps every state it can reach — it
   simply arrives there without travelling.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	.ecb-hero-slide__video { display: none; }

	.ecb-reveal-armed,
	.ecb-reveal-armed.is-revealed,
	.ecb-reveal-armed.is-revealed > * {
		opacity: 1;
		transform: none;
		transition: none;
		transition-delay: 0ms;
	}

	.woocommerce ul.products li.product a img,
	.ecb-product-shortcode ul.products li.product a img,
	.ecb-v9-tile__title,
	.ecb-v9-tile__eyebrow,
	.ecb-v9-tile__scrim,
	.ecb-v9-action,
	.ecb-v9-account-card,
	.ecb-v9-service__card,
	.ecb-v9-reach__card,
	.ecb-hero-cta__arrow,
	.ecb-section-head__link span,
	.ecb-v9-signature__cta span,
	#header.ct-header {
		transition: none;
	}

	.woocommerce ul.products li.product:hover a img,
	.ecb-product-shortcode ul.products li.product:hover a img,
	.ecb-v9-tile:hover .ecb-v9-tile__title,
	.ecb-v9-occasion:hover .ecb-v9-tile__title,
	.ecb-v9-story:hover .ecb-v9-tile__title,
	.ecb-v9-action:hover,
	.ecb-v9-account-card:hover,
	.ecb-v9-service__card:hover,
	.ecb-hero-cta:hover .ecb-hero-cta__arrow,
	.ecb-section-head__link:hover span,
	.ecb-v9-signature__cta:hover span,
	.ecb-v9-tile:hover .ecb-v9-tile__arrow {
		transform: none;
		box-shadow: none;
	}
}

/* --------------------------------------------------------------------------
   68.6 Print, and the last-resort visibility guarantee

   Armed elements are invisible until the script reveals them. Print never runs
   the observer, so without this a printed page would come out with its middle
   missing. The rule is stated in CSS as well as JS because print can be
   triggered in ways no script sees.
   -------------------------------------------------------------------------- */
@media print {
	.ecb-reveal-armed,
	.ecb-reveal-armed > * {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}

	.ecb-hero-slide__video { display: none; }
}
